6a97a07609b8c5b890fdff25b13c8ae6eb22ead5
[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 org.onlab.packet.IpAddress;
19 import org.onlab.packet.MacAddress;
20 import org.onlab.packet.MplsLabel;
21 import org.onlab.packet.TpPort;
22 import org.onlab.packet.VlanId;
23 import org.onosproject.net.ChannelSpacing;
24 import org.onosproject.net.GridType;
25 import org.onosproject.net.Lambda;
26 import org.onosproject.net.OchSignal;
27 import org.onosproject.net.PortNumber;
28
29 import com.fasterxml.jackson.databind.node.ObjectNode;
30 import org.onosproject.net.flow.instructions.Instruction;
31 import org.onosproject.net.flow.instructions.Instructions;
32 import org.onosproject.net.flow.instructions.L0ModificationInstruction;
33 import org.onosproject.net.flow.instructions.L2ModificationInstruction;
34 import org.onosproject.net.flow.instructions.L3ModificationInstruction;
35 import org.onosproject.net.flow.instructions.L4ModificationInstruction;
36
37 import static org.onlab.util.Tools.nullIsIllegal;
38
39 /**
40  * Decoding portion of the instruction codec.
41  */
42 public final class DecodeInstructionCodecHelper {
43     private final ObjectNode json;
44
45     /**
46      * Creates a decode instruction codec object.
47      *
48      * @param json JSON object to decode
49      */
50     public DecodeInstructionCodecHelper(ObjectNode json) {
51         this.json = json;
52     }
53
54     /**
55      * Decodes a Layer 2 instruction.
56      *
57      * @return instruction object decoded from the JSON
58      * @throws IllegalArgumentException if the JSON is invalid
59      */
60     private Instruction decodeL2() {
61         String subType = json.get(InstructionCodec.SUBTYPE).asText();
62
63         if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC.name())) {
64             String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
65                     InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
66             return Instructions.modL2Src(MacAddress.valueOf(mac));
67         } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST.name())) {
68             String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
69                     InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
70             return Instructions.modL2Dst(MacAddress.valueOf(mac));
71         } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_ID.name())) {
72             short vlanId = (short) nullIsIllegal(json.get(InstructionCodec.VLAN_ID),
73                     InstructionCodec.VLAN_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
74             return Instructions.modVlanId(VlanId.vlanId(vlanId));
75         } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PCP.name())) {
76             byte vlanPcp = (byte) nullIsIllegal(json.get(InstructionCodec.VLAN_PCP),
77                     InstructionCodec.VLAN_PCP + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
78             return Instructions.modVlanPcp(vlanPcp);
79         } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_LABEL.name())) {
80             int label = nullIsIllegal(json.get(InstructionCodec.MPLS_LABEL),
81                     InstructionCodec.MPLS_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
82             return Instructions.modMplsLabel(MplsLabel.mplsLabel(label));
83         } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_PUSH.name())) {
84             return Instructions.pushMpls();
85         } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_POP.name())) {
86             return Instructions.popMpls();
87         } else if (subType.equals(L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name())) {
88             return Instructions.decMplsTtl();
89         } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_POP.name())) {
90             return Instructions.popVlan();
91         } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PUSH.name())) {
92             return Instructions.pushVlan();
93         } else if (subType.equals(L2ModificationInstruction.L2SubType.TUNNEL_ID.name())) {
94             long tunnelId = nullIsIllegal(json.get(InstructionCodec.TUNNEL_ID),
95                     InstructionCodec.TUNNEL_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong();
96             return Instructions.modTunnelId(tunnelId);
97         }
98         throw new IllegalArgumentException("L2 Instruction subtype "
99                 + subType + " is not supported");
100     }
101
102     /**
103      * Decodes a Layer 3 instruction.
104      *
105      * @return instruction object decoded from the JSON
106      * @throws IllegalArgumentException if the JSON is invalid
107      */
108     private Instruction decodeL3() {
109         String subType = json.get(InstructionCodec.SUBTYPE).asText();
110
111         if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_SRC.name())) {
112             IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
113                     InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
114             return Instructions.modL3Src(ip);
115         } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_DST.name())) {
116             IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
117                     InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
118             return Instructions.modL3Dst(ip);
119         } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_SRC.name())) {
120             IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
121                     InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
122             return Instructions.modL3IPv6Src(ip);
123         } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_DST.name())) {
124             IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
125                     InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
126             return Instructions.modL3IPv6Dst(ip);
127         } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_FLABEL.name())) {
128             int flowLabel = nullIsIllegal(json.get(InstructionCodec.FLOW_LABEL),
129                     InstructionCodec.FLOW_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
130             return Instructions.modL3IPv6FlowLabel(flowLabel);
131         }
132         throw new IllegalArgumentException("L3 Instruction subtype "
133                 + subType + " is not supported");
134     }
135
136     /**
137      * Decodes a Layer 0 instruction.
138      *
139      * @return instruction object decoded from the JSON
140      * @throws IllegalArgumentException if the JSON is invalid
141      */
142     private Instruction decodeL0() {
143         String subType = json.get(InstructionCodec.SUBTYPE).asText();
144
145
146         if (subType.equals(L0ModificationInstruction.L0SubType.LAMBDA.name())) {
147             int lambda = nullIsIllegal(json.get(InstructionCodec.LAMBDA),
148                     InstructionCodec.LAMBDA + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
149             return Instructions.modL0Lambda(Lambda.indexedLambda(lambda));
150         } else if (subType.equals(L0ModificationInstruction.L0SubType.OCH.name())) {
151             String gridTypeString = nullIsIllegal(json.get(InstructionCodec.GRID_TYPE),
152                     InstructionCodec.GRID_TYPE + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
153             GridType gridType = GridType.valueOf(gridTypeString);
154             if (gridType == null) {
155                 throw new IllegalArgumentException("Unknown grid type  "
156                         + gridTypeString);
157             }
158             String channelSpacingString = nullIsIllegal(json.get(InstructionCodec.CHANNEL_SPACING),
159                     InstructionCodec.CHANNEL_SPACING + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
160             ChannelSpacing channelSpacing = ChannelSpacing.valueOf(channelSpacingString);
161             if (channelSpacing == null) {
162                 throw new IllegalArgumentException("Unknown channel spacing  "
163                         + channelSpacingString);
164             }
165             int spacingMultiplier = nullIsIllegal(json.get(InstructionCodec.SPACING_MULTIPLIER),
166                     InstructionCodec.SPACING_MULTIPLIER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
167             int slotGranularity = nullIsIllegal(json.get(InstructionCodec.SLOT_GRANULARITY),
168                     InstructionCodec.SLOT_GRANULARITY + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
169             return Instructions.modL0Lambda(new OchSignal(gridType, channelSpacing,
170                     spacingMultiplier, slotGranularity));
171         }
172         throw new IllegalArgumentException("L0 Instruction subtype "
173                 + subType + " is not supported");
174     }
175
176     /**
177      * Decodes a Layer 4 instruction.
178      *
179      * @return instruction object decoded from the JSON
180      * @throws IllegalArgumentException if the JSON is invalid
181      */
182     private Instruction decodeL4() {
183         String subType = json.get(InstructionCodec.SUBTYPE).asText();
184
185         if (subType.equals(L4ModificationInstruction.L4SubType.TCP_DST.name())) {
186             TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT),
187                     InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
188             return Instructions.modTcpDst(tcpPort);
189         } else if (subType.equals(L4ModificationInstruction.L4SubType.TCP_SRC.name())) {
190             TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT),
191                     InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
192             return Instructions.modTcpSrc(tcpPort);
193         } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_DST.name())) {
194             TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT),
195                     InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
196             return Instructions.modUdpDst(udpPort);
197         } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_SRC.name())) {
198             TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT),
199                     InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
200             return Instructions.modUdpSrc(udpPort);
201         }
202         throw new IllegalArgumentException("L4 Instruction subtype "
203                 + subType + " is not supported");
204     }
205
206     /**
207      * Decodes the JSON into an instruction object.
208      *
209      * @return Criterion object
210      * @throws IllegalArgumentException if the JSON is invalid
211      */
212     public Instruction decode() {
213         String type = json.get(InstructionCodec.TYPE).asText();
214
215         if (type.equals(Instruction.Type.OUTPUT.name())) {
216             PortNumber portNumber =
217                     PortNumber.portNumber(nullIsIllegal(json.get(InstructionCodec.PORT),
218                             InstructionCodec.PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong());
219             return Instructions.createOutput(portNumber);
220         } else if (type.equals(Instruction.Type.DROP.name())) {
221             return Instructions.createDrop();
222         } else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
223             return decodeL0();
224         } else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
225             return decodeL2();
226         } else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
227             return decodeL3();
228         } else if (type.equals(Instruction.Type.L4MODIFICATION.name())) {
229             return decodeL4();
230         }
231         throw new IllegalArgumentException("Instruction type "
232                 + type + " is not supported");
233     }
234
235 }