blob: d7a23b862f8b25705601fab78bab3564cb880cbf [file] [log] [blame]
Ray Milkeyd43fe452015-05-29 09:35:12 -07001/*
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 */
16package org.onosproject.codec.impl;
17
Jian Li1ef82db2016-03-03 14:43:21 -080018import com.fasterxml.jackson.databind.node.ObjectNode;
Ray Milkeyd43fe452015-05-29 09:35:12 -070019import org.onlab.packet.IpAddress;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.MplsLabel;
Hyunsun Moonfab29502015-08-25 13:39:16 -070022import org.onlab.packet.TpPort;
Ray Milkeyd43fe452015-05-29 09:35:12 -070023import org.onlab.packet.VlanId;
Yafit Hadar5796d972015-10-15 13:16:11 +030024import org.onlab.util.HexString;
Jian Lice8c5602016-03-03 21:43:24 -080025import org.onosproject.core.DefaultGroupId;
26import org.onosproject.core.GroupId;
Ray Milkeyd43fe452015-05-29 09:35:12 -070027import org.onosproject.net.ChannelSpacing;
28import org.onosproject.net.GridType;
Ray Milkeyd43fe452015-05-29 09:35:12 -070029import org.onosproject.net.OchSignal;
Yafit Hadar5796d972015-10-15 13:16:11 +030030import org.onosproject.net.OduSignalId;
Ray Milkeyd43fe452015-05-29 09:35:12 -070031import org.onosproject.net.PortNumber;
32import org.onosproject.net.flow.instructions.Instruction;
33import org.onosproject.net.flow.instructions.Instructions;
34import org.onosproject.net.flow.instructions.L0ModificationInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030035import org.onosproject.net.flow.instructions.L1ModificationInstruction;
Ray Milkeyd43fe452015-05-29 09:35:12 -070036import org.onosproject.net.flow.instructions.L2ModificationInstruction;
37import org.onosproject.net.flow.instructions.L3ModificationInstruction;
Hyunsun Moonfab29502015-08-25 13:39:16 -070038import org.onosproject.net.flow.instructions.L4ModificationInstruction;
Jian Li47b26232016-03-07 09:59:59 -080039import org.onosproject.net.meter.MeterId;
Ray Milkeyd43fe452015-05-29 09:35:12 -070040
Jian Li1ef82db2016-03-03 14:43:21 -080041import static org.onlab.util.Tools.nullIsIllegal;
Ray Milkeyd43fe452015-05-29 09:35:12 -070042
43/**
44 * Decoding portion of the instruction codec.
45 */
Ray Milkey6d7968e2015-07-06 14:30:02 -070046public final class DecodeInstructionCodecHelper {
Ray Milkeyd43fe452015-05-29 09:35:12 -070047 private final ObjectNode json;
48
49 /**
50 * Creates a decode instruction codec object.
51 *
52 * @param json JSON object to decode
53 */
Ray Milkey6d7968e2015-07-06 14:30:02 -070054 public DecodeInstructionCodecHelper(ObjectNode json) {
Ray Milkeyd43fe452015-05-29 09:35:12 -070055 this.json = json;
56 }
57
58 /**
59 * Decodes a Layer 2 instruction.
60 *
61 * @return instruction object decoded from the JSON
62 * @throws IllegalArgumentException if the JSON is invalid
63 */
64 private Instruction decodeL2() {
65 String subType = json.get(InstructionCodec.SUBTYPE).asText();
66
67 if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC.name())) {
68 String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
69 InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
70 return Instructions.modL2Src(MacAddress.valueOf(mac));
71 } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST.name())) {
72 String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
73 InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
74 return Instructions.modL2Dst(MacAddress.valueOf(mac));
75 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_ID.name())) {
76 short vlanId = (short) nullIsIllegal(json.get(InstructionCodec.VLAN_ID),
77 InstructionCodec.VLAN_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
78 return Instructions.modVlanId(VlanId.vlanId(vlanId));
79 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PCP.name())) {
80 byte vlanPcp = (byte) nullIsIllegal(json.get(InstructionCodec.VLAN_PCP),
81 InstructionCodec.VLAN_PCP + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
82 return Instructions.modVlanPcp(vlanPcp);
83 } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_LABEL.name())) {
84 int label = nullIsIllegal(json.get(InstructionCodec.MPLS_LABEL),
85 InstructionCodec.MPLS_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
86 return Instructions.modMplsLabel(MplsLabel.mplsLabel(label));
87 } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_PUSH.name())) {
88 return Instructions.pushMpls();
89 } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_POP.name())) {
90 return Instructions.popMpls();
91 } else if (subType.equals(L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name())) {
92 return Instructions.decMplsTtl();
93 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_POP.name())) {
94 return Instructions.popVlan();
95 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PUSH.name())) {
96 return Instructions.pushVlan();
Hyunsun Moon7080a0d2015-08-14 19:18:48 -070097 } else if (subType.equals(L2ModificationInstruction.L2SubType.TUNNEL_ID.name())) {
98 long tunnelId = nullIsIllegal(json.get(InstructionCodec.TUNNEL_ID),
99 InstructionCodec.TUNNEL_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong();
100 return Instructions.modTunnelId(tunnelId);
Ray Milkeyd43fe452015-05-29 09:35:12 -0700101 }
102 throw new IllegalArgumentException("L2 Instruction subtype "
103 + subType + " is not supported");
104 }
105
106 /**
107 * Decodes a Layer 3 instruction.
108 *
109 * @return instruction object decoded from the JSON
110 * @throws IllegalArgumentException if the JSON is invalid
111 */
112 private Instruction decodeL3() {
113 String subType = json.get(InstructionCodec.SUBTYPE).asText();
114
115 if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_SRC.name())) {
116 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
117 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
118 return Instructions.modL3Src(ip);
119 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_DST.name())) {
120 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
121 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
122 return Instructions.modL3Dst(ip);
123 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_SRC.name())) {
124 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
125 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
126 return Instructions.modL3IPv6Src(ip);
127 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_DST.name())) {
128 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
129 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
130 return Instructions.modL3IPv6Dst(ip);
131 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_FLABEL.name())) {
132 int flowLabel = nullIsIllegal(json.get(InstructionCodec.FLOW_LABEL),
133 InstructionCodec.FLOW_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
134 return Instructions.modL3IPv6FlowLabel(flowLabel);
135 }
136 throw new IllegalArgumentException("L3 Instruction subtype "
137 + subType + " is not supported");
138 }
139
140 /**
141 * Decodes a Layer 0 instruction.
142 *
143 * @return instruction object decoded from the JSON
144 * @throws IllegalArgumentException if the JSON is invalid
145 */
146 private Instruction decodeL0() {
147 String subType = json.get(InstructionCodec.SUBTYPE).asText();
148
Sho SHIMIZUcc137a92016-03-11 15:10:54 -0800149 if (subType.equals(L0ModificationInstruction.L0SubType.OCH.name())) {
Ray Milkeyd43fe452015-05-29 09:35:12 -0700150 String gridTypeString = nullIsIllegal(json.get(InstructionCodec.GRID_TYPE),
151 InstructionCodec.GRID_TYPE + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
152 GridType gridType = GridType.valueOf(gridTypeString);
153 if (gridType == null) {
154 throw new IllegalArgumentException("Unknown grid type "
155 + gridTypeString);
156 }
157 String channelSpacingString = nullIsIllegal(json.get(InstructionCodec.CHANNEL_SPACING),
158 InstructionCodec.CHANNEL_SPACING + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
159 ChannelSpacing channelSpacing = ChannelSpacing.valueOf(channelSpacingString);
160 if (channelSpacing == null) {
161 throw new IllegalArgumentException("Unknown channel spacing "
162 + channelSpacingString);
163 }
164 int spacingMultiplier = nullIsIllegal(json.get(InstructionCodec.SPACING_MULTIPLIER),
165 InstructionCodec.SPACING_MULTIPLIER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
166 int slotGranularity = nullIsIllegal(json.get(InstructionCodec.SLOT_GRANULARITY),
167 InstructionCodec.SLOT_GRANULARITY + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
168 return Instructions.modL0Lambda(new OchSignal(gridType, channelSpacing,
169 spacingMultiplier, slotGranularity));
170 }
171 throw new IllegalArgumentException("L0 Instruction subtype "
172 + subType + " is not supported");
173 }
174
175 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300176 * Decodes a Layer 1 instruction.
177 *
178 * @return instruction object decoded from the JSON
179 * @throws IllegalArgumentException if the JSON is invalid
180 */
181 private Instruction decodeL1() {
182 String subType = json.get(InstructionCodec.SUBTYPE).asText();
183 if (subType.equals(L1ModificationInstruction.L1SubType.ODU_SIGID.name())) {
184 int tributaryPortNumber = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_PORT_NUMBER),
185 InstructionCodec.TRIBUTARY_PORT_NUMBER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
186 int tributarySlotLen = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_LEN),
187 InstructionCodec.TRIBUTARY_SLOT_LEN + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
188 byte[] tributarySlotBitmap = null;
189 tributarySlotBitmap = HexString.fromHexString(
190 nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_BITMAP),
191 InstructionCodec.TRIBUTARY_SLOT_BITMAP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
192 return Instructions.modL1OduSignalId(OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen,
193 tributarySlotBitmap));
194 }
195 throw new IllegalArgumentException("L1 Instruction subtype "
196 + subType + " is not supported");
197 }
198
199 /**
Hyunsun Moonfab29502015-08-25 13:39:16 -0700200 * Decodes a Layer 4 instruction.
201 *
202 * @return instruction object decoded from the JSON
203 * @throws IllegalArgumentException if the JSON is invalid
204 */
205 private Instruction decodeL4() {
206 String subType = json.get(InstructionCodec.SUBTYPE).asText();
207
208 if (subType.equals(L4ModificationInstruction.L4SubType.TCP_DST.name())) {
209 TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT),
210 InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
211 return Instructions.modTcpDst(tcpPort);
212 } else if (subType.equals(L4ModificationInstruction.L4SubType.TCP_SRC.name())) {
213 TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT),
214 InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
215 return Instructions.modTcpSrc(tcpPort);
216 } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_DST.name())) {
217 TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT),
218 InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
219 return Instructions.modUdpDst(udpPort);
220 } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_SRC.name())) {
221 TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT),
222 InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
223 return Instructions.modUdpSrc(udpPort);
224 }
225 throw new IllegalArgumentException("L4 Instruction subtype "
226 + subType + " is not supported");
227 }
228
229 /**
Jian Li70dffe42016-03-08 22:23:02 -0800230 * Extracts port number of the given json node.
231 *
232 * @param jsonNode json node
233 * @return port number
234 */
235 private PortNumber getPortNumber(ObjectNode jsonNode) {
236 PortNumber portNumber;
237 if (jsonNode.get(InstructionCodec.PORT).isLong() || jsonNode.get(InstructionCodec.PORT).isInt()) {
238 portNumber = PortNumber
239 .portNumber(nullIsIllegal(jsonNode.get(InstructionCodec.PORT)
240 .asLong(), InstructionCodec.PORT
241 + InstructionCodec.MISSING_MEMBER_MESSAGE));
242 } else if (jsonNode.get(InstructionCodec.PORT).isTextual()) {
243 portNumber = PortNumber
244 .fromString(nullIsIllegal(jsonNode.get(InstructionCodec.PORT)
245 .textValue(), InstructionCodec.PORT
246 + InstructionCodec.MISSING_MEMBER_MESSAGE));
247 } else {
248 throw new IllegalArgumentException("Port value "
249 + jsonNode.get(InstructionCodec.PORT).toString()
250 + " is not supported");
251 }
252 return portNumber;
253 }
254
255 /**
Ray Milkeyd43fe452015-05-29 09:35:12 -0700256 * Decodes the JSON into an instruction object.
257 *
258 * @return Criterion object
259 * @throws IllegalArgumentException if the JSON is invalid
260 */
261 public Instruction decode() {
262 String type = json.get(InstructionCodec.TYPE).asText();
263
264 if (type.equals(Instruction.Type.OUTPUT.name())) {
Jian Li70dffe42016-03-08 22:23:02 -0800265 return Instructions.createOutput(getPortNumber(json));
Ray Milkey2be39ed2016-02-22 15:54:19 -0800266 } else if (type.equals(Instruction.Type.NOACTION.name())) {
267 return Instructions.createNoAction();
Jian Li1ef82db2016-03-03 14:43:21 -0800268 } else if (type.equals(Instruction.Type.TABLE.name())) {
269 return Instructions.transition(nullIsIllegal(json.get(InstructionCodec.TABLE_ID)
270 .asInt(), InstructionCodec.TABLE_ID + InstructionCodec.MISSING_MEMBER_MESSAGE));
Jian Lice8c5602016-03-03 21:43:24 -0800271 } else if (type.equals(Instruction.Type.GROUP.name())) {
272 GroupId groupId = new DefaultGroupId(nullIsIllegal(json.get(InstructionCodec.GROUP_ID)
273 .asInt(), InstructionCodec.GROUP_ID + InstructionCodec.MISSING_MEMBER_MESSAGE));
274 return Instructions.createGroup(groupId);
Jian Li47b26232016-03-07 09:59:59 -0800275 } else if (type.equals(Instruction.Type.METER.name())) {
276 MeterId meterId = MeterId.meterId(nullIsIllegal(json.get(InstructionCodec.METER_ID)
277 .asLong(), InstructionCodec.METER_ID + InstructionCodec.MISSING_MEMBER_MESSAGE));
278 return Instructions.meterTraffic(meterId);
Jian Li70dffe42016-03-08 22:23:02 -0800279 } else if (type.equals(Instruction.Type.QUEUE.name())) {
280 long queueId = nullIsIllegal(json.get(InstructionCodec.QUEUE_ID)
281 .asLong(), InstructionCodec.QUEUE_ID + InstructionCodec.MISSING_MEMBER_MESSAGE);
282 return Instructions.setQueue(queueId, getPortNumber(json));
Ray Milkeyd43fe452015-05-29 09:35:12 -0700283 } else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
284 return decodeL0();
Yafit Hadar5796d972015-10-15 13:16:11 +0300285 } else if (type.equals(Instruction.Type.L1MODIFICATION.name())) {
286 return decodeL1();
Ray Milkeyd43fe452015-05-29 09:35:12 -0700287 } else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
288 return decodeL2();
289 } else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
290 return decodeL3();
Hyunsun Moonfab29502015-08-25 13:39:16 -0700291 } else if (type.equals(Instruction.Type.L4MODIFICATION.name())) {
292 return decodeL4();
Ray Milkeyd43fe452015-05-29 09:35:12 -0700293 }
294 throw new IllegalArgumentException("Instruction type "
295 + type + " is not supported");
296 }
Ray Milkeyd43fe452015-05-29 09:35:12 -0700297}