4e0f2bd952356666546e97ba9513f59324ea194e
[onosfw.git] /
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.TpPort;
26 import org.onlab.packet.VlanId;
27 import org.onosproject.net.ChannelSpacing;
28 import org.onosproject.net.GridType;
29 import org.onosproject.net.Lambda;
30 import org.onosproject.net.PortNumber;
31 import org.onosproject.net.flow.criteria.Criteria;
32 import org.onosproject.net.flow.criteria.Criterion;
33
34 import com.fasterxml.jackson.databind.JsonNode;
35 import com.fasterxml.jackson.databind.node.ObjectNode;
36
37 import static org.onlab.util.Tools.nullIsIllegal;
38
39 /**
40  * Decode portion of the criterion codec.
41  */
42 public final class DecodeCriterionCodecHelper {
43
44     private final ObjectNode json;
45
46     protected static final String MISSING_MEMBER_MESSAGE =
47             " member is required in Criterion";
48
49     private interface CriterionDecoder {
50         Criterion decodeCriterion(ObjectNode json);
51     }
52     private final Map<String, CriterionDecoder> decoderMap;
53
54     /**
55      * Creates a decode criterion codec object.
56      * Initializes the lookup map for criterion subclass decoders.
57      *
58      * @param json JSON object to decode
59      */
60     public DecodeCriterionCodecHelper(ObjectNode json) {
61         this.json = json;
62         decoderMap = new HashMap<>();
63
64         decoderMap.put(Criterion.Type.IN_PORT.name(), new InPortDecoder());
65         decoderMap.put(Criterion.Type.IN_PHY_PORT.name(), new InPhyPortDecoder());
66         decoderMap.put(Criterion.Type.METADATA.name(), new MetadataDecoder());
67         decoderMap.put(Criterion.Type.ETH_DST.name(), new EthDstDecoder());
68         decoderMap.put(Criterion.Type.ETH_SRC.name(), new EthSrcDecoder());
69         decoderMap.put(Criterion.Type.ETH_TYPE.name(), new EthTypeDecoder());
70         decoderMap.put(Criterion.Type.VLAN_VID.name(), new VlanVidDecoder());
71         decoderMap.put(Criterion.Type.VLAN_PCP.name(), new VlanPcpDecoder());
72         decoderMap.put(Criterion.Type.IP_DSCP.name(), new IpDscpDecoder());
73         decoderMap.put(Criterion.Type.IP_ECN.name(), new IpEcnDecoder());
74         decoderMap.put(Criterion.Type.IP_PROTO.name(), new IpProtoDecoder());
75         decoderMap.put(Criterion.Type.IPV4_SRC.name(), new IpV4SrcDecoder());
76         decoderMap.put(Criterion.Type.IPV4_DST.name(), new IpV4DstDecoder());
77         decoderMap.put(Criterion.Type.TCP_SRC.name(), new TcpSrcDecoder());
78         decoderMap.put(Criterion.Type.TCP_DST.name(), new TcpDstDecoder());
79         decoderMap.put(Criterion.Type.UDP_SRC.name(), new UdpSrcDecoder());
80         decoderMap.put(Criterion.Type.UDP_DST.name(), new UdpDstDecoder());
81         decoderMap.put(Criterion.Type.SCTP_SRC.name(), new SctpSrcDecoder());
82         decoderMap.put(Criterion.Type.SCTP_DST.name(), new SctpDstDecoder());
83         decoderMap.put(Criterion.Type.ICMPV4_TYPE.name(), new IcmpV4TypeDecoder());
84         decoderMap.put(Criterion.Type.ICMPV4_CODE.name(), new IcmpV4CodeDecoder());
85         decoderMap.put(Criterion.Type.IPV6_SRC.name(), new IpV6SrcDecoder());
86         decoderMap.put(Criterion.Type.IPV6_DST.name(), new IpV6DstDecoder());
87         decoderMap.put(Criterion.Type.IPV6_FLABEL.name(), new IpV6FLabelDecoder());
88         decoderMap.put(Criterion.Type.ICMPV6_TYPE.name(), new IcmpV6TypeDecoder());
89         decoderMap.put(Criterion.Type.ICMPV6_CODE.name(), new IcmpV6CodeDecoder());
90         decoderMap.put(Criterion.Type.IPV6_ND_TARGET.name(), new V6NDTargetDecoder());
91         decoderMap.put(Criterion.Type.IPV6_ND_SLL.name(), new V6NDSllDecoder());
92         decoderMap.put(Criterion.Type.IPV6_ND_TLL.name(), new V6NDTllDecoder());
93         decoderMap.put(Criterion.Type.MPLS_LABEL.name(), new MplsLabelDecoder());
94         decoderMap.put(Criterion.Type.IPV6_EXTHDR.name(), new IpV6ExthdrDecoder());
95         decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder());
96         decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder());
97         decoderMap.put(Criterion.Type.TUNNEL_ID.name(), new TunnelIdDecoder());
98     }
99
100     private class EthTypeDecoder implements CriterionDecoder {
101         @Override
102         public Criterion decodeCriterion(ObjectNode json) {
103             int ethType = nullIsIllegal(json.get(CriterionCodec.ETH_TYPE),
104                     CriterionCodec.ETH_TYPE + MISSING_MEMBER_MESSAGE).asInt();
105             return Criteria.matchEthType(ethType);
106         }
107     }
108
109     private class EthDstDecoder implements CriterionDecoder {
110         @Override
111         public Criterion decodeCriterion(ObjectNode json) {
112             MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
113                     CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
114
115             return Criteria.matchEthDst(mac);
116         }
117     }
118
119     private class EthSrcDecoder implements CriterionDecoder {
120         @Override
121         public Criterion decodeCriterion(ObjectNode json) {
122             MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
123                     CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
124
125             return Criteria.matchEthSrc(mac);
126         }
127     }
128
129     private class InPortDecoder implements CriterionDecoder {
130         @Override
131         public Criterion decodeCriterion(ObjectNode json) {
132             PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
133                     CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
134
135             return Criteria.matchInPort(port);
136         }
137     }
138
139     private class InPhyPortDecoder implements CriterionDecoder {
140         @Override
141         public Criterion decodeCriterion(ObjectNode json) {
142             PortNumber port = PortNumber.portNumber(nullIsIllegal(json.get(CriterionCodec.PORT),
143                     CriterionCodec.PORT + MISSING_MEMBER_MESSAGE).asLong());
144
145             return Criteria.matchInPhyPort(port);
146         }
147     }
148
149     private class MetadataDecoder implements CriterionDecoder {
150         @Override
151         public Criterion decodeCriterion(ObjectNode json) {
152             long metadata = nullIsIllegal(json.get(CriterionCodec.METADATA),
153                     CriterionCodec.METADATA + MISSING_MEMBER_MESSAGE).asLong();
154
155             return Criteria.matchMetadata(metadata);
156         }
157     }
158
159     private class VlanVidDecoder implements CriterionDecoder {
160         @Override
161         public Criterion decodeCriterion(ObjectNode json) {
162             short vlanId = (short) nullIsIllegal(json.get(CriterionCodec.VLAN_ID),
163                     CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
164
165             return Criteria.matchVlanId(VlanId.vlanId(vlanId));
166         }
167     }
168
169     private class VlanPcpDecoder implements CriterionDecoder {
170         @Override
171         public Criterion decodeCriterion(ObjectNode json) {
172             byte priority = (byte) nullIsIllegal(json.get(CriterionCodec.PRIORITY),
173                     CriterionCodec.VLAN_ID + MISSING_MEMBER_MESSAGE).asInt();
174
175             return Criteria.matchVlanPcp(priority);
176         }
177     }
178
179     private class IpDscpDecoder implements CriterionDecoder {
180         @Override
181         public Criterion decodeCriterion(ObjectNode json) {
182             byte ipDscp = (byte) nullIsIllegal(json.get(CriterionCodec.IP_DSCP),
183                     CriterionCodec.IP_DSCP + MISSING_MEMBER_MESSAGE).asInt();
184             return Criteria.matchIPDscp(ipDscp);
185         }
186     }
187
188     private class IpEcnDecoder implements CriterionDecoder {
189         @Override
190         public Criterion decodeCriterion(ObjectNode json) {
191             byte ipEcn = (byte) nullIsIllegal(json.get(CriterionCodec.IP_ECN),
192                     CriterionCodec.IP_ECN + MISSING_MEMBER_MESSAGE).asInt();
193             return Criteria.matchIPEcn(ipEcn);
194         }
195     }
196
197     private class IpProtoDecoder implements CriterionDecoder {
198         @Override
199         public Criterion decodeCriterion(ObjectNode json) {
200             short proto = (short) nullIsIllegal(json.get(CriterionCodec.PROTOCOL),
201                     CriterionCodec.PROTOCOL + MISSING_MEMBER_MESSAGE).asInt();
202             return Criteria.matchIPProtocol(proto);
203         }
204     }
205
206     private class IpV4SrcDecoder implements CriterionDecoder {
207         @Override
208         public Criterion decodeCriterion(ObjectNode json) {
209             String ip = nullIsIllegal(json.get(CriterionCodec.IP),
210                     CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
211             return Criteria.matchIPSrc(IpPrefix.valueOf(ip));
212         }
213     }
214
215     private class IpV4DstDecoder implements CriterionDecoder {
216         @Override
217         public Criterion decodeCriterion(ObjectNode json) {
218             String ip = nullIsIllegal(json.get(CriterionCodec.IP),
219                     CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
220             return Criteria.matchIPDst(IpPrefix.valueOf(ip));
221         }
222     }
223
224     private class IpV6SrcDecoder implements CriterionDecoder {
225         @Override
226         public Criterion decodeCriterion(ObjectNode json) {
227             String ip = nullIsIllegal(json.get(CriterionCodec.IP),
228                     CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
229             return Criteria.matchIPv6Src(IpPrefix.valueOf(ip));
230         }
231     }
232
233     private class IpV6DstDecoder implements CriterionDecoder {
234         @Override
235         public Criterion decodeCriterion(ObjectNode json) {
236             String ip = nullIsIllegal(json.get(CriterionCodec.IP),
237                     CriterionCodec.IP + MISSING_MEMBER_MESSAGE).asText();
238             return Criteria.matchIPv6Dst(IpPrefix.valueOf(ip));
239         }
240     }
241
242     private class TcpSrcDecoder implements CriterionDecoder {
243         @Override
244         public Criterion decodeCriterion(ObjectNode json) {
245             TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.TCP_PORT),
246                     CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt());
247             return Criteria.matchTcpSrc(tcpPort);
248         }
249     }
250
251     private class TcpDstDecoder implements CriterionDecoder {
252         @Override
253         public Criterion decodeCriterion(ObjectNode json) {
254             TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.TCP_PORT),
255                     CriterionCodec.TCP_PORT + MISSING_MEMBER_MESSAGE).asInt());
256             return Criteria.matchTcpDst(tcpPort);
257         }
258     }
259
260     private class UdpSrcDecoder implements CriterionDecoder {
261         @Override
262         public Criterion decodeCriterion(ObjectNode json) {
263             TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.UDP_PORT),
264                     CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt());
265             return Criteria.matchUdpSrc(udpPort);
266         }
267     }
268
269     private class UdpDstDecoder implements CriterionDecoder {
270         @Override
271         public Criterion decodeCriterion(ObjectNode json) {
272             TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.UDP_PORT),
273                     CriterionCodec.UDP_PORT + MISSING_MEMBER_MESSAGE).asInt());
274             return Criteria.matchUdpDst(udpPort);
275         }
276     }
277
278     private class SctpSrcDecoder implements CriterionDecoder {
279         @Override
280         public Criterion decodeCriterion(ObjectNode json) {
281             TpPort sctpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.SCTP_PORT),
282                     CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt());
283             return Criteria.matchSctpSrc(sctpPort);
284         }
285     }
286
287     private class SctpDstDecoder implements CriterionDecoder {
288         @Override
289         public Criterion decodeCriterion(ObjectNode json) {
290             TpPort sctpPort = TpPort.tpPort(nullIsIllegal(json.get(CriterionCodec.SCTP_PORT),
291                     CriterionCodec.SCTP_PORT + MISSING_MEMBER_MESSAGE).asInt());
292             return Criteria.matchSctpDst(sctpPort);
293         }
294     }
295
296     private class IcmpV4TypeDecoder implements CriterionDecoder {
297         @Override
298         public Criterion decodeCriterion(ObjectNode json) {
299             short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_TYPE),
300                     CriterionCodec.ICMP_TYPE + MISSING_MEMBER_MESSAGE).asInt();
301             return Criteria.matchIcmpType(type);
302         }
303     }
304
305     private class IcmpV4CodeDecoder implements CriterionDecoder {
306         @Override
307         public Criterion decodeCriterion(ObjectNode json) {
308             short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMP_CODE),
309                     CriterionCodec.ICMP_CODE + MISSING_MEMBER_MESSAGE).asInt();
310             return Criteria.matchIcmpCode(code);
311         }
312     }
313
314     private class IpV6FLabelDecoder implements CriterionDecoder {
315         @Override
316         public Criterion decodeCriterion(ObjectNode json) {
317             int flowLabel = nullIsIllegal(json.get(CriterionCodec.FLOW_LABEL),
318                     CriterionCodec.FLOW_LABEL + MISSING_MEMBER_MESSAGE).asInt();
319             return Criteria.matchIPv6FlowLabel(flowLabel);
320         }
321     }
322
323     private class IcmpV6TypeDecoder implements CriterionDecoder {
324         @Override
325         public Criterion decodeCriterion(ObjectNode json) {
326             short type = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_TYPE),
327                     CriterionCodec.ICMPV6_TYPE + MISSING_MEMBER_MESSAGE).asInt();
328             return Criteria.matchIcmpv6Type(type);
329         }
330     }
331
332     private class IcmpV6CodeDecoder implements CriterionDecoder {
333         @Override
334         public Criterion decodeCriterion(ObjectNode json) {
335             short code = (short) nullIsIllegal(json.get(CriterionCodec.ICMPV6_CODE),
336                     CriterionCodec.ICMPV6_CODE + MISSING_MEMBER_MESSAGE).asInt();
337             return Criteria.matchIcmpv6Code(code);
338         }
339     }
340
341     private class V6NDTargetDecoder implements CriterionDecoder {
342         @Override
343         public Criterion decodeCriterion(ObjectNode json) {
344             Ip6Address target = Ip6Address.valueOf(nullIsIllegal(json.get(CriterionCodec.TARGET_ADDRESS),
345                     CriterionCodec.TARGET_ADDRESS + MISSING_MEMBER_MESSAGE).asText());
346             return Criteria.matchIPv6NDTargetAddress(target);
347         }
348     }
349
350     private class V6NDSllDecoder implements CriterionDecoder {
351         @Override
352         public Criterion decodeCriterion(ObjectNode json) {
353             MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
354                     CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
355             return Criteria.matchIPv6NDSourceLinkLayerAddress(mac);
356         }
357     }
358
359     private class V6NDTllDecoder implements CriterionDecoder {
360         @Override
361         public Criterion decodeCriterion(ObjectNode json) {
362             MacAddress mac = MacAddress.valueOf(nullIsIllegal(json.get(CriterionCodec.MAC),
363                     CriterionCodec.MAC + MISSING_MEMBER_MESSAGE).asText());
364             return Criteria.matchIPv6NDTargetLinkLayerAddress(mac);
365         }
366     }
367
368     private class MplsLabelDecoder implements CriterionDecoder {
369         @Override
370         public Criterion decodeCriterion(ObjectNode json) {
371             int label = nullIsIllegal(json.get(CriterionCodec.LABEL),
372                     CriterionCodec.LABEL + MISSING_MEMBER_MESSAGE).asInt();
373             return Criteria.matchMplsLabel(MplsLabel.mplsLabel(label));
374         }
375     }
376
377     private class IpV6ExthdrDecoder implements CriterionDecoder {
378         @Override
379         public Criterion decodeCriterion(ObjectNode json) {
380             int exthdrFlags = nullIsIllegal(json.get(CriterionCodec.EXT_HDR_FLAGS),
381                     CriterionCodec.EXT_HDR_FLAGS + MISSING_MEMBER_MESSAGE).asInt();
382             return Criteria.matchIPv6ExthdrFlags(exthdrFlags);
383         }
384     }
385
386     private class OchSigIdDecoder implements CriterionDecoder {
387         @Override
388         public Criterion decodeCriterion(ObjectNode json) {
389             if (json.get(CriterionCodec.LAMBDA) != null) {
390                 Lambda lambda = Lambda.indexedLambda(nullIsIllegal(json.get(CriterionCodec.LAMBDA),
391                         CriterionCodec.LAMBDA + MISSING_MEMBER_MESSAGE).asInt());
392                 return Criteria.matchLambda(lambda);
393             } else {
394                 JsonNode ochSignalId = nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_ID),
395                         CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE);
396                 GridType gridType =
397                         GridType.valueOf(
398                                 nullIsIllegal(ochSignalId.get(CriterionCodec.GRID_TYPE),
399                                 CriterionCodec.GRID_TYPE + MISSING_MEMBER_MESSAGE).asText());
400                 ChannelSpacing channelSpacing =
401                         ChannelSpacing.valueOf(
402                                 nullIsIllegal(ochSignalId.get(CriterionCodec.CHANNEL_SPACING),
403                                 CriterionCodec.CHANNEL_SPACING + MISSING_MEMBER_MESSAGE).asText());
404                 int spacingMultiplier = nullIsIllegal(ochSignalId.get(CriterionCodec.SPACING_MULIPLIER),
405                         CriterionCodec.SPACING_MULIPLIER + MISSING_MEMBER_MESSAGE).asInt();
406                 int slotGranularity = nullIsIllegal(ochSignalId.get(CriterionCodec.SLOT_GRANULARITY),
407                         CriterionCodec.SLOT_GRANULARITY + MISSING_MEMBER_MESSAGE).asInt();
408                 return Criteria.matchLambda(
409                         Lambda.ochSignal(gridType, channelSpacing,
410                                 spacingMultiplier, slotGranularity));
411             }
412         }
413     }
414
415     private class OchSigTypeDecoder implements CriterionDecoder {
416         @Override
417         public Criterion decodeCriterion(ObjectNode json) {
418             return null;
419         }
420     }
421
422     private class TunnelIdDecoder implements CriterionDecoder {
423         @Override
424         public Criterion decodeCriterion(ObjectNode json) {
425             long tunnelId = nullIsIllegal(json.get(CriterionCodec.TUNNEL_ID),
426                     CriterionCodec.TUNNEL_ID + MISSING_MEMBER_MESSAGE).asLong();
427             return Criteria.matchTunnelId(tunnelId);
428         }
429     }
430
431     /**
432      * Decodes the JSON into a criterion object.
433      *
434      * @return Criterion object
435      * @throws IllegalArgumentException if the JSON is invalid
436      */
437     public Criterion decode() {
438         String type = json.get(CriterionCodec.TYPE).asText();
439
440         CriterionDecoder decoder = decoderMap.get(type);
441         if (decoder != null) {
442             return decoder.decodeCriterion(json);
443         }
444
445         throw new IllegalArgumentException("Type " + type + " is unknown");
446     }
447
448
449 }