Committed by
Gerrit Code Review
REST API to create flows
Change-Id: I5d001782249c0eab249d7aa857ae465da95b5955
Showing
22 changed files
with
2181 additions
and
501 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 | - | ||
236 | - private static class FormatSctp implements CriterionTypeFormatter { | ||
237 | - @Override | ||
238 | - public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) { | ||
239 | - final SctpPortCriterion sctpPortCriterion = | ||
240 | - (SctpPortCriterion) criterion; | ||
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 | - } | ||
360 | 63 | ||
361 | @Override | 64 | @Override |
362 | public ObjectNode encode(Criterion criterion, CodecContext context) { | 65 | public ObjectNode encode(Criterion criterion, CodecContext context) { |
363 | - checkNotNull(criterion, "Criterion cannot be null"); | 66 | + EncodeCriterionCodec encoder = new EncodeCriterionCodec(criterion, context); |
364 | - | 67 | + return encoder.encode(); |
365 | - final ObjectNode result = context.mapper().createObjectNode() | 68 | + } |
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 | 69 | ||
374 | - return formatter.encodeCriterion(result, criterion); | 70 | + @Override |
71 | + public Criterion decode(ObjectNode json, CodecContext context) { | ||
72 | + DecodeCriterionCodec decoder = new DecodeCriterionCodec(json); | ||
73 | + return decoder.decode(); | ||
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"; |
43 | + protected static final String FLOW_LABEL = "flowLabel"; | ||
44 | + protected static final String LAMBDA = "lambda"; | ||
45 | + protected static final String GRID_TYPE = "gridType"; | ||
46 | + protected static final String CHANNEL_SPACING = "channelSpacing"; | ||
47 | + protected static final String SPACING_MULTIPLIER = "spacingMultiplier"; | ||
48 | + protected static final String SLOT_GRANULARITY = "slotGranularity"; | ||
49 | + protected static final String ETHERNET_TYPE = "ethernetType"; | ||
50 | + | ||
51 | + protected static final String MISSING_MEMBER_MESSAGE = | ||
52 | + " member is required in Instruction"; | ||
48 | 53 | ||
49 | - switch (instruction.subtype()) { | ||
50 | - case LAMBDA: | ||
51 | - final L0ModificationInstruction.ModLambdaInstruction modLambdaInstruction = | ||
52 | - (L0ModificationInstruction.ModLambdaInstruction) instruction; | ||
53 | - result.put("lambda", modLambdaInstruction.lambda()); | ||
54 | - break; | ||
55 | - | ||
56 | - case OCH: | ||
57 | - L0ModificationInstruction.ModOchSignalInstruction ochSignalInstruction = | ||
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 | - | ||
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 | +} |
... | @@ -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 | ... | ... |
web/api/src/main/java/org/onosproject/rest/exceptions/IllegalArgumentExceptionMapper.java
0 → 100644
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 | } | ... | ... |
-
Please register or login to post a comment