Ray Milkey
Committed by Gerrit Code Review

REST API to create flows

Change-Id: I5d001782249c0eab249d7aa857ae465da95b5955
Showing 22 changed files with 2180 additions and 500 deletions
...@@ -35,6 +35,7 @@ import org.onosproject.net.Path; ...@@ -35,6 +35,7 @@ import org.onosproject.net.Path;
35 import org.onosproject.net.Port; 35 import org.onosproject.net.Port;
36 import org.onosproject.net.driver.Driver; 36 import org.onosproject.net.driver.Driver;
37 import org.onosproject.net.flow.FlowEntry; 37 import org.onosproject.net.flow.FlowEntry;
38 +import org.onosproject.net.flow.FlowRule;
38 import org.onosproject.net.flow.TrafficSelector; 39 import org.onosproject.net.flow.TrafficSelector;
39 import org.onosproject.net.flow.TrafficTreatment; 40 import org.onosproject.net.flow.TrafficTreatment;
40 import org.onosproject.net.flow.criteria.Criterion; 41 import org.onosproject.net.flow.criteria.Criterion;
...@@ -83,6 +84,7 @@ public class CodecManager implements CodecService { ...@@ -83,6 +84,7 @@ public class CodecManager implements CodecService {
83 registerCodec(Intent.class, new IntentCodec()); 84 registerCodec(Intent.class, new IntentCodec());
84 registerCodec(ConnectivityIntent.class, new ConnectivityIntentCodec()); 85 registerCodec(ConnectivityIntent.class, new ConnectivityIntentCodec());
85 registerCodec(FlowEntry.class, new FlowEntryCodec()); 86 registerCodec(FlowEntry.class, new FlowEntryCodec());
87 + registerCodec(FlowRule.class, new FlowRuleCodec());
86 registerCodec(TrafficTreatment.class, new TrafficTreatmentCodec()); 88 registerCodec(TrafficTreatment.class, new TrafficTreatmentCodec());
87 registerCodec(TrafficSelector.class, new TrafficSelectorCodec()); 89 registerCodec(TrafficSelector.class, new TrafficSelectorCodec());
88 registerCodec(Instruction.class, new InstructionCodec()); 90 registerCodec(Instruction.class, new InstructionCodec());
......
...@@ -15,43 +15,14 @@ ...@@ -15,43 +15,14 @@
15 */ 15 */
16 package org.onosproject.codec.impl; 16 package org.onosproject.codec.impl;
17 17
18 -import java.util.EnumMap;
19 -
20 import org.onosproject.codec.CodecContext; 18 import org.onosproject.codec.CodecContext;
21 import org.onosproject.codec.JsonCodec; 19 import org.onosproject.codec.JsonCodec;
22 -import org.onosproject.net.OchSignal;
23 import org.onosproject.net.flow.criteria.Criterion; 20 import org.onosproject.net.flow.criteria.Criterion;
24 -import org.onosproject.net.flow.criteria.EthCriterion;
25 -import org.onosproject.net.flow.criteria.EthTypeCriterion;
26 -import org.onosproject.net.flow.criteria.IPCriterion;
27 -import org.onosproject.net.flow.criteria.IPDscpCriterion;
28 -import org.onosproject.net.flow.criteria.IPEcnCriterion;
29 -import org.onosproject.net.flow.criteria.IPProtocolCriterion;
30 -import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
31 -import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
32 -import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
33 -import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
34 -import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
35 -import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
36 -import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
37 -import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
38 -import org.onosproject.net.flow.criteria.MetadataCriterion;
39 -import org.onosproject.net.flow.criteria.MplsCriterion;
40 -import org.onosproject.net.flow.criteria.OchSignalCriterion;
41 -import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
42 -import org.onosproject.net.flow.criteria.PortCriterion;
43 -import org.onosproject.net.flow.criteria.SctpPortCriterion;
44 -import org.onosproject.net.flow.criteria.TcpPortCriterion;
45 -import org.onosproject.net.flow.criteria.UdpPortCriterion;
46 -import org.onosproject.net.flow.criteria.VlanIdCriterion;
47 -import org.onosproject.net.flow.criteria.VlanPcpCriterion;
48 import org.slf4j.Logger; 21 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
50 23
51 import com.fasterxml.jackson.databind.node.ObjectNode; 24 import com.fasterxml.jackson.databind.node.ObjectNode;
52 25
53 -import static com.google.common.base.Preconditions.checkNotNull;
54 -
55 /** 26 /**
56 * Criterion codec. 27 * Criterion codec.
57 */ 28 */
...@@ -60,318 +31,46 @@ public final class CriterionCodec extends JsonCodec<Criterion> { ...@@ -60,318 +31,46 @@ public final class CriterionCodec extends JsonCodec<Criterion> {
60 protected static final Logger log = 31 protected static final Logger log =
61 LoggerFactory.getLogger(CriterionCodec.class); 32 LoggerFactory.getLogger(CriterionCodec.class);
62 33
63 - private final EnumMap<Criterion.Type, CriterionTypeFormatter> formatMap; 34 + protected static final String TYPE = "type";
64 - 35 + protected static final String ETH_TYPE = "ethType";
65 - public CriterionCodec() { 36 + protected static final String MAC = "mac";
66 - formatMap = new EnumMap<>(Criterion.Type.class); 37 + protected static final String PORT = "port";
67 - 38 + protected static final String METADATA = "metadata";
68 - formatMap.put(Criterion.Type.IN_PORT, new FormatInPort()); 39 +
69 - formatMap.put(Criterion.Type.IN_PHY_PORT, new FormatInPort()); 40 + protected static final String VLAN_ID = "vlanId";
70 - formatMap.put(Criterion.Type.METADATA, new FormatMetadata()); 41 + protected static final String PRIORITY = "priority";
71 - formatMap.put(Criterion.Type.ETH_DST, new FormatEth()); 42 + protected static final String IP_DSCP = "ipDscp";
72 - formatMap.put(Criterion.Type.ETH_SRC, new FormatEth()); 43 + protected static final String IP_ECN = "ipEcn";
73 - formatMap.put(Criterion.Type.ETH_TYPE, new FormatEthType()); 44 + protected static final String PROTOCOL = "protocol";
74 - formatMap.put(Criterion.Type.VLAN_VID, new FormatVlanVid()); 45 + protected static final String IP = "ip";
75 - formatMap.put(Criterion.Type.VLAN_PCP, new FormatVlanPcp()); 46 + protected static final String TCP_PORT = "tcpPort";
76 - formatMap.put(Criterion.Type.IP_DSCP, new FormatIpDscp()); 47 + protected static final String UDP_PORT = "udpPort";
77 - formatMap.put(Criterion.Type.IP_ECN, new FormatIpEcn()); 48 + protected static final String SCTP_PORT = "sctpPort";
78 - formatMap.put(Criterion.Type.IP_PROTO, new FormatIpProto()); 49 + protected static final String ICMP_TYPE = "icmpType";
79 - formatMap.put(Criterion.Type.IPV4_SRC, new FormatIp()); 50 + protected static final String ICMP_CODE = "icmpCode";
80 - formatMap.put(Criterion.Type.IPV4_DST, new FormatIp()); 51 + protected static final String FLOW_LABEL = "flowLabel";
81 - formatMap.put(Criterion.Type.TCP_SRC, new FormatTcp()); 52 + protected static final String ICMPV6_TYPE = "icmpv6Type";
82 - formatMap.put(Criterion.Type.TCP_DST, new FormatTcp()); 53 + protected static final String ICMPV6_CODE = "icmpv6Code";
83 - formatMap.put(Criterion.Type.UDP_SRC, new FormatUdp()); 54 + protected static final String TARGET_ADDRESS = "targetAddress";
84 - formatMap.put(Criterion.Type.UDP_DST, new FormatUdp()); 55 + protected static final String LABEL = "label";
85 - formatMap.put(Criterion.Type.SCTP_SRC, new FormatSctp()); 56 + protected static final String EXT_HDR_FLAGS = "exthdrFlags";
86 - formatMap.put(Criterion.Type.SCTP_DST, new FormatSctp()); 57 + protected static final String LAMBDA = "lambda";
87 - formatMap.put(Criterion.Type.ICMPV4_TYPE, new FormatIcmpV4Type()); 58 + protected static final String GRID_TYPE = "gridType";
88 - formatMap.put(Criterion.Type.ICMPV4_CODE, new FormatIcmpV4Code()); 59 + protected static final String CHANNEL_SPACING = "channelSpacing";
89 - formatMap.put(Criterion.Type.IPV6_SRC, new FormatIp()); 60 + protected static final String SPACING_MULIPLIER = "spacingMultiplier";
90 - formatMap.put(Criterion.Type.IPV6_DST, new FormatIp()); 61 + protected static final String SLOT_GRANULARITY = "slotGranularity";
91 - formatMap.put(Criterion.Type.IPV6_FLABEL, new FormatIpV6FLabel()); 62 + protected static final String OCH_SIGNAL_ID = "ochSignalId";
92 - formatMap.put(Criterion.Type.ICMPV6_TYPE, new FormatIcmpV6Type());
93 - formatMap.put(Criterion.Type.ICMPV6_CODE, new FormatIcmpV6Code());
94 - formatMap.put(Criterion.Type.IPV6_ND_TARGET, new FormatV6NDTarget());
95 - formatMap.put(Criterion.Type.IPV6_ND_SLL, new FormatV6NDTll());
96 - formatMap.put(Criterion.Type.IPV6_ND_TLL, new FormatV6NDTll());
97 - formatMap.put(Criterion.Type.MPLS_LABEL, new FormatMplsLabel());
98 - formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
99 - formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
100 - formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
101 - formatMap.put(Criterion.Type.DUMMY, new FormatDummyType());
102 -
103 - // Currently unimplemented
104 - formatMap.put(Criterion.Type.ARP_OP, new FormatUnknown());
105 - formatMap.put(Criterion.Type.ARP_SPA, new FormatUnknown());
106 - formatMap.put(Criterion.Type.ARP_TPA, new FormatUnknown());
107 - formatMap.put(Criterion.Type.ARP_SHA, new FormatUnknown());
108 - formatMap.put(Criterion.Type.ARP_THA, new FormatUnknown());
109 - formatMap.put(Criterion.Type.MPLS_TC, new FormatUnknown());
110 - formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
111 - formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
112 - formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
113 - formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
114 - formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
115 - formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
116 - formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown());
117 - formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown());
118 - }
119 -
120 - private interface CriterionTypeFormatter {
121 - ObjectNode encodeCriterion(ObjectNode root, Criterion criterion);
122 - }
123 -
124 - private static class FormatUnknown implements CriterionTypeFormatter {
125 - @Override
126 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
127 - return root;
128 - }
129 - }
130 -
131 - private static class FormatInPort implements CriterionTypeFormatter {
132 - @Override
133 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
134 - final PortCriterion portCriterion = (PortCriterion) criterion;
135 - return root.put("port", portCriterion.port().toLong());
136 - }
137 - }
138 -
139 - private static class FormatMetadata implements CriterionTypeFormatter {
140 - @Override
141 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
142 - final MetadataCriterion metadataCriterion =
143 - (MetadataCriterion) criterion;
144 - return root.put("metadata", metadataCriterion.metadata());
145 - }
146 - }
147 -
148 - private static class FormatEth implements CriterionTypeFormatter {
149 - @Override
150 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
151 - final EthCriterion ethCriterion = (EthCriterion) criterion;
152 - return root.put("mac", ethCriterion.mac().toString());
153 - }
154 - }
155 -
156 - private static class FormatEthType implements CriterionTypeFormatter {
157 - @Override
158 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
159 - final EthTypeCriterion ethTypeCriterion =
160 - (EthTypeCriterion) criterion;
161 - return root.put("ethType", ethTypeCriterion.ethType());
162 - }
163 - }
164 -
165 - private static class FormatVlanVid implements CriterionTypeFormatter {
166 - @Override
167 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
168 - final VlanIdCriterion vlanIdCriterion =
169 - (VlanIdCriterion) criterion;
170 - return root.put("vlanId", vlanIdCriterion.vlanId().toShort());
171 - }
172 - }
173 -
174 - private static class FormatVlanPcp implements CriterionTypeFormatter {
175 - @Override
176 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
177 - final VlanPcpCriterion vlanPcpCriterion =
178 - (VlanPcpCriterion) criterion;
179 - return root.put("priority", vlanPcpCriterion.priority());
180 - }
181 - }
182 -
183 - private static class FormatIpDscp implements CriterionTypeFormatter {
184 - @Override
185 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
186 - final IPDscpCriterion ipDscpCriterion =
187 - (IPDscpCriterion) criterion;
188 - return root.put("ipDscp", ipDscpCriterion.ipDscp());
189 - }
190 - }
191 -
192 - private static class FormatIpEcn implements CriterionTypeFormatter {
193 - @Override
194 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
195 - final IPEcnCriterion ipEcnCriterion =
196 - (IPEcnCriterion) criterion;
197 - return root.put("ipEcn", ipEcnCriterion.ipEcn());
198 - }
199 - }
200 -
201 - private static class FormatIpProto implements CriterionTypeFormatter {
202 - @Override
203 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
204 - final IPProtocolCriterion iPProtocolCriterion =
205 - (IPProtocolCriterion) criterion;
206 - return root.put("protocol", iPProtocolCriterion.protocol());
207 - }
208 - }
209 -
210 - private static class FormatIp implements CriterionTypeFormatter {
211 - @Override
212 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
213 - final IPCriterion iPCriterion = (IPCriterion) criterion;
214 - return root.put("ip", iPCriterion.ip().toString());
215 - }
216 - }
217 -
218 - private static class FormatTcp implements CriterionTypeFormatter {
219 - @Override
220 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
221 - final TcpPortCriterion tcpPortCriterion =
222 - (TcpPortCriterion) criterion;
223 - return root.put("tcpPort", tcpPortCriterion.tcpPort());
224 - }
225 - }
226 -
227 - private static class FormatUdp implements CriterionTypeFormatter {
228 - @Override
229 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
230 - final UdpPortCriterion udpPortCriterion =
231 - (UdpPortCriterion) criterion;
232 - return root.put("udpPort", udpPortCriterion.udpPort());
233 - }
234 - }
235 63
236 - private static class FormatSctp implements CriterionTypeFormatter {
237 @Override 64 @Override
238 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) { 65 + public ObjectNode encode(Criterion criterion, CodecContext context) {
239 - final SctpPortCriterion sctpPortCriterion = 66 + EncodeCriterionCodec encoder = new EncodeCriterionCodec(criterion, context);
240 - (SctpPortCriterion) criterion; 67 + return encoder.encode();
241 - return root.put("sctpPort", sctpPortCriterion.sctpPort());
242 - }
243 - }
244 -
245 - private static class FormatIcmpV4Type implements CriterionTypeFormatter {
246 - @Override
247 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
248 - final IcmpTypeCriterion icmpTypeCriterion =
249 - (IcmpTypeCriterion) criterion;
250 - return root.put("icmpType", icmpTypeCriterion.icmpType());
251 - }
252 - }
253 -
254 - private static class FormatIcmpV4Code implements CriterionTypeFormatter {
255 - @Override
256 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
257 - final IcmpCodeCriterion icmpCodeCriterion =
258 - (IcmpCodeCriterion) criterion;
259 - return root.put("icmpCode", icmpCodeCriterion.icmpCode());
260 - }
261 - }
262 -
263 - private static class FormatIpV6FLabel implements CriterionTypeFormatter {
264 - @Override
265 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
266 - final IPv6FlowLabelCriterion ipv6FlowLabelCriterion =
267 - (IPv6FlowLabelCriterion) criterion;
268 - return root.put("flowLabel", ipv6FlowLabelCriterion.flowLabel());
269 - }
270 - }
271 -
272 - private static class FormatIcmpV6Type implements CriterionTypeFormatter {
273 - @Override
274 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
275 - final Icmpv6TypeCriterion icmpv6TypeCriterion =
276 - (Icmpv6TypeCriterion) criterion;
277 - return root.put("icmpv6Type", icmpv6TypeCriterion.icmpv6Type());
278 - }
279 - }
280 -
281 - private static class FormatIcmpV6Code implements CriterionTypeFormatter {
282 - @Override
283 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
284 - final Icmpv6CodeCriterion icmpv6CodeCriterion =
285 - (Icmpv6CodeCriterion) criterion;
286 - return root.put("icmpv6Code", icmpv6CodeCriterion.icmpv6Code());
287 - }
288 - }
289 -
290 - private static class FormatV6NDTarget implements CriterionTypeFormatter {
291 - @Override
292 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
293 - final IPv6NDTargetAddressCriterion ipv6NDTargetAddressCriterion
294 - = (IPv6NDTargetAddressCriterion) criterion;
295 - return root.put("targetAddress", ipv6NDTargetAddressCriterion.targetAddress().toString());
296 - }
297 - }
298 -
299 - private static class FormatV6NDTll implements CriterionTypeFormatter {
300 - @Override
301 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
302 - final IPv6NDLinkLayerAddressCriterion ipv6NDLinkLayerAddressCriterion
303 - = (IPv6NDLinkLayerAddressCriterion) criterion;
304 - return root.put("mac", ipv6NDLinkLayerAddressCriterion.mac().toString());
305 - }
306 - }
307 -
308 - private static class FormatMplsLabel implements CriterionTypeFormatter {
309 - @Override
310 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
311 - final MplsCriterion mplsCriterion =
312 - (MplsCriterion) criterion;
313 - return root.put("label", mplsCriterion.label().toInt());
314 - }
315 - }
316 -
317 - private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
318 - @Override
319 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
320 - final IPv6ExthdrFlagsCriterion exthdrCriterion =
321 - (IPv6ExthdrFlagsCriterion) criterion;
322 - return root.put("exthdrFlags", exthdrCriterion.exthdrFlags());
323 - }
324 - }
325 -
326 - private static class FormatOchSigId implements CriterionTypeFormatter {
327 - @Override
328 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
329 - OchSignal ochSignal = ((OchSignalCriterion) criterion).lambda();
330 - ObjectNode child = root.putObject("ochSignalId");
331 -
332 - child.put("gridType", ochSignal.gridType().name());
333 - child.put("channelSpacing", ochSignal.channelSpacing().name());
334 - child.put("spacingMultiplier", ochSignal.spacingMultiplier());
335 - child.put("slotGranularity", ochSignal.slotGranularity());
336 -
337 - return root;
338 - }
339 - }
340 -
341 - private static class FormatOchSigType implements CriterionTypeFormatter {
342 - @Override
343 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
344 - final OchSignalTypeCriterion ochSignalTypeCriterion =
345 - (OchSignalTypeCriterion) criterion;
346 - return root.put("ochSignalType", ochSignalTypeCriterion.signalType().name());
347 - }
348 - }
349 -
350 - private class FormatDummyType implements CriterionTypeFormatter {
351 -
352 - @Override
353 - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
354 - checkNotNull(criterion, "Criterion cannot be null");
355 -
356 - return root.put("type", criterion.type().toString());
357 -
358 - }
359 } 68 }
360 69
361 @Override 70 @Override
362 - public ObjectNode encode(Criterion criterion, CodecContext context) { 71 + public Criterion decode(ObjectNode json, CodecContext context) {
363 - checkNotNull(criterion, "Criterion cannot be null"); 72 + DecodeCriterionCodec decoder = new DecodeCriterionCodec(json);
364 - 73 + return decoder.decode();
365 - final ObjectNode result = context.mapper().createObjectNode()
366 - .put("type", criterion.type().toString());
367 -
368 - CriterionTypeFormatter formatter =
369 - checkNotNull(
370 - formatMap.get(criterion.type()),
371 - "No formatter found for criterion type "
372 - + criterion.type().toString());
373 -
374 - return formatter.encodeCriterion(result, criterion);
375 } 74 }
376 75
377 76
......
1 +/*
2 + * Copyright 2015 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 java.util.HashMap;
19 +import java.util.Map;
20 +
21 +import org.onlab.packet.Ip6Address;
22 +import org.onlab.packet.IpPrefix;
23 +import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.MplsLabel;
25 +import org.onlab.packet.VlanId;
26 +import org.onosproject.net.ChannelSpacing;
27 +import org.onosproject.net.GridType;
28 +import org.onosproject.net.Lambda;
29 +import org.onosproject.net.PortNumber;
30 +import org.onosproject.net.flow.criteria.Criteria;
31 +import org.onosproject.net.flow.criteria.Criterion;
32 +
33 +import com.fasterxml.jackson.databind.JsonNode;
34 +import com.fasterxml.jackson.databind.node.ObjectNode;
35 +
36 +import static org.onlab.util.Tools.nullIsIllegal;
37 +
38 +/**
39 + * Decode portion of the criterion codec.
40 + */
41 +public final class DecodeCriterionCodec {
42 +
43 + private final ObjectNode json;
44 +
45 + protected static final String MISSING_MEMBER_MESSAGE =
46 + " member is required in Criterion";
47 +
48 + private interface CriterionDecoder {
49 + Criterion decodeCriterion(ObjectNode json);
50 + }
51 + private final Map<String, CriterionDecoder> decoderMap;
52 +
53 + /**
54 + * Creates a decode criterion codec object.
55 + * Initializes the lookup map for criterion subclass decoders.
56 + *
57 + * @param json JSON object to decode
58 + */
59 + public DecodeCriterionCodec(ObjectNode json) {
60 + this.json = json;
61 + decoderMap = new HashMap<>();
62 +
63 + decoderMap.put(Criterion.Type.IN_PORT.name(), new InPortDecoder());
64 + decoderMap.put(Criterion.Type.IN_PHY_PORT.name(), new InPhyPortDecoder());
65 + decoderMap.put(Criterion.Type.METADATA.name(), new MetadataDecoder());
66 + decoderMap.put(Criterion.Type.ETH_DST.name(), new EthDstDecoder());
67 + decoderMap.put(Criterion.Type.ETH_SRC.name(), new EthSrcDecoder());
68 + decoderMap.put(Criterion.Type.ETH_TYPE.name(), new EthTypeDecoder());
69 + decoderMap.put(Criterion.Type.VLAN_VID.name(), new VlanVidDecoder());
70 + decoderMap.put(Criterion.Type.VLAN_PCP.name(), new VlanPcpDecoder());
71 + decoderMap.put(Criterion.Type.IP_DSCP.name(), new IpDscpDecoder());
72 + decoderMap.put(Criterion.Type.IP_ECN.name(), new IpEcnDecoder());
73 + decoderMap.put(Criterion.Type.IP_PROTO.name(), new IpProtoDecoder());
74 + decoderMap.put(Criterion.Type.IPV4_SRC.name(), new IpV4SrcDecoder());
75 + decoderMap.put(Criterion.Type.IPV4_DST.name(), new IpV4DstDecoder());
76 + decoderMap.put(Criterion.Type.TCP_SRC.name(), new TcpSrcDecoder());
77 + decoderMap.put(Criterion.Type.TCP_DST.name(), new TcpDstDecoder());
78 + decoderMap.put(Criterion.Type.UDP_SRC.name(), new UdpSrcDecoder());
79 + decoderMap.put(Criterion.Type.UDP_DST.name(), new UdpDstDecoder());
80 + decoderMap.put(Criterion.Type.SCTP_SRC.name(), new SctpSrcDecoder());
81 + decoderMap.put(Criterion.Type.SCTP_DST.name(), new SctpDstDecoder());
82 + decoderMap.put(Criterion.Type.ICMPV4_TYPE.name(), new IcmpV4TypeDecoder());
83 + decoderMap.put(Criterion.Type.ICMPV4_CODE.name(), new IcmpV4CodeDecoder());
84 + decoderMap.put(Criterion.Type.IPV6_SRC.name(), new IpV6SrcDecoder());
85 + decoderMap.put(Criterion.Type.IPV6_DST.name(), new IpV6DstDecoder());
86 + decoderMap.put(Criterion.Type.IPV6_FLABEL.name(), new IpV6FLabelDecoder());
87 + decoderMap.put(Criterion.Type.ICMPV6_TYPE.name(), new IcmpV6TypeDecoder());
88 + decoderMap.put(Criterion.Type.ICMPV6_CODE.name(), new IcmpV6CodeDecoder());
89 + decoderMap.put(Criterion.Type.IPV6_ND_TARGET.name(), new V6NDTargetDecoder());
90 + decoderMap.put(Criterion.Type.IPV6_ND_SLL.name(), new V6NDSllDecoder());
91 + decoderMap.put(Criterion.Type.IPV6_ND_TLL.name(), new V6NDTllDecoder());
92 + decoderMap.put(Criterion.Type.MPLS_LABEL.name(), new MplsLabelDecoder());
93 + decoderMap.put(Criterion.Type.IPV6_EXTHDR.name(), new IpV6ExthdrDecoder());
94 + decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder());
95 + decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder());
96 + }
97 +
98 + private class EthTypeDecoder implements CriterionDecoder {
99 + @Override
100 + public Criterion decodeCriterion(ObjectNode json) {
101 + int ethType = nullIsIllegal(json.get(CriterionCodec.ETH_TYPE),
102 + CriterionCodec.ETH_TYPE + MISSING_MEMBER_MESSAGE).asInt();
103 + return Criteria.matchEthType(ethType);
104 + }
105 + }
106 +
107 + private class EthDstDecoder implements CriterionDecoder {
108 + @Override
109 + public Criterion decodeCriterion(ObjectNode json) {
110 + MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
111 + CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
112 +
113 + return Criteria.matchEthDst(mac);
114 + }
115 + }
116 +
117 + private class EthSrcDecoder implements CriterionDecoder {
118 + @Override
119 + public Criterion decodeCriterion(ObjectNode json) {
120 + MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
121 + CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
122 +
123 + return Criteria.matchEthSrc(mac);
124 + }
125 + }
126 +
127 + private class InPortDecoder implements CriterionDecoder {
128 + @Override
129 + public Criterion decodeCriterion(ObjectNode json) {
130 + PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
131 + CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
132 +
133 + return Criteria.matchInPort(port);
134 + }
135 + }
136 +
137 + private class InPhyPortDecoder implements CriterionDecoder {
138 + @Override
139 + public Criterion decodeCriterion(ObjectNode json) {
140 + PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
141 + CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
142 +
143 + return Criteria.matchInPhyPort(port);
144 + }
145 + }
146 +
147 + private class MetadataDecoder implements CriterionDecoder {
148 + @Override
149 + public Criterion decodeCriterion(ObjectNode json) {
150 + long metadata = nullIsIllegal(json.get(CriterionCodec.METADATA),
151 + CriterionCodec.METADATA + MISSING_MEMBER_MESSAGE).asLong();
152 +
153 + return Criteria.matchMetadata(metadata);
154 + }
155 + }
156 +
157 + private class VlanVidDecoder implements CriterionDecoder {
158 + @Override
159 + public Criterion decodeCriterion(ObjectNode json) {
160 + short vlanId = (short) nullIsIllegal(json.get(CriterionCodec.VLAN_ID),
161 + CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
162 +
163 + return Criteria.matchVlanId(VlanId.vlanId(vlanId));
164 + }
165 + }
166 +
167 + private class VlanPcpDecoder implements CriterionDecoder {
168 + @Override
169 + public Criterion decodeCriterion(ObjectNode json) {
170 + byte priority = (byte) nullIsIllegal(json.get(CriterionCodec.PRIORITY),
171 + CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
172 +
173 + return Criteria.matchVlanPcp(priority);
174 + }
175 + }
176 +
177 + private class IpDscpDecoder implements CriterionDecoder {
178 + @Override
179 + public Criterion decodeCriterion(ObjectNode json) {
180 + byte ipDscp = (byte) nullIsIllegal(json.get(CriterionCodec.IP_DSCP),
181 + CriterionCodec.IP_DSCP + MISSING_MEMBER_MESSAGE).asInt();
182 + return Criteria.matchIPDscp(ipDscp);
183 + }
184 + }
185 +
186 + private class IpEcnDecoder implements CriterionDecoder {
187 + @Override
188 + public Criterion decodeCriterion(ObjectNode json) {
189 + byte ipEcn = (byte) nullIsIllegal(json.get(CriterionCodec.IP_ECN),
190 + CriterionCodec.IP_ECN + MISSING_MEMBER_MESSAGE).asInt();
191 + return Criteria.matchIPEcn(ipEcn);
192 + }
193 + }
194 +
195 + private class IpProtoDecoder implements CriterionDecoder {
196 + @Override
197 + public Criterion decodeCriterion(ObjectNode json) {
198 + short proto = (short) nullIsIllegal(json.get(CriterionCodec.PROTOCOL),
199 + CriterionCodec.PROTOCOL + MISSING_MEMBER_MESSAGE).asInt();
200 + return Criteria.matchIPProtocol(proto);
201 + }
202 + }
203 +
204 + private class IpV4SrcDecoder implements CriterionDecoder {
205 + @Override
206 + public Criterion decodeCriterion(ObjectNode json) {
207 + String ip = nullIsIllegal(json.get(CriterionCodec.IP),
208 + CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
209 + return Criteria.matchIPSrc(IpPrefix.valueOf(ip));
210 + }
211 + }
212 +
213 + private class IpV4DstDecoder implements CriterionDecoder {
214 + @Override
215 + public Criterion decodeCriterion(ObjectNode json) {
216 + String ip = nullIsIllegal(json.get(CriterionCodec.IP),
217 + CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
218 + return Criteria.matchIPDst(IpPrefix.valueOf(ip));
219 + }
220 + }
221 +
222 + private class IpV6SrcDecoder implements CriterionDecoder {
223 + @Override
224 + public Criterion decodeCriterion(ObjectNode json) {
225 + String ip = nullIsIllegal(json.get(CriterionCodec.IP),
226 + CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
227 + return Criteria.matchIPv6Src(IpPrefix.valueOf(ip));
228 + }
229 + }
230 +
231 + private class IpV6DstDecoder implements CriterionDecoder {
232 + @Override
233 + public Criterion decodeCriterion(ObjectNode json) {
234 + String ip = nullIsIllegal(json.get(CriterionCodec.IP),
235 + CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
236 + return Criteria.matchIPv6Dst(IpPrefix.valueOf(ip));
237 + }
238 + }
239 +
240 + private class TcpSrcDecoder implements CriterionDecoder {
241 + @Override
242 + public Criterion decodeCriterion(ObjectNode json) {
243 + int tcpPort = nullIsIllegal(json.get(CriterionCodec.TCP_PORT),
244 + CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt();
245 + return Criteria.matchTcpSrc(tcpPort);
246 + }
247 + }
248 +
249 + private class TcpDstDecoder implements CriterionDecoder {
250 + @Override
251 + public Criterion decodeCriterion(ObjectNode json) {
252 + int tcpPort = nullIsIllegal(json.get(CriterionCodec.TCP_PORT),
253 + CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt();
254 + return Criteria.matchTcpDst(tcpPort);
255 + }
256 + }
257 +
258 + private class UdpSrcDecoder implements CriterionDecoder {
259 + @Override
260 + public Criterion decodeCriterion(ObjectNode json) {
261 + int udpPort = nullIsIllegal(json.get(CriterionCodec.UDP_PORT),
262 + CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt();
263 + return Criteria.matchUdpSrc(udpPort);
264 + }
265 + }
266 +
267 + private class UdpDstDecoder implements CriterionDecoder {
268 + @Override
269 + public Criterion decodeCriterion(ObjectNode json) {
270 + int udpPort = nullIsIllegal(json.get(CriterionCodec.UDP_PORT),
271 + CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt();
272 + return Criteria.matchUdpDst(udpPort);
273 + }
274 + }
275 +
276 + private class SctpSrcDecoder implements CriterionDecoder {
277 + @Override
278 + public Criterion decodeCriterion(ObjectNode json) {
279 + int sctpPort = nullIsIllegal(json.get(CriterionCodec.SCTP_PORT),
280 + CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt();
281 + return Criteria.matchSctpSrc(sctpPort);
282 + }
283 + }
284 +
285 + private class SctpDstDecoder implements CriterionDecoder {
286 + @Override
287 + public Criterion decodeCriterion(ObjectNode json) {
288 + int sctpPort = nullIsIllegal(json.get(CriterionCodec.SCTP_PORT),
289 + CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt();
290 + return Criteria.matchSctpDst(sctpPort);
291 + }
292 + }
293 +
294 + private class IcmpV4TypeDecoder implements CriterionDecoder {
295 + @Override
296 + public Criterion decodeCriterion(ObjectNode json) {
297 + short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_TYPE),
298 + CriterionCodec.ICMP_TYPE + MISSING_MEMBER_MESSAGE).asInt();
299 + return Criteria.matchIcmpType(type);
300 + }
301 + }
302 +
303 + private class IcmpV4CodeDecoder implements CriterionDecoder {
304 + @Override
305 + public Criterion decodeCriterion(ObjectNode json) {
306 + short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_CODE),
307 + CriterionCodec.ICMP_CODE + MISSING_MEMBER_MESSAGE).asInt();
308 + return Criteria.matchIcmpCode(code);
309 + }
310 + }
311 +
312 + private class IpV6FLabelDecoder implements CriterionDecoder {
313 + @Override
314 + public Criterion decodeCriterion(ObjectNode json) {
315 + int flowLabel = nullIsIllegal(json.get(CriterionCodec.FLOW_LABEL),
316 + CriterionCodec.FLOW_LABEL + MISSING_MEMBER_MESSAGE).asInt();
317 + return Criteria.matchIPv6FlowLabel(flowLabel);
318 + }
319 + }
320 +
321 + private class IcmpV6TypeDecoder implements CriterionDecoder {
322 + @Override
323 + public Criterion decodeCriterion(ObjectNode json) {
324 + short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_TYPE),
325 + CriterionCodec.ICMPV6_TYPE + MISSING_MEMBER_MESSAGE).asInt();
326 + return Criteria.matchIcmpv6Type(type);
327 + }
328 + }
329 +
330 + private class IcmpV6CodeDecoder implements CriterionDecoder {
331 + @Override
332 + public Criterion decodeCriterion(ObjectNode json) {
333 + short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_CODE),
334 + CriterionCodec.ICMPV6_CODE + MISSING_MEMBER_MESSAGE).asInt();
335 + return Criteria.matchIcmpv6Code(code);
336 + }
337 + }
338 +
339 + private class V6NDTargetDecoder implements CriterionDecoder {
340 + @Override
341 + public Criterion decodeCriterion(ObjectNode json) {
342 + Ip6Address target = Ip6Address.valueOf(nullIsIllegal(json.get(CriterionCodec.TARGET_ADDRESS),
343 + CriterionCodec.TARGET_ADDRESS + MISSING_MEMBER_MESSAGE).asText());
344 + return Criteria.matchIPv6NDTargetAddress(target);
345 + }
346 + }
347 +
348 + private class V6NDSllDecoder implements CriterionDecoder {
349 + @Override
350 + public Criterion decodeCriterion(ObjectNode json) {
351 + MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
352 + CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
353 + return Criteria.matchIPv6NDSourceLinkLayerAddress(mac);
354 + }
355 + }
356 +
357 + private class V6NDTllDecoder implements CriterionDecoder {
358 + @Override
359 + public Criterion decodeCriterion(ObjectNode json) {
360 + MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
361 + CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
362 + return Criteria.matchIPv6NDTargetLinkLayerAddress(mac);
363 + }
364 + }
365 +
366 + private class MplsLabelDecoder implements CriterionDecoder {
367 + @Override
368 + public Criterion decodeCriterion(ObjectNode json) {
369 + int label = nullIsIllegal(json.get(CriterionCodec.LABEL),
370 + CriterionCodec.LABEL + MISSING_MEMBER_MESSAGE).asInt();
371 + return Criteria.matchMplsLabel(MplsLabel.mplsLabel(label));
372 + }
373 + }
374 +
375 + private class IpV6ExthdrDecoder implements CriterionDecoder {
376 + @Override
377 + public Criterion decodeCriterion(ObjectNode json) {
378 + int exthdrFlags = nullIsIllegal(json.get(CriterionCodec.EXT_HDR_FLAGS),
379 + CriterionCodec.EXT_HDR_FLAGS + MISSING_MEMBER_MESSAGE).asInt();
380 + return Criteria.matchIPv6ExthdrFlags(exthdrFlags);
381 + }
382 + }
383 +
384 + private class OchSigIdDecoder implements CriterionDecoder {
385 + @Override
386 + public Criterion decodeCriterion(ObjectNode json) {
387 + if (json.get(CriterionCodec.LAMBDA) != null) {
388 + Lambda lambda = Lambda.indexedLambda(nullIsIllegal(json.get(CriterionCodec.LAMBDA),
389 + CriterionCodec.LAMBDA + MISSING_MEMBER_MESSAGE).asInt());
390 + return Criteria.matchLambda(lambda);
391 + } else {
392 + JsonNode ochSignalId = nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_ID),
393 + CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE);
394 + GridType gridType =
395 + GridType.valueOf(
396 + nullIsIllegal(ochSignalId.get(CriterionCodec.GRID_TYPE),
397 + CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE).asText());
398 + ChannelSpacing channelSpacing =
399 + ChannelSpacing.valueOf(
400 + nullIsIllegal(ochSignalId.get(CriterionCodec.CHANNEL_SPACING),
401 + CriterionCodec.CHANNEL_SPACING + MISSING_MEMBER_MESSAGE).asText());
402 + int spacingMultiplier = nullIsIllegal(ochSignalId.get(CriterionCodec.SPACING_MULIPLIER),
403 + CriterionCodec.SPACING_MULIPLIER + MISSING_MEMBER_MESSAGE).asInt();
404 + int slotGranularity = nullIsIllegal(ochSignalId.get(CriterionCodec.SLOT_GRANULARITY),
405 + CriterionCodec.SLOT_GRANULARITY + MISSING_MEMBER_MESSAGE).asInt();
406 + return Criteria.matchLambda(
407 + Lambda.ochSignal(gridType, channelSpacing,
408 + spacingMultiplier, slotGranularity));
409 + }
410 + }
411 + }
412 +
413 + private class OchSigTypeDecoder implements CriterionDecoder {
414 + @Override
415 + public Criterion decodeCriterion(ObjectNode json) {
416 + return null;
417 + }
418 + }
419 +
420 + /**
421 + * Decodes the JSON into a criterion object.
422 + *
423 + * @return Criterion object
424 + * @throws IllegalArgumentException if the JSON is invalid
425 + */
426 + public Criterion decode() {
427 + String type = json.get(CriterionCodec.TYPE).asText();
428 +
429 + CriterionDecoder decoder = decoderMap.get(type);
430 + if (decoder != null) {
431 + return decoder.decodeCriterion(json);
432 + }
433 +
434 + throw new IllegalArgumentException("Type " + type + " is unknown");
435 + }
436 +
437 +
438 +}
1 +/*
2 + * Copyright 2015 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 org.onlab.packet.IpAddress;
19 +import org.onlab.packet.MacAddress;
20 +import org.onlab.packet.MplsLabel;
21 +import org.onlab.packet.VlanId;
22 +import org.onosproject.net.ChannelSpacing;
23 +import org.onosproject.net.GridType;
24 +import org.onosproject.net.Lambda;
25 +import org.onosproject.net.OchSignal;
26 +import org.onosproject.net.PortNumber;
27 +import org.onosproject.net.flow.instructions.Instruction;
28 +import org.onosproject.net.flow.instructions.Instructions;
29 +import org.onosproject.net.flow.instructions.L0ModificationInstruction;
30 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
31 +import org.onosproject.net.flow.instructions.L3ModificationInstruction;
32 +
33 +import com.fasterxml.jackson.databind.node.ObjectNode;
34 +
35 +import static org.onlab.util.Tools.nullIsIllegal;
36 +
37 +/**
38 + * Decoding portion of the instruction codec.
39 + */
40 +public final class DecodeInstructionCodec {
41 + private final ObjectNode json;
42 +
43 + /**
44 + * Creates a decode instruction codec object.
45 + *
46 + * @param json JSON object to decode
47 + */
48 + public DecodeInstructionCodec(ObjectNode json) {
49 + this.json = json;
50 + }
51 +
52 + /**
53 + * Decodes a Layer 2 instruction.
54 + *
55 + * @return instruction object decoded from the JSON
56 + * @throws IllegalArgumentException if the JSON is invalid
57 + */
58 + private Instruction decodeL2() {
59 + String subType = json.get(InstructionCodec.SUBTYPE).asText();
60 +
61 + if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC.name())) {
62 + String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
63 + InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
64 + return Instructions.modL2Src(MacAddress.valueOf(mac));
65 + } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST.name())) {
66 + String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
67 + InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
68 + return Instructions.modL2Dst(MacAddress.valueOf(mac));
69 + } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_ID.name())) {
70 + short vlanId = (short) nullIsIllegal(json.get(InstructionCodec.VLAN_ID),
71 + InstructionCodec.VLAN_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
72 + return Instructions.modVlanId(VlanId.vlanId(vlanId));
73 + } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PCP.name())) {
74 + byte vlanPcp = (byte) nullIsIllegal(json.get(InstructionCodec.VLAN_PCP),
75 + InstructionCodec.VLAN_PCP + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
76 + return Instructions.modVlanPcp(vlanPcp);
77 + } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_LABEL.name())) {
78 + int label = nullIsIllegal(json.get(InstructionCodec.MPLS_LABEL),
79 + InstructionCodec.MPLS_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
80 + return Instructions.modMplsLabel(MplsLabel.mplsLabel(label));
81 + } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_PUSH.name())) {
82 + return Instructions.pushMpls();
83 + } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_POP.name())) {
84 + return Instructions.popMpls();
85 + } else if (subType.equals(L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name())) {
86 + return Instructions.decMplsTtl();
87 + } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_POP.name())) {
88 + return Instructions.popVlan();
89 + } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PUSH.name())) {
90 + return Instructions.pushVlan();
91 + }
92 + throw new IllegalArgumentException("L2 Instruction subtype "
93 + + subType + " is not supported");
94 + }
95 +
96 + /**
97 + * Decodes a Layer 3 instruction.
98 + *
99 + * @return instruction object decoded from the JSON
100 + * @throws IllegalArgumentException if the JSON is invalid
101 + */
102 + private Instruction decodeL3() {
103 + String subType = json.get(InstructionCodec.SUBTYPE).asText();
104 +
105 + if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_SRC.name())) {
106 + IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
107 + InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
108 + return Instructions.modL3Src(ip);
109 + } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_DST.name())) {
110 + IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
111 + InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
112 + return Instructions.modL3Dst(ip);
113 + } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_SRC.name())) {
114 + IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
115 + InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
116 + return Instructions.modL3IPv6Src(ip);
117 + } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_DST.name())) {
118 + IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
119 + InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
120 + return Instructions.modL3IPv6Dst(ip);
121 + } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_FLABEL.name())) {
122 + int flowLabel = nullIsIllegal(json.get(InstructionCodec.FLOW_LABEL),
123 + InstructionCodec.FLOW_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
124 + return Instructions.modL3IPv6FlowLabel(flowLabel);
125 + }
126 + throw new IllegalArgumentException("L3 Instruction subtype "
127 + + subType + " is not supported");
128 + }
129 +
130 + /**
131 + * Decodes a Layer 0 instruction.
132 + *
133 + * @return instruction object decoded from the JSON
134 + * @throws IllegalArgumentException if the JSON is invalid
135 + */
136 + private Instruction decodeL0() {
137 + String subType = json.get(InstructionCodec.SUBTYPE).asText();
138 +
139 +
140 + if (subType.equals(L0ModificationInstruction.L0SubType.LAMBDA.name())) {
141 + int lambda = nullIsIllegal(json.get(InstructionCodec.LAMBDA),
142 + InstructionCodec.LAMBDA + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
143 + return Instructions.modL0Lambda(Lambda.indexedLambda(lambda));
144 + } else if (subType.equals(L0ModificationInstruction.L0SubType.OCH.name())) {
145 + String gridTypeString = nullIsIllegal(json.get(InstructionCodec.GRID_TYPE),
146 + InstructionCodec.GRID_TYPE + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
147 + GridType gridType = GridType.valueOf(gridTypeString);
148 + if (gridType == null) {
149 + throw new IllegalArgumentException("Unknown grid type "
150 + + gridTypeString);
151 + }
152 + String channelSpacingString = nullIsIllegal(json.get(InstructionCodec.CHANNEL_SPACING),
153 + InstructionCodec.CHANNEL_SPACING + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
154 + ChannelSpacing channelSpacing = ChannelSpacing.valueOf(channelSpacingString);
155 + if (channelSpacing == null) {
156 + throw new IllegalArgumentException("Unknown channel spacing "
157 + + channelSpacingString);
158 + }
159 + int spacingMultiplier = nullIsIllegal(json.get(InstructionCodec.SPACING_MULTIPLIER),
160 + InstructionCodec.SPACING_MULTIPLIER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
161 + int slotGranularity = nullIsIllegal(json.get(InstructionCodec.SLOT_GRANULARITY),
162 + InstructionCodec.SLOT_GRANULARITY + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
163 + return Instructions.modL0Lambda(new OchSignal(gridType, channelSpacing,
164 + spacingMultiplier, slotGranularity));
165 + }
166 + throw new IllegalArgumentException("L0 Instruction subtype "
167 + + subType + " is not supported");
168 + }
169 +
170 + /**
171 + * Decodes the JSON into an instruction object.
172 + *
173 + * @return Criterion object
174 + * @throws IllegalArgumentException if the JSON is invalid
175 + */
176 + public Instruction decode() {
177 + String type = json.get(InstructionCodec.TYPE).asText();
178 +
179 + if (type.equals(Instruction.Type.OUTPUT.name())) {
180 + PortNumber portNumber =
181 + PortNumber.portNumber(nullIsIllegal(json.get(InstructionCodec.PORT),
182 + InstructionCodec.PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong());
183 + return Instructions.createOutput(portNumber);
184 + } else if (type.equals(Instruction.Type.DROP.name())) {
185 + return Instructions.createDrop();
186 + } else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
187 + return decodeL0();
188 + } else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
189 + return decodeL2();
190 + } else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
191 + return decodeL3();
192 + }
193 + throw new IllegalArgumentException("Instruction type "
194 + + type + " is not supported");
195 + }
196 +
197 +}
1 +/*
2 + * Copyright 2015 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 java.util.EnumMap;
19 +
20 +import org.onosproject.codec.CodecContext;
21 +import org.onosproject.net.OchSignal;
22 +import org.onosproject.net.flow.criteria.Criterion;
23 +import org.onosproject.net.flow.criteria.EthCriterion;
24 +import org.onosproject.net.flow.criteria.EthTypeCriterion;
25 +import org.onosproject.net.flow.criteria.IPCriterion;
26 +import org.onosproject.net.flow.criteria.IPDscpCriterion;
27 +import org.onosproject.net.flow.criteria.IPEcnCriterion;
28 +import org.onosproject.net.flow.criteria.IPProtocolCriterion;
29 +import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
30 +import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
31 +import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
32 +import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
33 +import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
34 +import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
35 +import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
36 +import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
37 +import org.onosproject.net.flow.criteria.MetadataCriterion;
38 +import org.onosproject.net.flow.criteria.MplsCriterion;
39 +import org.onosproject.net.flow.criteria.OchSignalCriterion;
40 +import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
41 +import org.onosproject.net.flow.criteria.PortCriterion;
42 +import org.onosproject.net.flow.criteria.SctpPortCriterion;
43 +import org.onosproject.net.flow.criteria.TcpPortCriterion;
44 +import org.onosproject.net.flow.criteria.UdpPortCriterion;
45 +import org.onosproject.net.flow.criteria.VlanIdCriterion;
46 +import org.onosproject.net.flow.criteria.VlanPcpCriterion;
47 +
48 +import com.fasterxml.jackson.databind.node.ObjectNode;
49 +
50 +import static com.google.common.base.Preconditions.checkNotNull;
51 +
52 +/**
53 + * Encode portion of the criterion codec.
54 + */
55 +public final class EncodeCriterionCodec {
56 +
57 + private final Criterion criterion;
58 + private final CodecContext context;
59 +
60 + private final EnumMap<Criterion.Type, CriterionTypeFormatter> formatMap;
61 +
62 + /**
63 + * Creates an encoder object for a criterion.
64 + * Initializes the formatter lookup map for the criterion subclasses.
65 + *
66 + * @param criterion Criterion to encode
67 + * @param context context of the JSON encoding
68 + */
69 + public EncodeCriterionCodec(Criterion criterion, CodecContext context) {
70 + this.criterion = criterion;
71 + this.context = context;
72 +
73 + formatMap = new EnumMap<>(Criterion.Type.class);
74 +
75 + formatMap.put(Criterion.Type.IN_PORT, new FormatInPort());
76 + formatMap.put(Criterion.Type.IN_PHY_PORT, new FormatInPort());
77 + formatMap.put(Criterion.Type.METADATA, new FormatMetadata());
78 + formatMap.put(Criterion.Type.ETH_DST, new FormatEth());
79 + formatMap.put(Criterion.Type.ETH_SRC, new FormatEth());
80 + formatMap.put(Criterion.Type.ETH_TYPE, new FormatEthType());
81 + formatMap.put(Criterion.Type.VLAN_VID, new FormatVlanVid());
82 + formatMap.put(Criterion.Type.VLAN_PCP, new FormatVlanPcp());
83 + formatMap.put(Criterion.Type.IP_DSCP, new FormatIpDscp());
84 + formatMap.put(Criterion.Type.IP_ECN, new FormatIpEcn());
85 + formatMap.put(Criterion.Type.IP_PROTO, new FormatIpProto());
86 + formatMap.put(Criterion.Type.IPV4_SRC, new FormatIp());
87 + formatMap.put(Criterion.Type.IPV4_DST, new FormatIp());
88 + formatMap.put(Criterion.Type.TCP_SRC, new FormatTcp());
89 + formatMap.put(Criterion.Type.TCP_DST, new FormatTcp());
90 + formatMap.put(Criterion.Type.UDP_SRC, new FormatUdp());
91 + formatMap.put(Criterion.Type.UDP_DST, new FormatUdp());
92 + formatMap.put(Criterion.Type.SCTP_SRC, new FormatSctp());
93 + formatMap.put(Criterion.Type.SCTP_DST, new FormatSctp());
94 + formatMap.put(Criterion.Type.ICMPV4_TYPE, new FormatIcmpV4Type());
95 + formatMap.put(Criterion.Type.ICMPV4_CODE, new FormatIcmpV4Code());
96 + formatMap.put(Criterion.Type.IPV6_SRC, new FormatIp());
97 + formatMap.put(Criterion.Type.IPV6_DST, new FormatIp());
98 + formatMap.put(Criterion.Type.IPV6_FLABEL, new FormatIpV6FLabel());
99 + formatMap.put(Criterion.Type.ICMPV6_TYPE, new FormatIcmpV6Type());
100 + formatMap.put(Criterion.Type.ICMPV6_CODE, new FormatIcmpV6Code());
101 + formatMap.put(Criterion.Type.IPV6_ND_TARGET, new FormatV6NDTarget());
102 + formatMap.put(Criterion.Type.IPV6_ND_SLL, new FormatV6NDTll());
103 + formatMap.put(Criterion.Type.IPV6_ND_TLL, new FormatV6NDTll());
104 + formatMap.put(Criterion.Type.MPLS_LABEL, new FormatMplsLabel());
105 + formatMap.put(Criterion.Type.IPV6_EXTHDR, new FormatIpV6Exthdr());
106 + formatMap.put(Criterion.Type.OCH_SIGID, new FormatOchSigId());
107 + formatMap.put(Criterion.Type.OCH_SIGTYPE, new FormatOchSigType());
108 + formatMap.put(Criterion.Type.DUMMY, new FormatDummyType());
109 +
110 + // Currently unimplemented
111 + formatMap.put(Criterion.Type.ARP_OP, new FormatUnknown());
112 + formatMap.put(Criterion.Type.ARP_SPA, new FormatUnknown());
113 + formatMap.put(Criterion.Type.ARP_TPA, new FormatUnknown());
114 + formatMap.put(Criterion.Type.ARP_SHA, new FormatUnknown());
115 + formatMap.put(Criterion.Type.ARP_THA, new FormatUnknown());
116 + formatMap.put(Criterion.Type.MPLS_TC, new FormatUnknown());
117 + formatMap.put(Criterion.Type.MPLS_BOS, new FormatUnknown());
118 + formatMap.put(Criterion.Type.PBB_ISID, new FormatUnknown());
119 + formatMap.put(Criterion.Type.TUNNEL_ID, new FormatUnknown());
120 + formatMap.put(Criterion.Type.UNASSIGNED_40, new FormatUnknown());
121 + formatMap.put(Criterion.Type.PBB_UCA, new FormatUnknown());
122 + formatMap.put(Criterion.Type.TCP_FLAGS, new FormatUnknown());
123 + formatMap.put(Criterion.Type.ACTSET_OUTPUT, new FormatUnknown());
124 + formatMap.put(Criterion.Type.PACKET_TYPE, new FormatUnknown());
125 + }
126 +
127 + private interface CriterionTypeFormatter {
128 + ObjectNode encodeCriterion(ObjectNode root, Criterion criterion);
129 + }
130 +
131 + private static class FormatUnknown implements CriterionTypeFormatter {
132 + @Override
133 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
134 + return root;
135 + }
136 + }
137 +
138 + private static class FormatInPort implements CriterionTypeFormatter {
139 + @Override
140 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
141 + final PortCriterion portCriterion = (PortCriterion) criterion;
142 + return root.put(CriterionCodec.PORT, portCriterion.port().toLong());
143 + }
144 + }
145 +
146 + private static class FormatMetadata implements CriterionTypeFormatter {
147 + @Override
148 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
149 + final MetadataCriterion metadataCriterion =
150 + (MetadataCriterion) criterion;
151 + return root.put(CriterionCodec.METADATA, metadataCriterion.metadata());
152 + }
153 + }
154 +
155 + private static class FormatEth implements CriterionTypeFormatter {
156 + @Override
157 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
158 + final EthCriterion ethCriterion = (EthCriterion) criterion;
159 + return root.put(CriterionCodec.MAC, ethCriterion.mac().toString());
160 + }
161 + }
162 +
163 + private static class FormatEthType implements CriterionTypeFormatter {
164 + @Override
165 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
166 + final EthTypeCriterion ethTypeCriterion =
167 + (EthTypeCriterion) criterion;
168 + return root.put(CriterionCodec.ETH_TYPE, ethTypeCriterion.ethType());
169 + }
170 + }
171 +
172 + private static class FormatVlanVid implements CriterionTypeFormatter {
173 + @Override
174 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
175 + final VlanIdCriterion vlanIdCriterion =
176 + (VlanIdCriterion) criterion;
177 + return root.put(CriterionCodec.VLAN_ID, vlanIdCriterion.vlanId().toShort());
178 + }
179 + }
180 +
181 + private static class FormatVlanPcp implements CriterionTypeFormatter {
182 + @Override
183 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
184 + final VlanPcpCriterion vlanPcpCriterion =
185 + (VlanPcpCriterion) criterion;
186 + return root.put(CriterionCodec.PRIORITY, vlanPcpCriterion.priority());
187 + }
188 + }
189 +
190 + private static class FormatIpDscp implements CriterionTypeFormatter {
191 + @Override
192 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
193 + final IPDscpCriterion ipDscpCriterion =
194 + (IPDscpCriterion) criterion;
195 + return root.put(CriterionCodec.IP_DSCP, ipDscpCriterion.ipDscp());
196 + }
197 + }
198 +
199 + private static class FormatIpEcn implements CriterionTypeFormatter {
200 + @Override
201 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
202 + final IPEcnCriterion ipEcnCriterion =
203 + (IPEcnCriterion) criterion;
204 + return root.put(CriterionCodec.IP_ECN, ipEcnCriterion.ipEcn());
205 + }
206 + }
207 +
208 + private static class FormatIpProto implements CriterionTypeFormatter {
209 + @Override
210 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
211 + final IPProtocolCriterion iPProtocolCriterion =
212 + (IPProtocolCriterion) criterion;
213 + return root.put(CriterionCodec.PROTOCOL, iPProtocolCriterion.protocol());
214 + }
215 + }
216 +
217 + private static class FormatIp implements CriterionTypeFormatter {
218 + @Override
219 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
220 + final IPCriterion iPCriterion = (IPCriterion) criterion;
221 + return root.put(CriterionCodec.IP, iPCriterion.ip().toString());
222 + }
223 + }
224 +
225 + private static class FormatTcp implements CriterionTypeFormatter {
226 + @Override
227 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
228 + final TcpPortCriterion tcpPortCriterion =
229 + (TcpPortCriterion) criterion;
230 + return root.put(CriterionCodec.TCP_PORT, tcpPortCriterion.tcpPort());
231 + }
232 + }
233 +
234 + private static class FormatUdp implements CriterionTypeFormatter {
235 + @Override
236 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
237 + final UdpPortCriterion udpPortCriterion =
238 + (UdpPortCriterion) criterion;
239 + return root.put(CriterionCodec.UDP_PORT, udpPortCriterion.udpPort());
240 + }
241 + }
242 +
243 + private static class FormatSctp implements CriterionTypeFormatter {
244 + @Override
245 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
246 + final SctpPortCriterion sctpPortCriterion =
247 + (SctpPortCriterion) criterion;
248 + return root.put(CriterionCodec.SCTP_PORT, sctpPortCriterion.sctpPort());
249 + }
250 + }
251 +
252 + private static class FormatIcmpV4Type implements CriterionTypeFormatter {
253 + @Override
254 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
255 + final IcmpTypeCriterion icmpTypeCriterion =
256 + (IcmpTypeCriterion) criterion;
257 + return root.put(CriterionCodec.ICMP_TYPE, icmpTypeCriterion.icmpType());
258 + }
259 + }
260 +
261 + private static class FormatIcmpV4Code implements CriterionTypeFormatter {
262 + @Override
263 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
264 + final IcmpCodeCriterion icmpCodeCriterion =
265 + (IcmpCodeCriterion) criterion;
266 + return root.put(CriterionCodec.ICMP_CODE, icmpCodeCriterion.icmpCode());
267 + }
268 + }
269 +
270 + private static class FormatIpV6FLabel implements CriterionTypeFormatter {
271 + @Override
272 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
273 + final IPv6FlowLabelCriterion ipv6FlowLabelCriterion =
274 + (IPv6FlowLabelCriterion) criterion;
275 + return root.put(CriterionCodec.FLOW_LABEL, ipv6FlowLabelCriterion.flowLabel());
276 + }
277 + }
278 +
279 + private static class FormatIcmpV6Type implements CriterionTypeFormatter {
280 + @Override
281 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
282 + final Icmpv6TypeCriterion icmpv6TypeCriterion =
283 + (Icmpv6TypeCriterion) criterion;
284 + return root.put(CriterionCodec.ICMPV6_TYPE, icmpv6TypeCriterion.icmpv6Type());
285 + }
286 + }
287 +
288 + private static class FormatIcmpV6Code implements CriterionTypeFormatter {
289 + @Override
290 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
291 + final Icmpv6CodeCriterion icmpv6CodeCriterion =
292 + (Icmpv6CodeCriterion) criterion;
293 + return root.put(CriterionCodec.ICMPV6_CODE, icmpv6CodeCriterion.icmpv6Code());
294 + }
295 + }
296 +
297 + private static class FormatV6NDTarget implements CriterionTypeFormatter {
298 + @Override
299 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
300 + final IPv6NDTargetAddressCriterion ipv6NDTargetAddressCriterion
301 + = (IPv6NDTargetAddressCriterion) criterion;
302 + return root.put(CriterionCodec.TARGET_ADDRESS, ipv6NDTargetAddressCriterion.targetAddress().toString());
303 + }
304 + }
305 +
306 + private static class FormatV6NDTll implements CriterionTypeFormatter {
307 + @Override
308 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
309 + final IPv6NDLinkLayerAddressCriterion ipv6NDLinkLayerAddressCriterion
310 + = (IPv6NDLinkLayerAddressCriterion) criterion;
311 + return root.put(CriterionCodec.MAC, ipv6NDLinkLayerAddressCriterion.mac().toString());
312 + }
313 + }
314 +
315 + private static class FormatMplsLabel implements CriterionTypeFormatter {
316 + @Override
317 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
318 + final MplsCriterion mplsCriterion =
319 + (MplsCriterion) criterion;
320 + return root.put(CriterionCodec.LABEL, mplsCriterion.label().toInt());
321 + }
322 + }
323 +
324 + private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
325 + @Override
326 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
327 + final IPv6ExthdrFlagsCriterion exthdrCriterion =
328 + (IPv6ExthdrFlagsCriterion) criterion;
329 + return root.put(CriterionCodec.EXT_HDR_FLAGS, exthdrCriterion.exthdrFlags());
330 + }
331 + }
332 +
333 + private static class FormatOchSigId implements CriterionTypeFormatter {
334 + @Override
335 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
336 + OchSignal ochSignal = ((OchSignalCriterion) criterion).lambda();
337 + ObjectNode child = root.putObject(CriterionCodec.OCH_SIGNAL_ID);
338 +
339 + child.put(CriterionCodec.GRID_TYPE, ochSignal.gridType().name());
340 + child.put(CriterionCodec.CHANNEL_SPACING, ochSignal.channelSpacing().name());
341 + child.put(CriterionCodec.SPACING_MULIPLIER, ochSignal.spacingMultiplier());
342 + child.put(CriterionCodec.SLOT_GRANULARITY, ochSignal.slotGranularity());
343 +
344 + return root;
345 + }
346 + }
347 +
348 + private static class FormatOchSigType implements CriterionTypeFormatter {
349 + @Override
350 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
351 + final OchSignalTypeCriterion ochSignalTypeCriterion =
352 + (OchSignalTypeCriterion) criterion;
353 + return root.put("ochSignalType", ochSignalTypeCriterion.signalType().name());
354 + }
355 + }
356 +
357 + private class FormatDummyType implements CriterionTypeFormatter {
358 +
359 + @Override
360 + public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
361 + checkNotNull(criterion, "Criterion cannot be null");
362 +
363 + return root.put(CriterionCodec.TYPE, criterion.type().toString());
364 +
365 + }
366 + }
367 +
368 + /**
369 + * Encodes a criterion into a JSON node.
370 + *
371 + * @return encoded JSON object for the given criterion
372 + */
373 + public ObjectNode encode() {
374 + final ObjectNode result = context.mapper().createObjectNode()
375 + .put(CriterionCodec.TYPE, criterion.type().toString());
376 +
377 + CriterionTypeFormatter formatter =
378 + checkNotNull(
379 + formatMap.get(criterion.type()),
380 + "No formatter found for criterion type "
381 + + criterion.type().toString());
382 +
383 + return formatter.encodeCriterion(result, criterion);
384 + }
385 +
386 +}
1 +/*
2 + * Copyright 2015 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 org.onosproject.codec.CodecContext;
19 +import org.onosproject.net.OchSignal;
20 +import org.onosproject.net.flow.instructions.Instruction;
21 +import org.onosproject.net.flow.instructions.Instructions;
22 +import org.onosproject.net.flow.instructions.L0ModificationInstruction;
23 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
24 +import org.onosproject.net.flow.instructions.L3ModificationInstruction;
25 +import org.slf4j.Logger;
26 +import org.slf4j.LoggerFactory;
27 +
28 +import com.fasterxml.jackson.databind.node.ObjectNode;
29 +
30 +/**
31 + * JSON encoding of Instructions.
32 + */
33 +public final class EncodeInstructionCodec {
34 + protected static final Logger log = LoggerFactory.getLogger(EncodeInstructionCodec.class);
35 + private final Instruction instruction;
36 + private final CodecContext context;
37 +
38 + /**
39 + * Creates an instruction object encoder.
40 + *
41 + * @param instruction instruction to encode
42 + * @param context codec context for the encoding
43 + */
44 + public EncodeInstructionCodec(Instruction instruction, CodecContext context) {
45 + this.instruction = instruction;
46 + this.context = context;
47 + }
48 +
49 +
50 + /**
51 + * Encode an L0 modification instruction.
52 + *
53 + * @param result json node that the instruction attributes are added to
54 + */
55 + private void encodeL0(ObjectNode result) {
56 + L0ModificationInstruction instruction =
57 + (L0ModificationInstruction) this.instruction;
58 + result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
59 +
60 + switch (instruction.subtype()) {
61 + case LAMBDA:
62 + final L0ModificationInstruction.ModLambdaInstruction modLambdaInstruction =
63 + (L0ModificationInstruction.ModLambdaInstruction) instruction;
64 + result.put(InstructionCodec.LAMBDA, modLambdaInstruction.lambda());
65 + break;
66 +
67 + case OCH:
68 + L0ModificationInstruction.ModOchSignalInstruction ochSignalInstruction =
69 + (L0ModificationInstruction.ModOchSignalInstruction) instruction;
70 + OchSignal ochSignal = ochSignalInstruction.lambda();
71 + result.put(InstructionCodec.GRID_TYPE, ochSignal.gridType().name());
72 + result.put(InstructionCodec.CHANNEL_SPACING, ochSignal.channelSpacing().name());
73 + result.put(InstructionCodec.SPACING_MULTIPLIER, ochSignal.spacingMultiplier());
74 + result.put(InstructionCodec.SLOT_GRANULARITY, ochSignal.slotGranularity());
75 + break;
76 +
77 + default:
78 + log.info("Cannot convert L0 subtype of {}", instruction.subtype());
79 + }
80 + }
81 +
82 + /**
83 + * Encode an L2 modification instruction.
84 + *
85 + * @param result json node that the instruction attributes are added to
86 + */
87 + private void encodeL2(ObjectNode result) {
88 + L2ModificationInstruction instruction =
89 + (L2ModificationInstruction) this.instruction;
90 + result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
91 +
92 + switch (instruction.subtype()) {
93 + case ETH_SRC:
94 + case ETH_DST:
95 + final L2ModificationInstruction.ModEtherInstruction modEtherInstruction =
96 + (L2ModificationInstruction.ModEtherInstruction) instruction;
97 + result.put(InstructionCodec.MAC, modEtherInstruction.mac().toString());
98 + break;
99 +
100 + case VLAN_ID:
101 + final L2ModificationInstruction.ModVlanIdInstruction modVlanIdInstruction =
102 + (L2ModificationInstruction.ModVlanIdInstruction) instruction;
103 + result.put(InstructionCodec.VLAN_ID, modVlanIdInstruction.vlanId().toShort());
104 + break;
105 +
106 + case VLAN_PCP:
107 + final L2ModificationInstruction.ModVlanPcpInstruction modVlanPcpInstruction =
108 + (L2ModificationInstruction.ModVlanPcpInstruction) instruction;
109 + result.put(InstructionCodec.VLAN_PCP, modVlanPcpInstruction.vlanPcp());
110 + break;
111 +
112 + case MPLS_LABEL:
113 + final L2ModificationInstruction.ModMplsLabelInstruction modMplsLabelInstruction =
114 + (L2ModificationInstruction.ModMplsLabelInstruction) instruction;
115 + result.put(InstructionCodec.MPLS_LABEL, modMplsLabelInstruction.label());
116 + break;
117 +
118 + case MPLS_PUSH:
119 + final L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
120 + (L2ModificationInstruction.PushHeaderInstructions) instruction;
121 +
122 + result.put(InstructionCodec.ETHERNET_TYPE, pushHeaderInstructions.ethernetType());
123 + break;
124 +
125 + default:
126 + log.info("Cannot convert L2 subtype of {}", instruction.subtype());
127 + break;
128 + }
129 + }
130 +
131 + /**
132 + * Encode an L3 modification instruction.
133 + *
134 + * @param result json node that the instruction attributes are added to
135 + */
136 + private void encodeL3(ObjectNode result) {
137 + L3ModificationInstruction instruction =
138 + (L3ModificationInstruction) this.instruction;
139 + result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
140 + switch (instruction.subtype()) {
141 + case IPV4_SRC:
142 + case IPV4_DST:
143 + case IPV6_SRC:
144 + case IPV6_DST:
145 + final L3ModificationInstruction.ModIPInstruction modIPInstruction =
146 + (L3ModificationInstruction.ModIPInstruction) instruction;
147 + result.put(InstructionCodec.IP, modIPInstruction.ip().toString());
148 + break;
149 +
150 + case IPV6_FLABEL:
151 + final L3ModificationInstruction.ModIPv6FlowLabelInstruction
152 + modFlowLabelInstruction =
153 + (L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction;
154 + result.put(InstructionCodec.FLOW_LABEL, modFlowLabelInstruction.flowLabel());
155 + break;
156 +
157 + default:
158 + log.info("Cannot convert L3 subtype of {}", instruction.subtype());
159 + break;
160 + }
161 + }
162 +
163 + /**
164 + * Encodes the given instruction into JSON.
165 + *
166 + * @return JSON object node representing the instruction
167 + */
168 + public ObjectNode encode() {
169 + final ObjectNode result = context.mapper().createObjectNode()
170 + .put(InstructionCodec.TYPE, instruction.type().toString());
171 +
172 + switch (instruction.type()) {
173 + case OUTPUT:
174 + final Instructions.OutputInstruction outputInstruction =
175 + (Instructions.OutputInstruction) instruction;
176 + result.put(InstructionCodec.PORT, outputInstruction.port().toLong());
177 + break;
178 +
179 + case DROP:
180 + break;
181 +
182 + case L0MODIFICATION:
183 + encodeL0(result);
184 + break;
185 +
186 + case L2MODIFICATION:
187 + encodeL2(result);
188 + break;
189 +
190 + case L3MODIFICATION:
191 + encodeL3(result);
192 + break;
193 +
194 + default:
195 + log.info("Cannot convert instruction type of {}", instruction.type());
196 + break;
197 + }
198 + return result;
199 + }
200 +
201 +}
1 +/*
2 + * Copyright 2015 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 org.onosproject.codec.CodecContext;
19 +import org.onosproject.codec.JsonCodec;
20 +import org.onosproject.core.CoreService;
21 +import org.onosproject.net.DeviceId;
22 +import org.onosproject.net.flow.DefaultFlowRule;
23 +import org.onosproject.net.flow.FlowRule;
24 +import org.onosproject.net.flow.TrafficSelector;
25 +import org.onosproject.net.flow.TrafficTreatment;
26 +
27 +import com.fasterxml.jackson.databind.node.ObjectNode;
28 +
29 +import static org.onlab.util.Tools.nullIsIllegal;
30 +
31 +/**
32 + * Flow rule JSON codec.
33 + */
34 +public final class FlowRuleCodec extends JsonCodec<FlowRule> {
35 +
36 + private static final String APP_ID = "appId";
37 + private static final String PRIORITY = "priority";
38 + private static final String TIMEOUT = "timeout";
39 + private static final String IS_PERMANENT = "isPermanent";
40 + private static final String DEVICE_ID = "deviceId";
41 + private static final String TREATMENT = "treatment";
42 + private static final String SELECTOR = "selector";
43 + private static final String MISSING_MEMBER_MESSAGE =
44 + " member is required in FlowRule";
45 +
46 +
47 + @Override
48 + public FlowRule decode(ObjectNode json, CodecContext context) {
49 + if (json == null || !json.isObject()) {
50 + return null;
51 + }
52 +
53 + FlowRule.Builder resultBuilder = new DefaultFlowRule.Builder();
54 +
55 + short appId = nullIsIllegal(json.get(APP_ID),
56 + APP_ID + MISSING_MEMBER_MESSAGE).shortValue();
57 + CoreService coreService = context.getService(CoreService.class);
58 + resultBuilder.fromApp(coreService.getAppId(appId));
59 +
60 + int priority = nullIsIllegal(json.get(PRIORITY),
61 + PRIORITY + MISSING_MEMBER_MESSAGE).asInt();
62 + resultBuilder.withPriority(priority);
63 +
64 + boolean isPermanent = nullIsIllegal(json.get(IS_PERMANENT),
65 + IS_PERMANENT + MISSING_MEMBER_MESSAGE).asBoolean();
66 + if (isPermanent) {
67 + resultBuilder.makePermanent();
68 + } else {
69 + resultBuilder.makeTemporary(nullIsIllegal(json.get(TIMEOUT),
70 + TIMEOUT
71 + + MISSING_MEMBER_MESSAGE
72 + + " if the flow is temporary").asInt());
73 + }
74 +
75 + DeviceId deviceId = DeviceId.deviceId(nullIsIllegal(json.get(DEVICE_ID),
76 + DEVICE_ID + MISSING_MEMBER_MESSAGE).asText());
77 + resultBuilder.forDevice(deviceId);
78 +
79 + ObjectNode treatmentJson = (ObjectNode) json.get(TREATMENT);
80 + if (treatmentJson != null) {
81 + JsonCodec<TrafficTreatment> treatmentCodec =
82 + context.codec(TrafficTreatment.class);
83 + resultBuilder.withTreatment(treatmentCodec.decode(treatmentJson, context));
84 + }
85 +
86 + ObjectNode selectorJson = (ObjectNode) json.get(SELECTOR);
87 + if (selectorJson != null) {
88 + JsonCodec<TrafficSelector> selectorCodec =
89 + context.codec(TrafficSelector.class);
90 + resultBuilder.withSelector(selectorCodec.decode(selectorJson, context));
91 + }
92 +
93 + return resultBuilder.build();
94 + }
95 +}
...@@ -17,12 +17,7 @@ package org.onosproject.codec.impl; ...@@ -17,12 +17,7 @@ package org.onosproject.codec.impl;
17 17
18 import org.onosproject.codec.CodecContext; 18 import org.onosproject.codec.CodecContext;
19 import org.onosproject.codec.JsonCodec; 19 import org.onosproject.codec.JsonCodec;
20 -import org.onosproject.net.OchSignal;
21 import org.onosproject.net.flow.instructions.Instruction; 20 import org.onosproject.net.flow.instructions.Instruction;
22 -import org.onosproject.net.flow.instructions.Instructions;
23 -import org.onosproject.net.flow.instructions.L0ModificationInstruction;
24 -import org.onosproject.net.flow.instructions.L2ModificationInstruction;
25 -import org.onosproject.net.flow.instructions.L3ModificationInstruction;
26 import org.slf4j.Logger; 21 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
28 23
...@@ -37,159 +32,39 @@ public final class InstructionCodec extends JsonCodec<Instruction> { ...@@ -37,159 +32,39 @@ public final class InstructionCodec extends JsonCodec<Instruction> {
37 32
38 protected static final Logger log = LoggerFactory.getLogger(InstructionCodec.class); 33 protected static final Logger log = LoggerFactory.getLogger(InstructionCodec.class);
39 34
40 - /** 35 + protected static final String TYPE = "type";
41 - * Encode an L0 modification instruction. 36 + protected static final String SUBTYPE = "subtype";
42 - * 37 + protected static final String PORT = "port";
43 - * @param result json node that the instruction attributes are added to 38 + protected static final String MAC = "mac";
44 - * @param instruction The L0 instruction 39 + protected static final String VLAN_ID = "vlanId";
45 - */ 40 + protected static final String VLAN_PCP = "vlanPcp";
46 - private void encodeL0(ObjectNode result, L0ModificationInstruction instruction) { 41 + protected static final String MPLS_LABEL = "label";
47 - result.put("subtype", instruction.subtype().name()); 42 + protected static final String IP = "ip";
48 - 43 + protected static final String FLOW_LABEL = "flowLabel";
49 - switch (instruction.subtype()) { 44 + protected static final String LAMBDA = "lambda";
50 - case LAMBDA: 45 + protected static final String GRID_TYPE = "gridType";
51 - final L0ModificationInstruction.ModLambdaInstruction modLambdaInstruction = 46 + protected static final String CHANNEL_SPACING = "channelSpacing";
52 - (L0ModificationInstruction.ModLambdaInstruction) instruction; 47 + protected static final String SPACING_MULTIPLIER = "spacingMultiplier";
53 - result.put("lambda", modLambdaInstruction.lambda()); 48 + protected static final String SLOT_GRANULARITY = "slotGranularity";
54 - break; 49 + protected static final String ETHERNET_TYPE = "ethernetType";
55 - 50 +
56 - case OCH: 51 + protected static final String MISSING_MEMBER_MESSAGE =
57 - L0ModificationInstruction.ModOchSignalInstruction ochSignalInstruction = 52 + " member is required in Instruction";
58 - (L0ModificationInstruction.ModOchSignalInstruction) instruction;
59 - OchSignal ochSignal = ochSignalInstruction.lambda();
60 - result.put("gridType", ochSignal.gridType().name());
61 - result.put("channelSpacing", ochSignal.channelSpacing().name());
62 - result.put("spacingMultiplier", ochSignal.spacingMultiplier());
63 - result.put("slotGranularity", ochSignal.slotGranularity());
64 - break;
65 -
66 - default:
67 - log.info("Cannot convert L0 subtype of {}", instruction.subtype());
68 - }
69 - }
70 -
71 - /**
72 - * Encode an L2 modification instruction.
73 - *
74 - * @param result json node that the instruction attributes are added to
75 - * @param instruction The L2 instruction
76 - * @param context context of the request
77 - */
78 - private void encodeL2(ObjectNode result,
79 - L2ModificationInstruction instruction,
80 - CodecContext context) {
81 - result.put("subtype", instruction.subtype().name());
82 -
83 - switch (instruction.subtype()) {
84 - case ETH_SRC:
85 - case ETH_DST:
86 - final L2ModificationInstruction.ModEtherInstruction modEtherInstruction =
87 - (L2ModificationInstruction.ModEtherInstruction) instruction;
88 - result.put("mac", modEtherInstruction.mac().toString());
89 - break;
90 -
91 - case VLAN_ID:
92 - final L2ModificationInstruction.ModVlanIdInstruction modVlanIdInstruction =
93 - (L2ModificationInstruction.ModVlanIdInstruction) instruction;
94 - result.put("vlanId", modVlanIdInstruction.vlanId().toShort());
95 - break;
96 -
97 - case VLAN_PCP:
98 - final L2ModificationInstruction.ModVlanPcpInstruction modVlanPcpInstruction =
99 - (L2ModificationInstruction.ModVlanPcpInstruction) instruction;
100 - result.put("vlanPcp", modVlanPcpInstruction.vlanPcp());
101 - break;
102 -
103 - case MPLS_LABEL:
104 - final L2ModificationInstruction.ModMplsLabelInstruction modMplsLabelInstruction =
105 - (L2ModificationInstruction.ModMplsLabelInstruction) instruction;
106 - result.put("label", modMplsLabelInstruction.label());
107 - break;
108 -
109 - case MPLS_PUSH:
110 - final L2ModificationInstruction.PushHeaderInstructions pushHeaderInstructions =
111 - (L2ModificationInstruction.PushHeaderInstructions) instruction;
112 -
113 - result.put("ethernetType", pushHeaderInstructions.ethernetType());
114 - break;
115 -
116 - default:
117 - log.info("Cannot convert L2 subtype of {}", instruction.subtype());
118 - break;
119 - }
120 - }
121 -
122 - /**
123 - * Encode an L3 modification instruction.
124 - *
125 - * @param result json node that the instruction attributes are added to
126 - * @param instruction The L3 instruction
127 - */
128 - private void encodeL3(ObjectNode result, L3ModificationInstruction instruction) {
129 - result.put("subtype", instruction.subtype().name());
130 - switch (instruction.subtype()) {
131 - case IPV4_SRC:
132 - case IPV4_DST:
133 - case IPV6_SRC:
134 - case IPV6_DST:
135 - final L3ModificationInstruction.ModIPInstruction modIPInstruction =
136 - (L3ModificationInstruction.ModIPInstruction) instruction;
137 - result.put("ip", modIPInstruction.ip().toString());
138 - break;
139 53
140 - case IPV6_FLABEL:
141 - final L3ModificationInstruction.ModIPv6FlowLabelInstruction
142 - modFlowLabelInstruction =
143 - (L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction;
144 - result.put("flowLabel", modFlowLabelInstruction.flowLabel());
145 - break;
146 -
147 - default:
148 - log.info("Cannot convert L3 subtype of {}", instruction.subtype());
149 - break;
150 - }
151 - }
152 54
153 @Override 55 @Override
154 public ObjectNode encode(Instruction instruction, CodecContext context) { 56 public ObjectNode encode(Instruction instruction, CodecContext context) {
155 checkNotNull(instruction, "Instruction cannot be null"); 57 checkNotNull(instruction, "Instruction cannot be null");
156 58
157 - final ObjectNode result = context.mapper().createObjectNode() 59 + return new EncodeInstructionCodec(instruction, context).encode();
158 - .put("type", instruction.type().toString()); 60 + }
159 -
160 -
161 - switch (instruction.type()) {
162 - case OUTPUT:
163 - final Instructions.OutputInstruction outputInstruction =
164 - (Instructions.OutputInstruction) instruction;
165 - result.put("port", outputInstruction.port().toLong());
166 - break;
167 -
168 - case DROP:
169 - break;
170 -
171 - case L0MODIFICATION:
172 - final L0ModificationInstruction l0ModificationInstruction =
173 - (L0ModificationInstruction) instruction;
174 - encodeL0(result, l0ModificationInstruction);
175 - break;
176 -
177 - case L2MODIFICATION:
178 - final L2ModificationInstruction l2ModificationInstruction =
179 - (L2ModificationInstruction) instruction;
180 - encodeL2(result, l2ModificationInstruction, context);
181 - break;
182 -
183 - case L3MODIFICATION:
184 - final L3ModificationInstruction l3ModificationInstruction =
185 - (L3ModificationInstruction) instruction;
186 - encodeL3(result, l3ModificationInstruction);
187 - break;
188 61
189 - default: 62 + @Override
190 - log.info("Cannot convert instruction type of {}", instruction.type()); 63 + public Instruction decode(ObjectNode json, CodecContext context) {
191 - break; 64 + if (json == null || !json.isObject()) {
65 + return null;
192 } 66 }
193 - return result; 67 +
68 + return new DecodeInstructionCodec(json).decode();
194 } 69 }
195 } 70 }
......
...@@ -15,11 +15,15 @@ ...@@ -15,11 +15,15 @@
15 */ 15 */
16 package org.onosproject.codec.impl; 16 package org.onosproject.codec.impl;
17 17
18 +import java.util.stream.IntStream;
19 +
18 import org.onosproject.codec.CodecContext; 20 import org.onosproject.codec.CodecContext;
19 import org.onosproject.codec.JsonCodec; 21 import org.onosproject.codec.JsonCodec;
22 +import org.onosproject.net.flow.DefaultTrafficSelector;
20 import org.onosproject.net.flow.TrafficSelector; 23 import org.onosproject.net.flow.TrafficSelector;
21 import org.onosproject.net.flow.criteria.Criterion; 24 import org.onosproject.net.flow.criteria.Criterion;
22 25
26 +import com.fasterxml.jackson.databind.JsonNode;
23 import com.fasterxml.jackson.databind.node.ArrayNode; 27 import com.fasterxml.jackson.databind.node.ArrayNode;
24 import com.fasterxml.jackson.databind.node.ObjectNode; 28 import com.fasterxml.jackson.databind.node.ObjectNode;
25 29
...@@ -29,12 +33,14 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -29,12 +33,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
29 * Traffic selector codec. 33 * Traffic selector codec.
30 */ 34 */
31 public final class TrafficSelectorCodec extends JsonCodec<TrafficSelector> { 35 public final class TrafficSelectorCodec extends JsonCodec<TrafficSelector> {
36 + private static final String CRITERIA = "criteria";
37 +
32 @Override 38 @Override
33 public ObjectNode encode(TrafficSelector selector, CodecContext context) { 39 public ObjectNode encode(TrafficSelector selector, CodecContext context) {
34 checkNotNull(selector, "Traffic selector cannot be null"); 40 checkNotNull(selector, "Traffic selector cannot be null");
35 41
36 final ObjectNode result = context.mapper().createObjectNode(); 42 final ObjectNode result = context.mapper().createObjectNode();
37 - final ArrayNode jsonCriteria = result.putArray("criteria"); 43 + final ArrayNode jsonCriteria = result.putArray(CRITERIA);
38 44
39 if (selector.criteria() != null) { 45 if (selector.criteria() != null) {
40 final JsonCodec<Criterion> criterionCodec = 46 final JsonCodec<Criterion> criterionCodec =
...@@ -46,4 +52,20 @@ public final class TrafficSelectorCodec extends JsonCodec<TrafficSelector> { ...@@ -46,4 +52,20 @@ public final class TrafficSelectorCodec extends JsonCodec<TrafficSelector> {
46 52
47 return result; 53 return result;
48 } 54 }
55 +
56 + @Override
57 + public TrafficSelector decode(ObjectNode json, CodecContext context) {
58 + final JsonCodec<Criterion> criterionCodec =
59 + context.codec(Criterion.class);
60 +
61 + JsonNode criteriaJson = json.get(CRITERIA);
62 + TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
63 + if (criteriaJson != null) {
64 + IntStream.range(0, criteriaJson.size())
65 + .forEach(i -> builder.add(
66 + criterionCodec.decode((ObjectNode) criteriaJson.get(i),
67 + context)));
68 + }
69 + return builder.build();
70 + }
49 } 71 }
......
...@@ -15,11 +15,15 @@ ...@@ -15,11 +15,15 @@
15 */ 15 */
16 package org.onosproject.codec.impl; 16 package org.onosproject.codec.impl;
17 17
18 +import java.util.stream.IntStream;
19 +
18 import org.onosproject.codec.CodecContext; 20 import org.onosproject.codec.CodecContext;
19 import org.onosproject.codec.JsonCodec; 21 import org.onosproject.codec.JsonCodec;
22 +import org.onosproject.net.flow.DefaultTrafficTreatment;
20 import org.onosproject.net.flow.TrafficTreatment; 23 import org.onosproject.net.flow.TrafficTreatment;
21 import org.onosproject.net.flow.instructions.Instruction; 24 import org.onosproject.net.flow.instructions.Instruction;
22 25
26 +import com.fasterxml.jackson.databind.JsonNode;
23 import com.fasterxml.jackson.databind.node.ArrayNode; 27 import com.fasterxml.jackson.databind.node.ArrayNode;
24 import com.fasterxml.jackson.databind.node.ObjectNode; 28 import com.fasterxml.jackson.databind.node.ObjectNode;
25 29
...@@ -29,12 +33,14 @@ import static com.google.common.base.Preconditions.checkNotNull; ...@@ -29,12 +33,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
29 * Traffic treatment codec. 33 * Traffic treatment codec.
30 */ 34 */
31 public final class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> { 35 public final class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> {
36 + private static final String INSTRUCTIONS = "instructions";
37 +
32 @Override 38 @Override
33 public ObjectNode encode(TrafficTreatment treatment, CodecContext context) { 39 public ObjectNode encode(TrafficTreatment treatment, CodecContext context) {
34 checkNotNull(treatment, "Traffic treatment cannot be null"); 40 checkNotNull(treatment, "Traffic treatment cannot be null");
35 41
36 final ObjectNode result = context.mapper().createObjectNode(); 42 final ObjectNode result = context.mapper().createObjectNode();
37 - final ArrayNode jsonInstructions = result.putArray("instructions"); 43 + final ArrayNode jsonInstructions = result.putArray(INSTRUCTIONS);
38 44
39 final JsonCodec<Instruction> instructionCodec = 45 final JsonCodec<Instruction> instructionCodec =
40 context.codec(Instruction.class); 46 context.codec(Instruction.class);
...@@ -51,4 +57,20 @@ public final class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> { ...@@ -51,4 +57,20 @@ public final class TrafficTreatmentCodec extends JsonCodec<TrafficTreatment> {
51 57
52 return result; 58 return result;
53 } 59 }
60 +
61 + @Override
62 + public TrafficTreatment decode(ObjectNode json, CodecContext context) {
63 + final JsonCodec<Instruction> instructionsCodec =
64 + context.codec(Instruction.class);
65 +
66 + JsonNode instructionsJson = json.get(INSTRUCTIONS);
67 + TrafficTreatment.Builder builder = DefaultTrafficTreatment.builder();
68 + if (instructionsJson != null) {
69 + IntStream.range(0, instructionsJson.size())
70 + .forEach(i -> builder.add(
71 + instructionsCodec.decode((ObjectNode) instructionsJson.get(i),
72 + context)));
73 + }
74 + return builder.build();
75 + }
54 } 76 }
......
...@@ -72,8 +72,10 @@ public class CriterionCodecTest { ...@@ -72,8 +72,10 @@ public class CriterionCodecTest {
72 */ 72 */
73 @Test 73 @Test
74 public void checkCriterionTypes() throws Exception { 74 public void checkCriterionTypes() throws Exception {
75 + EncodeCriterionCodec encoder = new EncodeCriterionCodec(
76 + Criteria.dummy(), context);
75 EnumMap<Criterion.Type, Object> formatMap = 77 EnumMap<Criterion.Type, Object> formatMap =
76 - getField(criterionCodec, "formatMap"); 78 + getField(encoder, "formatMap");
77 assertThat(formatMap, notNullValue()); 79 assertThat(formatMap, notNullValue());
78 80
79 for (Criterion.Type type : Criterion.Type.values()) { 81 for (Criterion.Type type : Criterion.Type.values()) {
......
1 +/*
2 + * Copyright 2015 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 java.io.IOException;
19 +import java.io.InputStream;
20 +import java.util.SortedMap;
21 +import java.util.TreeMap;
22 +
23 +import org.junit.Before;
24 +import org.junit.Test;
25 +import org.onlab.packet.Ethernet;
26 +import org.onlab.packet.IpAddress;
27 +import org.onlab.packet.IpPrefix;
28 +import org.onlab.packet.MacAddress;
29 +import org.onlab.packet.MplsLabel;
30 +import org.onlab.packet.VlanId;
31 +import org.onosproject.codec.JsonCodec;
32 +import org.onosproject.core.CoreService;
33 +import org.onosproject.net.ChannelSpacing;
34 +import org.onosproject.net.GridType;
35 +import org.onosproject.net.Lambda;
36 +import org.onosproject.net.OchSignal;
37 +import org.onosproject.net.PortNumber;
38 +import org.onosproject.net.flow.FlowRule;
39 +import org.onosproject.net.flow.criteria.Criterion;
40 +import org.onosproject.net.flow.criteria.EthCriterion;
41 +import org.onosproject.net.flow.criteria.EthTypeCriterion;
42 +import org.onosproject.net.flow.criteria.IPCriterion;
43 +import org.onosproject.net.flow.criteria.IPDscpCriterion;
44 +import org.onosproject.net.flow.criteria.IPEcnCriterion;
45 +import org.onosproject.net.flow.criteria.IPProtocolCriterion;
46 +import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
47 +import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
48 +import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
49 +import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
50 +import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
51 +import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
52 +import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
53 +import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
54 +import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
55 +import org.onosproject.net.flow.criteria.MplsCriterion;
56 +import org.onosproject.net.flow.criteria.OchSignalCriterion;
57 +import org.onosproject.net.flow.criteria.PortCriterion;
58 +import org.onosproject.net.flow.criteria.SctpPortCriterion;
59 +import org.onosproject.net.flow.criteria.TcpPortCriterion;
60 +import org.onosproject.net.flow.criteria.UdpPortCriterion;
61 +import org.onosproject.net.flow.criteria.VlanIdCriterion;
62 +import org.onosproject.net.flow.criteria.VlanPcpCriterion;
63 +import org.onosproject.net.flow.instructions.Instruction;
64 +import org.onosproject.net.flow.instructions.Instructions;
65 +import org.onosproject.net.flow.instructions.L0ModificationInstruction;
66 +import org.onosproject.net.flow.instructions.L2ModificationInstruction;
67 +import org.onosproject.net.flow.instructions.L3ModificationInstruction;
68 +
69 +import com.fasterxml.jackson.databind.JsonNode;
70 +import com.fasterxml.jackson.databind.node.ObjectNode;
71 +
72 +import static org.easymock.EasyMock.createMock;
73 +import static org.easymock.EasyMock.expect;
74 +import static org.easymock.EasyMock.replay;
75 +import static org.hamcrest.MatcherAssert.assertThat;
76 +import static org.hamcrest.Matchers.instanceOf;
77 +import static org.hamcrest.Matchers.is;
78 +import static org.hamcrest.Matchers.notNullValue;
79 +import static org.onosproject.net.NetTestTools.APP_ID;
80 +
81 +/**
82 + * Flow rule codec unit tests.
83 + */
84 +public class FlowRuleCodecTest {
85 +
86 + MockCodecContext context;
87 + JsonCodec<FlowRule> flowRuleCodec;
88 + final CoreService mockCoreService = createMock(CoreService.class);
89 +
90 + /**
91 + * Sets up for each test. Creates a context and fetches the flow rule
92 + * codec.
93 + */
94 + @Before
95 + public void setUp() {
96 + context = new MockCodecContext();
97 + flowRuleCodec = context.codec(FlowRule.class);
98 + assertThat(flowRuleCodec, notNullValue());
99 +
100 + expect(mockCoreService.getAppId(APP_ID.id()))
101 + .andReturn(APP_ID).anyTimes();
102 + replay(mockCoreService);
103 + context.registerService(CoreService.class, mockCoreService);
104 + }
105 +
106 + /**
107 + * Reads in a rule from the given resource and decodes it.
108 + *
109 + * @param resourceName resource to use to read the JSON for the rule
110 + * @return decoded flow rule
111 + * @throws IOException if processing the resource fails
112 + */
113 + private FlowRule getRule(String resourceName) throws IOException {
114 + InputStream jsonStream = FlowRuleCodecTest.class
115 + .getResourceAsStream(resourceName);
116 + JsonNode json = context.mapper().readTree(jsonStream);
117 + assertThat(json, notNullValue());
118 + FlowRule rule = flowRuleCodec.decode((ObjectNode) json, context);
119 + assertThat(rule, notNullValue());
120 + return rule;
121 + }
122 +
123 + /**
124 + * Checks that the data shared by all the resources is correct for a
125 + * given rule.
126 + *
127 + * @param rule rule to check
128 + */
129 + private void checkCommonData(FlowRule rule) {
130 + assertThat(rule.appId(), is(APP_ID.id()));
131 + assertThat(rule.isPermanent(), is(false));
132 + assertThat(rule.timeout(), is(1));
133 + assertThat(rule.priority(), is(1));
134 + assertThat(rule.deviceId().toString(), is("of:0000000000000001"));
135 + }
136 +
137 + /**
138 + * Checks that a simple rule decodes properly.
139 + *
140 + * @throws IOException if the resource cannot be processed
141 + */
142 + @Test
143 + public void codecSimpleFlowTest() throws IOException {
144 + FlowRule rule = getRule("simple-flow.json");
145 +
146 + checkCommonData(rule);
147 +
148 + assertThat(rule.selector().criteria().size(), is(1));
149 + Criterion criterion1 = rule.selector().criteria().iterator().next();
150 + assertThat(criterion1.type(), is(Criterion.Type.ETH_TYPE));
151 + assertThat(((EthTypeCriterion) criterion1).ethType(), is(2054));
152 +
153 + assertThat(rule.treatment().allInstructions().size(), is(1));
154 + Instruction instruction1 = rule.treatment().allInstructions().get(0);
155 + assertThat(instruction1.type(), is(Instruction.Type.OUTPUT));
156 + assertThat(((Instructions.OutputInstruction) instruction1).port(), is(PortNumber.CONTROLLER));
157 + }
158 +
159 + SortedMap<String, Instruction> instructions = new TreeMap<>();
160 +
161 + /**
162 + * Looks up an instruction in the instruction map based on type and subtype.
163 + *
164 + * @param type type string
165 + * @param subType subtype string
166 + * @return instruction that matches
167 + */
168 + private Instruction getInstruction(Instruction.Type type, String subType) {
169 + Instruction instruction = instructions.get(type.name() + "/" + subType);
170 + assertThat(instruction, notNullValue());
171 + assertThat(instruction.type(), is(type));
172 + return instruction;
173 + }
174 +
175 + /**
176 + * Checks that a rule with one of each instruction type decodes properly.
177 + *
178 + * @throws IOException if the resource cannot be processed
179 + */
180 + @Test
181 + public void decodeInstructionsFlowTest() throws Exception {
182 + FlowRule rule = getRule("instructions-flow.json");
183 +
184 + checkCommonData(rule);
185 +
186 + rule.treatment().allInstructions()
187 + .stream()
188 + .forEach(instruction ->
189 + {
190 + String subType;
191 + if (instruction.type() == Instruction.Type.L0MODIFICATION) {
192 + subType = ((L0ModificationInstruction) instruction)
193 + .subtype().name();
194 + } else if (instruction.type() == Instruction.Type.L2MODIFICATION) {
195 + subType = ((L2ModificationInstruction) instruction)
196 + .subtype().name();
197 + } else if (instruction.type() == Instruction.Type.L3MODIFICATION) {
198 + subType = ((L3ModificationInstruction) instruction)
199 + .subtype().name();
200 + } else {
201 + subType = "";
202 + }
203 + instructions.put(
204 + instruction.type().name() + "/" + subType, instruction);
205 + });
206 +
207 + assertThat(rule.treatment().allInstructions().size(), is(19));
208 +
209 + Instruction instruction;
210 +
211 + instruction = getInstruction(Instruction.Type.OUTPUT, "");
212 + assertThat(instruction.type(), is(Instruction.Type.OUTPUT));
213 + assertThat(((Instructions.OutputInstruction) instruction).port(), is(PortNumber.CONTROLLER));
214 +
215 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
216 + L2ModificationInstruction.L2SubType.ETH_SRC.name());
217 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
218 + assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
219 + is(MacAddress.valueOf("12:34:56:78:90:12")));
220 +
221 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
222 + L2ModificationInstruction.L2SubType.ETH_DST.name());
223 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
224 + assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
225 + is(MacAddress.valueOf("98:76:54:32:01:00")));
226 +
227 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
228 + L2ModificationInstruction.L2SubType.VLAN_ID.name());
229 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
230 + assertThat(((L2ModificationInstruction.ModVlanIdInstruction) instruction).vlanId().toShort(),
231 + is((short) 22));
232 +
233 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
234 + L2ModificationInstruction.L2SubType.VLAN_PCP.name());
235 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
236 + assertThat(((L2ModificationInstruction.ModVlanPcpInstruction) instruction).vlanPcp(),
237 + is((byte) 1));
238 +
239 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
240 + L2ModificationInstruction.L2SubType.MPLS_LABEL.name());
241 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
242 + assertThat(((L2ModificationInstruction.ModMplsLabelInstruction) instruction)
243 + .label().shortValue(),
244 + is((short) 777));
245 +
246 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
247 + L2ModificationInstruction.L2SubType.MPLS_PUSH.name());
248 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
249 + assertThat((short) ((L2ModificationInstruction.PushHeaderInstructions) instruction)
250 + .ethernetType(),
251 + is(Ethernet.MPLS_UNICAST));
252 +
253 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
254 + L2ModificationInstruction.L2SubType.MPLS_POP.name());
255 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
256 + assertThat((short) ((L2ModificationInstruction.PushHeaderInstructions) instruction)
257 + .ethernetType(),
258 + is(Ethernet.MPLS_UNICAST));
259 +
260 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
261 + L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name());
262 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
263 + assertThat(instruction, instanceOf(L2ModificationInstruction.ModMplsTtlInstruction.class));
264 +
265 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
266 + L2ModificationInstruction.L2SubType.VLAN_POP.name());
267 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
268 + assertThat(instruction, instanceOf(L2ModificationInstruction.PopVlanInstruction.class));
269 +
270 + instruction = getInstruction(Instruction.Type.L2MODIFICATION,
271 + L2ModificationInstruction.L2SubType.VLAN_PUSH.name());
272 + assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
273 + assertThat(instruction, instanceOf(L2ModificationInstruction.PushHeaderInstructions.class));
274 +
275 + instruction = getInstruction(Instruction.Type.L3MODIFICATION,
276 + L3ModificationInstruction.L3SubType.IPV4_SRC.name());
277 + assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
278 + assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
279 + is(IpAddress.valueOf("1.2.3.4")));
280 +
281 + instruction = getInstruction(Instruction.Type.L3MODIFICATION,
282 + L3ModificationInstruction.L3SubType.IPV4_DST.name());
283 + assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
284 + assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
285 + is(IpAddress.valueOf("1.2.3.3")));
286 +
287 + instruction = getInstruction(Instruction.Type.L3MODIFICATION,
288 + L3ModificationInstruction.L3SubType.IPV6_SRC.name());
289 + assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
290 + assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
291 + is(IpAddress.valueOf("1.2.3.2")));
292 +
293 + instruction = getInstruction(Instruction.Type.L3MODIFICATION,
294 + L3ModificationInstruction.L3SubType.IPV6_DST.name());
295 + assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
296 + assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
297 + is(IpAddress.valueOf("1.2.3.1")));
298 +
299 + instruction = getInstruction(Instruction.Type.L3MODIFICATION,
300 + L3ModificationInstruction.L3SubType.IPV6_FLABEL.name());
301 + assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
302 + assertThat(((L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction)
303 + .flowLabel(),
304 + is(8));
305 +
306 + instruction = getInstruction(Instruction.Type.L0MODIFICATION,
307 + L0ModificationInstruction.L0SubType.LAMBDA.name());
308 + assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
309 + assertThat(((L0ModificationInstruction.ModLambdaInstruction) instruction)
310 + .lambda(),
311 + is((short) 7));
312 +
313 + instruction = getInstruction(Instruction.Type.L0MODIFICATION,
314 + L0ModificationInstruction.L0SubType.OCH.name());
315 + assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
316 + L0ModificationInstruction.ModOchSignalInstruction och =
317 + (L0ModificationInstruction.ModOchSignalInstruction) instruction;
318 + assertThat(och.lambda().spacingMultiplier(), is(4));
319 + assertThat(och.lambda().slotGranularity(), is(8));
320 + assertThat(och.lambda().gridType(), is(GridType.DWDM));
321 + assertThat(och.lambda().channelSpacing(), is(ChannelSpacing.CHL_100GHZ));
322 + }
323 +
324 + SortedMap<String, Criterion> criteria = new TreeMap<>();
325 +
326 + /**
327 + * Looks up a criterion in the instruction map based on type and subtype.
328 + *
329 + * @param type type string
330 + * @return criterion that matches
331 + */
332 + private Criterion getCriterion(Criterion.Type type) {
333 + Criterion criterion = criteria.get(type.name());
334 + assertThat(criterion.type(), is(type));
335 + return criterion;
336 + }
337 +
338 + /**
339 + * Checks that a rule with one of each kind of criterion decodes properly.
340 + *
341 + * @throws IOException if the resource cannot be processed
342 + */
343 + @Test
344 + public void codecCriteriaFlowTest() throws Exception {
345 + FlowRule rule = getRule("criteria-flow.json");
346 +
347 + checkCommonData(rule);
348 +
349 + assertThat(rule.selector().criteria().size(), is(32));
350 +
351 + rule.selector().criteria()
352 + .stream()
353 + .forEach(criterion ->
354 + criteria.put(criterion.type().name(), criterion));
355 +
356 + Criterion criterion;
357 +
358 + criterion = getCriterion(Criterion.Type.ETH_TYPE);
359 + assertThat(((EthTypeCriterion) criterion).ethType(), is(2054));
360 +
361 + criterion = getCriterion(Criterion.Type.ETH_DST);
362 + assertThat(((EthCriterion) criterion).mac(),
363 + is(MacAddress.valueOf("00:11:22:33:44:55")));
364 +
365 + criterion = getCriterion(Criterion.Type.ETH_SRC);
366 + assertThat(((EthCriterion) criterion).mac(),
367 + is(MacAddress.valueOf("00:11:22:33:44:55")));
368 +
369 + criterion = getCriterion(Criterion.Type.IN_PORT);
370 + assertThat(((PortCriterion) criterion).port(),
371 + is(PortNumber.portNumber(23)));
372 +
373 + criterion = getCriterion(Criterion.Type.IN_PHY_PORT);
374 + assertThat(((PortCriterion) criterion).port(),
375 + is(PortNumber.portNumber(44)));
376 +
377 + criterion = getCriterion(Criterion.Type.VLAN_VID);
378 + assertThat(((VlanIdCriterion) criterion).vlanId(),
379 + is(VlanId.vlanId((short) 777)));
380 +
381 + criterion = getCriterion(Criterion.Type.VLAN_PCP);
382 + assertThat(((VlanPcpCriterion) criterion).priority(),
383 + is(((byte) 3)));
384 +
385 + criterion = getCriterion(Criterion.Type.IP_DSCP);
386 + assertThat(((IPDscpCriterion) criterion).ipDscp(),
387 + is(((byte) 2)));
388 +
389 + criterion = getCriterion(Criterion.Type.IP_ECN);
390 + assertThat(((IPEcnCriterion) criterion).ipEcn(),
391 + is(((byte) 1)));
392 +
393 + criterion = getCriterion(Criterion.Type.IP_PROTO);
394 + assertThat(((IPProtocolCriterion) criterion).protocol(),
395 + is(((short) 4)));
396 +
397 + criterion = getCriterion(Criterion.Type.IPV4_SRC);
398 + assertThat(((IPCriterion) criterion).ip(),
399 + is((IpPrefix.valueOf("1.2.0.0/32"))));
400 +
401 + criterion = getCriterion(Criterion.Type.IPV4_DST);
402 + assertThat(((IPCriterion) criterion).ip(),
403 + is((IpPrefix.valueOf("2.2.0.0/32"))));
404 +
405 + criterion = getCriterion(Criterion.Type.IPV6_SRC);
406 + assertThat(((IPCriterion) criterion).ip(),
407 + is((IpPrefix.valueOf("3.2.0.0/32"))));
408 +
409 + criterion = getCriterion(Criterion.Type.IPV6_DST);
410 + assertThat(((IPCriterion) criterion).ip(),
411 + is((IpPrefix.valueOf("4.2.0.0/32"))));
412 +
413 + criterion = getCriterion(Criterion.Type.TCP_SRC);
414 + assertThat(((TcpPortCriterion) criterion).tcpPort(),
415 + is(80));
416 +
417 + criterion = getCriterion(Criterion.Type.TCP_DST);
418 + assertThat(((TcpPortCriterion) criterion).tcpPort(),
419 + is(443));
420 +
421 + criterion = getCriterion(Criterion.Type.UDP_SRC);
422 + assertThat(((UdpPortCriterion) criterion).udpPort(),
423 + is(180));
424 +
425 + criterion = getCriterion(Criterion.Type.UDP_DST);
426 + assertThat(((UdpPortCriterion) criterion).udpPort(),
427 + is(1443));
428 +
429 + criterion = getCriterion(Criterion.Type.SCTP_SRC);
430 + assertThat(((SctpPortCriterion) criterion).sctpPort(),
431 + is(280));
432 +
433 + criterion = getCriterion(Criterion.Type.SCTP_DST);
434 + assertThat(((SctpPortCriterion) criterion).sctpPort(),
435 + is(2443));
436 +
437 + criterion = getCriterion(Criterion.Type.ICMPV4_TYPE);
438 + assertThat(((IcmpTypeCriterion) criterion).icmpType(),
439 + is((short) 24));
440 +
441 + criterion = getCriterion(Criterion.Type.ICMPV4_CODE);
442 + assertThat(((IcmpCodeCriterion) criterion).icmpCode(),
443 + is((short) 16));
444 +
445 + criterion = getCriterion(Criterion.Type.ICMPV6_TYPE);
446 + assertThat(((Icmpv6TypeCriterion) criterion).icmpv6Type(),
447 + is((short) 14));
448 +
449 + criterion = getCriterion(Criterion.Type.ICMPV6_CODE);
450 + assertThat(((Icmpv6CodeCriterion) criterion).icmpv6Code(),
451 + is((short) 6));
452 +
453 + criterion = getCriterion(Criterion.Type.IPV6_FLABEL);
454 + assertThat(((IPv6FlowLabelCriterion) criterion).flowLabel(),
455 + is(8));
456 +
457 + criterion = getCriterion(Criterion.Type.IPV6_ND_TARGET);
458 + assertThat(((IPv6NDTargetAddressCriterion) criterion)
459 + .targetAddress().toString(),
460 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
461 +
462 + criterion = getCriterion(Criterion.Type.IPV6_ND_SLL);
463 + assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
464 + is(MacAddress.valueOf("00:11:22:33:44:56")));
465 +
466 + criterion = getCriterion(Criterion.Type.IPV6_ND_TLL);
467 + assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
468 + is(MacAddress.valueOf("00:11:22:33:44:57")));
469 +
470 + criterion = getCriterion(Criterion.Type.MPLS_LABEL);
471 + assertThat(((MplsCriterion) criterion).label(),
472 + is(MplsLabel.mplsLabel(123)));
473 +
474 + criterion = getCriterion(Criterion.Type.IPV6_EXTHDR);
475 + assertThat(((IPv6ExthdrFlagsCriterion) criterion).exthdrFlags(),
476 + is(99));
477 +
478 + criterion = getCriterion(Criterion.Type.OCH_SIGID);
479 + assertThat(((IndexedLambdaCriterion) criterion).lambda(),
480 + is(Lambda.indexedLambda(122)));
481 + }
482 +
483 + /**
484 + * Checks that a rule with a SigId criterion decodes properly.
485 + *
486 + * @throws IOException if the resource cannot be processed
487 + */
488 + @Test
489 + public void codecSigIdCriteriaFlowTest() throws Exception {
490 + FlowRule rule = getRule("sigid-flow.json");
491 +
492 + checkCommonData(rule);
493 +
494 + assertThat(rule.selector().criteria().size(), is(1));
495 + Criterion criterion = rule.selector().criteria().iterator().next();
496 + assertThat(criterion.type(), is(Criterion.Type.OCH_SIGID));
497 + Lambda lambda = ((OchSignalCriterion) criterion).lambda();
498 + assertThat(lambda, instanceOf(OchSignal.class));
499 + OchSignal ochSignal = (OchSignal) lambda;
500 + assertThat(ochSignal.spacingMultiplier(), is(3));
501 + assertThat(ochSignal.slotGranularity(), is(4));
502 + assertThat(ochSignal.gridType(), is(GridType.CWDM));
503 + assertThat(ochSignal.channelSpacing(), is(ChannelSpacing.CHL_25GHZ));
504 + }
505 +
506 +}
...@@ -38,6 +38,8 @@ public class ImmutableCodecsTest { ...@@ -38,6 +38,8 @@ public class ImmutableCodecsTest {
38 assertThatClassIsImmutable(ConnectPointCodec.class); 38 assertThatClassIsImmutable(ConnectPointCodec.class);
39 assertThatClassIsImmutable(ConstraintCodec.class); 39 assertThatClassIsImmutable(ConstraintCodec.class);
40 assertThatClassIsImmutable(CriterionCodec.class); 40 assertThatClassIsImmutable(CriterionCodec.class);
41 + assertThatClassIsImmutable(EncodeCriterionCodec.class);
42 + assertThatClassIsImmutable(DecodeCriterionCodec.class);
41 assertThatClassIsImmutable(DeviceCodec.class); 43 assertThatClassIsImmutable(DeviceCodec.class);
42 assertThatClassIsImmutable(EthernetCodec.class); 44 assertThatClassIsImmutable(EthernetCodec.class);
43 assertThatClassIsImmutable(FlowEntryCodec.class); 45 assertThatClassIsImmutable(FlowEntryCodec.class);
...@@ -45,6 +47,8 @@ public class ImmutableCodecsTest { ...@@ -45,6 +47,8 @@ public class ImmutableCodecsTest {
45 assertThatClassIsImmutable(HostLocationCodec.class); 47 assertThatClassIsImmutable(HostLocationCodec.class);
46 assertThatClassIsImmutable(HostToHostIntentCodec.class); 48 assertThatClassIsImmutable(HostToHostIntentCodec.class);
47 assertThatClassIsImmutable(InstructionCodec.class); 49 assertThatClassIsImmutable(InstructionCodec.class);
50 + assertThatClassIsImmutable(EncodeInstructionCodec.class);
51 + assertThatClassIsImmutable(DecodeInstructionCodec.class);
48 assertThatClassIsImmutable(IntentCodec.class); 52 assertThatClassIsImmutable(IntentCodec.class);
49 assertThatClassIsImmutable(LinkCodec.class); 53 assertThatClassIsImmutable(LinkCodec.class);
50 assertThatClassIsImmutable(PathCodec.class); 54 assertThatClassIsImmutable(PathCodec.class);
...@@ -54,5 +58,6 @@ public class ImmutableCodecsTest { ...@@ -54,5 +58,6 @@ public class ImmutableCodecsTest {
54 assertThatClassIsImmutable(TopologyCodec.class); 58 assertThatClassIsImmutable(TopologyCodec.class);
55 assertThatClassIsImmutable(TrafficSelectorCodec.class); 59 assertThatClassIsImmutable(TrafficSelectorCodec.class);
56 assertThatClassIsImmutable(TrafficTreatmentCodec.class); 60 assertThatClassIsImmutable(TrafficTreatmentCodec.class);
61 + assertThatClassIsImmutable(FlowRuleCodec.class);
57 } 62 }
58 } 63 }
......
1 +{
2 + "appId":-29467,
3 + "priority":1,
4 + "isPermanent":"false",
5 + "timeout":1,
6 + "deviceId":"of:0000000000000001",
7 + "selector":
8 + {"criteria":
9 + [
10 + {"type":"IN_PORT", "port":23},
11 + {"type":"IN_PHY_PORT", "port":44},
12 + {"type":"METADATA", "metadata":123456},
13 + {"type":"ETH_TYPE","ethType":2054},
14 + {"type":"ETH_SRC","mac":"00:11:22:33:44:55"},
15 + {"type":"ETH_DST","mac":"00:11:22:33:44:55"},
16 + {"type":"VLAN_VID","vlanId":777},
17 + {"type":"VLAN_PCP","priority":3},
18 + {"type":"IP_DSCP","ipDscp":2},
19 + {"type":"IP_ECN","ipEcn":1},
20 + {"type":"IP_PROTO","protocol":4},
21 + {"type":"IPV4_SRC", "ip":"1.2.0.0/32"},
22 + {"type":"IPV4_DST", "ip":"2.2.0.0/32"},
23 + {"type":"IPV6_SRC", "ip":"3.2.0.0/32"},
24 + {"type":"IPV6_DST", "ip":"4.2.0.0/32"},
25 + {"type":"TCP_SRC", "tcpPort":80},
26 + {"type":"TCP_DST", "tcpPort":443},
27 + {"type":"UDP_SRC", "udpPort":180},
28 + {"type":"UDP_DST", "udpPort":1443},
29 + {"type":"SCTP_SRC", "sctpPort":280},
30 + {"type":"SCTP_DST", "sctpPort":2443},
31 + {"type":"ICMPV4_TYPE", "icmpType":24},
32 + {"type":"ICMPV4_CODE", "icmpCode":16},
33 + {"type":"ICMPV6_TYPE", "icmpv6Type":14},
34 + {"type":"ICMPV6_CODE", "icmpv6Code":6},
35 + {"type":"IPV6_FLABEL", "flowLabel":8},
36 + {"type":"IPV6_ND_TARGET", "targetAddress":"1111:2222:3333:4444:5555:6666:7777:8888"},
37 + {"type":"IPV6_ND_SLL", "mac":"00:11:22:33:44:56"},
38 + {"type":"IPV6_ND_TLL", "mac":"00:11:22:33:44:57"},
39 + {"type":"MPLS_LABEL", "label":123},
40 + {"type":"IPV6_EXTHDR", "exthdrFlags":99},
41 + {"type":"OCH_SIGID", "lambda":122}
42 + ]
43 + }
44 +}
1 +{
2 + "appId":-29467,
3 + "priority":1,
4 + "isPermanent":"false",
5 + "timeout":1,
6 + "deviceId":"of:0000000000000001",
7 + "treatment":
8 + {
9 + "instructions":
10 + [
11 + {"type":"OUTPUT","port":-3},
12 + {"type":"DROP"},
13 + {"type":"L2MODIFICATION","subtype":"ETH_SRC","mac":"12:34:56:78:90:12"},
14 + {"type":"L2MODIFICATION","subtype":"ETH_DST","mac":"98:76:54:32:01:00"},
15 + {"type":"L2MODIFICATION","subtype":"VLAN_ID","vlanId":22},
16 + {"type":"L2MODIFICATION","subtype":"VLAN_PCP","vlanPcp":1},
17 + {"type":"L2MODIFICATION","subtype":"MPLS_LABEL","label":777},
18 + {"type":"L2MODIFICATION","subtype":"MPLS_PUSH"},
19 + {"type":"L2MODIFICATION","subtype":"MPLS_POP"},
20 + {"type":"L2MODIFICATION","subtype":"DEC_MPLS_TTL"},
21 + {"type":"L2MODIFICATION","subtype":"VLAN_POP"},
22 + {"type":"L2MODIFICATION","subtype":"VLAN_PUSH"},
23 + {"type":"L3MODIFICATION","subtype":"IPV4_SRC", "ip":"1.2.3.4"},
24 + {"type":"L3MODIFICATION","subtype":"IPV4_DST", "ip":"1.2.3.3"},
25 + {"type":"L3MODIFICATION","subtype":"IPV6_SRC", "ip":"1.2.3.2"},
26 + {"type":"L3MODIFICATION","subtype":"IPV6_DST", "ip":"1.2.3.1"},
27 + {"type":"L3MODIFICATION","subtype":"IPV6_FLABEL", "flowLabel":8},
28 + {"type":"L0MODIFICATION","subtype":"LAMBDA","lambda":7},
29 + {"type":"L0MODIFICATION","subtype":"OCH","gridType":"DWDM",
30 + "channelSpacing":"CHL_100GHZ","spacingMultiplier":4,"slotGranularity":8}
31 + ],
32 + "deferred":[]
33 + },
34 + "selector": {"criteria":[{"type":"ETH_TYPE","ethType":2054}]}
35 +}
1 +{
2 + "appId":-29467,
3 + "priority":1,
4 + "isPermanent":"false",
5 + "timeout":1,
6 + "deviceId":"of:0000000000000001",
7 + "selector":
8 + {"criteria":
9 + [
10 + {"type":"OCH_SIGID",
11 + "ochSignalId":
12 + {
13 + "gridType":"CWDM",
14 + "channelSpacing":"CHL_25GHZ",
15 + "spacingMultiplier":3,
16 + "slotGranularity":4
17 + }
18 + }
19 + ]
20 + }
21 +}
1 +{
2 + "appId":-29467,
3 + "priority":1,
4 + "isPermanent":"false",
5 + "timeout":1,
6 + "deviceId":"of:0000000000000001",
7 + "treatment":
8 + {"instructions":
9 + [{"type":"OUTPUT","port":-3}],"deferred":[]},
10 + "selector":
11 + {"criteria":
12 + [{"type":"ETH_TYPE","ethType":2054}]}
13 +}
...@@ -123,7 +123,7 @@ public abstract class Tools { ...@@ -123,7 +123,7 @@ public abstract class Tools {
123 } 123 }
124 124
125 /** 125 /**
126 - * Returns the specified item if that items is null; otherwise throws 126 + * Returns the specified item if that item is not null; otherwise throws
127 * not found exception. 127 * not found exception.
128 * 128 *
129 * @param item item to check 129 * @param item item to check
...@@ -140,6 +140,23 @@ public abstract class Tools { ...@@ -140,6 +140,23 @@ public abstract class Tools {
140 } 140 }
141 141
142 /** 142 /**
143 + * Returns the specified item if that item is not null; otherwise throws
144 + * bad argument exception.
145 + *
146 + * @param item item to check
147 + * @param message not found message
148 + * @param <T> item type
149 + * @return item if not null
150 + * @throws IllegalArgumentException if item is null
151 + */
152 + public static <T> T nullIsIllegal(T item, String message) {
153 + if (item == null) {
154 + throw new IllegalArgumentException(message);
155 + }
156 + return item;
157 + }
158 +
159 + /**
143 * Converts a string from hex to long. 160 * Converts a string from hex to long.
144 * 161 *
145 * @param string hex number in string form; sans 0x 162 * @param string hex number in string form; sans 0x
......
1 +/*
2 + * Copyright 2014-2015 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.rest.exceptions;
17 +
18 +import javax.ws.rs.core.Response;
19 +
20 +/**
21 + * Mapper for illegal argument exceptions to the BAD_REQUEST response code.
22 + */
23 +public class IllegalArgumentExceptionMapper extends AbstractMapper<IllegalArgumentException> {
24 + @Override
25 + protected Response.Status responseStatus() {
26 + return Response.Status.BAD_REQUEST;
27 + }
28 +}
29 +
...@@ -15,22 +15,29 @@ ...@@ -15,22 +15,29 @@
15 */ 15 */
16 package org.onosproject.rest.resources; 16 package org.onosproject.rest.resources;
17 17
18 -import com.fasterxml.jackson.databind.node.ArrayNode; 18 +import java.io.IOException;
19 -import com.fasterxml.jackson.databind.node.ObjectNode; 19 +import java.io.InputStream;
20 +
21 +import javax.ws.rs.Consumes;
22 +import javax.ws.rs.GET;
23 +import javax.ws.rs.POST;
24 +import javax.ws.rs.Path;
25 +import javax.ws.rs.PathParam;
26 +import javax.ws.rs.Produces;
27 +import javax.ws.rs.core.MediaType;
28 +import javax.ws.rs.core.Response;
29 +
20 import org.onlab.util.ItemNotFoundException; 30 import org.onlab.util.ItemNotFoundException;
21 import org.onosproject.net.Device; 31 import org.onosproject.net.Device;
22 import org.onosproject.net.DeviceId; 32 import org.onosproject.net.DeviceId;
23 import org.onosproject.net.device.DeviceService; 33 import org.onosproject.net.device.DeviceService;
24 import org.onosproject.net.flow.FlowEntry; 34 import org.onosproject.net.flow.FlowEntry;
35 +import org.onosproject.net.flow.FlowRule;
25 import org.onosproject.net.flow.FlowRuleService; 36 import org.onosproject.net.flow.FlowRuleService;
26 import org.onosproject.rest.AbstractWebResource; 37 import org.onosproject.rest.AbstractWebResource;
27 38
28 -import javax.ws.rs.GET; 39 +import com.fasterxml.jackson.databind.node.ArrayNode;
29 -import javax.ws.rs.Path; 40 +import com.fasterxml.jackson.databind.node.ObjectNode;
30 -import javax.ws.rs.PathParam;
31 -import javax.ws.rs.Produces;
32 -import javax.ws.rs.core.MediaType;
33 -import javax.ws.rs.core.Response;
34 41
35 /** 42 /**
36 * REST resource for interacting with the inventory of flows. 43 * REST resource for interacting with the inventory of flows.
...@@ -113,4 +120,27 @@ public class FlowsWebResource extends AbstractWebResource { ...@@ -113,4 +120,27 @@ public class FlowsWebResource extends AbstractWebResource {
113 } 120 }
114 return ok(root).build(); 121 return ok(root).build();
115 } 122 }
123 +
124 + /**
125 + * Creates a flow rule from a POST of a JSON string and attempts to apply it.
126 + *
127 + * @param stream input JSON
128 + * @return status of the request - ACCEPTED if the JSON is correct,
129 + * BAD_REQUEST if the JSON is invalid
130 + */
131 + @POST
132 + @Consumes(MediaType.APPLICATION_JSON)
133 + @Produces(MediaType.APPLICATION_JSON)
134 + public Response createFlow(InputStream stream) {
135 + try {
136 + FlowRuleService service = get(FlowRuleService.class);
137 + ObjectNode root = (ObjectNode) mapper().readTree(stream);
138 + FlowRule rule = codec(FlowRule.class).decode(root, this);
139 + service.applyFlowRules(rule);
140 + } catch (IOException ex) {
141 + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
142 + }
143 + return Response.status(Response.Status.ACCEPTED).build();
144 + }
145 +
116 } 146 }
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
61 org.onosproject.rest.exceptions.ServerErrorMapper, 61 org.onosproject.rest.exceptions.ServerErrorMapper,
62 org.onosproject.rest.exceptions.BadRequestMapper, 62 org.onosproject.rest.exceptions.BadRequestMapper,
63 org.onosproject.rest.exceptions.WebApplicationExceptionMapper, 63 org.onosproject.rest.exceptions.WebApplicationExceptionMapper,
64 + org.onosproject.rest.exceptions.IllegalArgumentExceptionMapper,
64 org.onosproject.rest.resources.JsonBodyWriter, 65 org.onosproject.rest.resources.JsonBodyWriter,
65 66
66 org.onosproject.rest.resources.ApplicationsWebResource, 67 org.onosproject.rest.resources.ApplicationsWebResource,
......
...@@ -15,10 +15,13 @@ ...@@ -15,10 +15,13 @@
15 */ 15 */
16 package org.onosproject.rest; 16 package org.onosproject.rest;
17 17
18 +import java.net.HttpURLConnection;
18 import java.util.HashMap; 19 import java.util.HashMap;
19 import java.util.HashSet; 20 import java.util.HashSet;
20 import java.util.Set; 21 import java.util.Set;
21 22
23 +import javax.ws.rs.core.MediaType;
24 +
22 import org.hamcrest.Description; 25 import org.hamcrest.Description;
23 import org.hamcrest.TypeSafeMatcher; 26 import org.hamcrest.TypeSafeMatcher;
24 import org.junit.After; 27 import org.junit.After;
...@@ -30,11 +33,13 @@ import org.onlab.packet.MacAddress; ...@@ -30,11 +33,13 @@ import org.onlab.packet.MacAddress;
30 import org.onlab.rest.BaseResource; 33 import org.onlab.rest.BaseResource;
31 import org.onosproject.codec.CodecService; 34 import org.onosproject.codec.CodecService;
32 import org.onosproject.codec.impl.CodecManager; 35 import org.onosproject.codec.impl.CodecManager;
36 +import org.onosproject.core.CoreService;
33 import org.onosproject.core.DefaultGroupId; 37 import org.onosproject.core.DefaultGroupId;
34 import org.onosproject.core.GroupId; 38 import org.onosproject.core.GroupId;
35 import org.onosproject.net.DefaultDevice; 39 import org.onosproject.net.DefaultDevice;
36 import org.onosproject.net.Device; 40 import org.onosproject.net.Device;
37 import org.onosproject.net.DeviceId; 41 import org.onosproject.net.DeviceId;
42 +import org.onosproject.net.NetTestTools;
38 import org.onosproject.net.device.DeviceService; 43 import org.onosproject.net.device.DeviceService;
39 import org.onosproject.net.flow.DefaultTrafficSelector; 44 import org.onosproject.net.flow.DefaultTrafficSelector;
40 import org.onosproject.net.flow.DefaultTrafficTreatment; 45 import org.onosproject.net.flow.DefaultTrafficTreatment;
...@@ -51,12 +56,15 @@ import org.onosproject.net.flow.instructions.Instructions; ...@@ -51,12 +56,15 @@ import org.onosproject.net.flow.instructions.Instructions;
51 import com.eclipsesource.json.JsonArray; 56 import com.eclipsesource.json.JsonArray;
52 import com.eclipsesource.json.JsonObject; 57 import com.eclipsesource.json.JsonObject;
53 import com.google.common.collect.ImmutableSet; 58 import com.google.common.collect.ImmutableSet;
59 +import com.sun.jersey.api.client.ClientResponse;
54 import com.sun.jersey.api.client.UniformInterfaceException; 60 import com.sun.jersey.api.client.UniformInterfaceException;
55 import com.sun.jersey.api.client.WebResource; 61 import com.sun.jersey.api.client.WebResource;
56 62
57 import static org.easymock.EasyMock.anyObject; 63 import static org.easymock.EasyMock.anyObject;
64 +import static org.easymock.EasyMock.anyShort;
58 import static org.easymock.EasyMock.createMock; 65 import static org.easymock.EasyMock.createMock;
59 import static org.easymock.EasyMock.expect; 66 import static org.easymock.EasyMock.expect;
67 +import static org.easymock.EasyMock.expectLastCall;
60 import static org.easymock.EasyMock.replay; 68 import static org.easymock.EasyMock.replay;
61 import static org.easymock.EasyMock.verify; 69 import static org.easymock.EasyMock.verify;
62 import static org.hamcrest.Matchers.containsString; 70 import static org.hamcrest.Matchers.containsString;
...@@ -72,6 +80,8 @@ import static org.junit.Assert.fail; ...@@ -72,6 +80,8 @@ import static org.junit.Assert.fail;
72 */ 80 */
73 public class FlowsResourceTest extends ResourceTest { 81 public class FlowsResourceTest extends ResourceTest {
74 final FlowRuleService mockFlowService = createMock(FlowRuleService.class); 82 final FlowRuleService mockFlowService = createMock(FlowRuleService.class);
83 + CoreService mockCoreService = createMock(CoreService.class);
84 +
75 final HashMap<DeviceId, Set<FlowEntry>> rules = new HashMap<>(); 85 final HashMap<DeviceId, Set<FlowEntry>> rules = new HashMap<>();
76 86
77 final DeviceService mockDeviceService = createMock(DeviceService.class); 87 final DeviceService mockDeviceService = createMock(DeviceService.class);
...@@ -245,6 +255,11 @@ public class FlowsResourceTest extends ResourceTest { ...@@ -245,6 +255,11 @@ public class FlowsResourceTest extends ResourceTest {
245 expect(mockDeviceService.getDevices()) 255 expect(mockDeviceService.getDevices())
246 .andReturn(ImmutableSet.of(device1, device2)); 256 .andReturn(ImmutableSet.of(device1, device2));
247 257
258 + // Mock Core Service
259 + expect(mockCoreService.getAppId(anyShort()))
260 + .andReturn(NetTestTools.APP_ID).anyTimes();
261 + replay(mockCoreService);
262 +
248 // Register the services needed for the test 263 // Register the services needed for the test
249 final CodecManager codecService = new CodecManager(); 264 final CodecManager codecService = new CodecManager();
250 codecService.activate(); 265 codecService.activate();
...@@ -252,7 +267,8 @@ public class FlowsResourceTest extends ResourceTest { ...@@ -252,7 +267,8 @@ public class FlowsResourceTest extends ResourceTest {
252 new TestServiceDirectory() 267 new TestServiceDirectory()
253 .add(FlowRuleService.class, mockFlowService) 268 .add(FlowRuleService.class, mockFlowService)
254 .add(DeviceService.class, mockDeviceService) 269 .add(DeviceService.class, mockDeviceService)
255 - .add(CodecService.class, codecService); 270 + .add(CodecService.class, codecService)
271 + .add(CoreService.class, mockCoreService);
256 272
257 BaseResource.setServiceDirectory(testDirectory); 273 BaseResource.setServiceDirectory(testDirectory);
258 } 274 }
...@@ -263,6 +279,7 @@ public class FlowsResourceTest extends ResourceTest { ...@@ -263,6 +279,7 @@ public class FlowsResourceTest extends ResourceTest {
263 @After 279 @After
264 public void tearDownTest() { 280 public void tearDownTest() {
265 verify(mockFlowService); 281 verify(mockFlowService);
282 + verify(mockCoreService);
266 } 283 }
267 284
268 /** 285 /**
...@@ -542,4 +559,27 @@ public class FlowsResourceTest extends ResourceTest { ...@@ -542,4 +559,27 @@ public class FlowsResourceTest extends ResourceTest {
542 containsString("returned a response status of")); 559 containsString("returned a response status of"));
543 } 560 }
544 } 561 }
562 +
563 + /**
564 + * Tests creating a flow with POST.
565 + */
566 + @Test
567 + public void testPost() {
568 + String json = "{\"appId\":2,\"priority\":1,\"isPermanent\":true,"
569 + + "\"deviceId\":\"of:0000000000000001\","
570 + + "\"treatment\":{\"instructions\":[ {\"type\":\"OUTPUT\",\"port\":2}]},"
571 + + "\"selector\":{\"criteria\":[ {\"type\":\"ETH_TYPE\",\"ethType\":2054}]}}";
572 +
573 + mockFlowService.applyFlowRules(anyObject());
574 + expectLastCall();
575 + replay(mockFlowService);
576 +
577 + WebResource rs = resource();
578 +
579 +
580 + ClientResponse response = rs.path("flows/")
581 + .type(MediaType.APPLICATION_JSON_TYPE)
582 + .post(ClientResponse.class, json);
583 + assertThat(response.getStatus(), is(HttpURLConnection.HTTP_ACCEPTED));
584 + }
545 } 585 }
......