blob: b70a684b94527e322a0e3d34e2e0f3ba22f09c17 [file] [log] [blame]
Ray Milkeyd43fe452015-05-29 09:35:12 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Ray Milkeyd43fe452015-05-29 09:35:12 -07003 *
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 Lidab72562016-04-12 14:10:32 -070018import com.fasterxml.jackson.databind.JsonNode;
Jian Li1ef82db2016-03-03 14:43:21 -080019import com.fasterxml.jackson.databind.node.ObjectNode;
Jian Lidab72562016-04-12 14:10:32 -070020import org.onlab.osgi.DefaultServiceDirectory;
21import org.onlab.osgi.ServiceDirectory;
Ray Milkeyd43fe452015-05-29 09:35:12 -070022import org.onlab.packet.IpAddress;
23import org.onlab.packet.MacAddress;
24import org.onlab.packet.MplsLabel;
Hyunsun Moonfab29502015-08-25 13:39:16 -070025import org.onlab.packet.TpPort;
Ray Milkeyd43fe452015-05-29 09:35:12 -070026import org.onlab.packet.VlanId;
Yafit Hadar5796d972015-10-15 13:16:11 +030027import org.onlab.util.HexString;
Jian Lidab72562016-04-12 14:10:32 -070028import org.onosproject.codec.ExtensionTreatmentCodec;
Jian Lice8c5602016-03-03 21:43:24 -080029import org.onosproject.core.DefaultGroupId;
30import org.onosproject.core.GroupId;
Ray Milkeyd43fe452015-05-29 09:35:12 -070031import org.onosproject.net.ChannelSpacing;
Jian Lidab72562016-04-12 14:10:32 -070032import org.onosproject.net.Device;
33import org.onosproject.net.DeviceId;
Ray Milkeyd43fe452015-05-29 09:35:12 -070034import org.onosproject.net.GridType;
Ray Milkeyd43fe452015-05-29 09:35:12 -070035import org.onosproject.net.OchSignal;
Yafit Hadar5796d972015-10-15 13:16:11 +030036import org.onosproject.net.OduSignalId;
Ray Milkeyd43fe452015-05-29 09:35:12 -070037import org.onosproject.net.PortNumber;
Jian Lidab72562016-04-12 14:10:32 -070038import org.onosproject.net.device.DeviceService;
39import org.onosproject.net.flow.instructions.ExtensionTreatment;
Ray Milkeyd43fe452015-05-29 09:35:12 -070040import org.onosproject.net.flow.instructions.Instruction;
41import org.onosproject.net.flow.instructions.Instructions;
42import org.onosproject.net.flow.instructions.L0ModificationInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030043import org.onosproject.net.flow.instructions.L1ModificationInstruction;
Ray Milkeyd43fe452015-05-29 09:35:12 -070044import org.onosproject.net.flow.instructions.L2ModificationInstruction;
45import org.onosproject.net.flow.instructions.L3ModificationInstruction;
Hyunsun Moonfab29502015-08-25 13:39:16 -070046import org.onosproject.net.flow.instructions.L4ModificationInstruction;
Jian Li47b26232016-03-07 09:59:59 -080047import org.onosproject.net.meter.MeterId;
Jian Lidab72562016-04-12 14:10:32 -070048import org.slf4j.Logger;
Ray Milkeyd43fe452015-05-29 09:35:12 -070049
Jian Li1ef82db2016-03-03 14:43:21 -080050import static org.onlab.util.Tools.nullIsIllegal;
Jian Lidab72562016-04-12 14:10:32 -070051import static org.slf4j.LoggerFactory.getLogger;
Ray Milkeyd43fe452015-05-29 09:35:12 -070052
53/**
54 * Decoding portion of the instruction codec.
55 */
Ray Milkey6d7968e2015-07-06 14:30:02 -070056public final class DecodeInstructionCodecHelper {
Jian Lidab72562016-04-12 14:10:32 -070057 protected static final Logger log = getLogger(DecodeInstructionCodecHelper.class);
Ray Milkeyd43fe452015-05-29 09:35:12 -070058 private final ObjectNode json;
59
60 /**
61 * Creates a decode instruction codec object.
62 *
63 * @param json JSON object to decode
64 */
Ray Milkey6d7968e2015-07-06 14:30:02 -070065 public DecodeInstructionCodecHelper(ObjectNode json) {
Ray Milkeyd43fe452015-05-29 09:35:12 -070066 this.json = json;
67 }
68
69 /**
70 * Decodes a Layer 2 instruction.
71 *
72 * @return instruction object decoded from the JSON
73 * @throws IllegalArgumentException if the JSON is invalid
74 */
75 private Instruction decodeL2() {
76 String subType = json.get(InstructionCodec.SUBTYPE).asText();
77
78 if (subType.equals(L2ModificationInstruction.L2SubType.ETH_SRC.name())) {
79 String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
80 InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
81 return Instructions.modL2Src(MacAddress.valueOf(mac));
82 } else if (subType.equals(L2ModificationInstruction.L2SubType.ETH_DST.name())) {
83 String mac = nullIsIllegal(json.get(InstructionCodec.MAC),
84 InstructionCodec.MAC + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
85 return Instructions.modL2Dst(MacAddress.valueOf(mac));
86 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_ID.name())) {
87 short vlanId = (short) nullIsIllegal(json.get(InstructionCodec.VLAN_ID),
88 InstructionCodec.VLAN_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
89 return Instructions.modVlanId(VlanId.vlanId(vlanId));
90 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PCP.name())) {
91 byte vlanPcp = (byte) nullIsIllegal(json.get(InstructionCodec.VLAN_PCP),
92 InstructionCodec.VLAN_PCP + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
93 return Instructions.modVlanPcp(vlanPcp);
94 } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_LABEL.name())) {
95 int label = nullIsIllegal(json.get(InstructionCodec.MPLS_LABEL),
96 InstructionCodec.MPLS_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
97 return Instructions.modMplsLabel(MplsLabel.mplsLabel(label));
98 } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_PUSH.name())) {
99 return Instructions.pushMpls();
100 } else if (subType.equals(L2ModificationInstruction.L2SubType.MPLS_POP.name())) {
101 return Instructions.popMpls();
102 } else if (subType.equals(L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name())) {
103 return Instructions.decMplsTtl();
104 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_POP.name())) {
105 return Instructions.popVlan();
106 } else if (subType.equals(L2ModificationInstruction.L2SubType.VLAN_PUSH.name())) {
107 return Instructions.pushVlan();
Hyunsun Moon7080a0d2015-08-14 19:18:48 -0700108 } else if (subType.equals(L2ModificationInstruction.L2SubType.TUNNEL_ID.name())) {
109 long tunnelId = nullIsIllegal(json.get(InstructionCodec.TUNNEL_ID),
110 InstructionCodec.TUNNEL_ID + InstructionCodec.MISSING_MEMBER_MESSAGE).asLong();
111 return Instructions.modTunnelId(tunnelId);
Ray Milkeyd43fe452015-05-29 09:35:12 -0700112 }
113 throw new IllegalArgumentException("L2 Instruction subtype "
114 + subType + " is not supported");
115 }
116
117 /**
118 * Decodes a Layer 3 instruction.
119 *
120 * @return instruction object decoded from the JSON
121 * @throws IllegalArgumentException if the JSON is invalid
122 */
123 private Instruction decodeL3() {
124 String subType = json.get(InstructionCodec.SUBTYPE).asText();
125
126 if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_SRC.name())) {
127 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
128 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
129 return Instructions.modL3Src(ip);
130 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV4_DST.name())) {
131 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
132 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
133 return Instructions.modL3Dst(ip);
134 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_SRC.name())) {
135 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
136 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
137 return Instructions.modL3IPv6Src(ip);
138 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_DST.name())) {
139 IpAddress ip = IpAddress.valueOf(nullIsIllegal(json.get(InstructionCodec.IP),
140 InstructionCodec.IP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
141 return Instructions.modL3IPv6Dst(ip);
142 } else if (subType.equals(L3ModificationInstruction.L3SubType.IPV6_FLABEL.name())) {
143 int flowLabel = nullIsIllegal(json.get(InstructionCodec.FLOW_LABEL),
144 InstructionCodec.FLOW_LABEL + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
145 return Instructions.modL3IPv6FlowLabel(flowLabel);
146 }
147 throw new IllegalArgumentException("L3 Instruction subtype "
148 + subType + " is not supported");
149 }
150
151 /**
152 * Decodes a Layer 0 instruction.
153 *
154 * @return instruction object decoded from the JSON
155 * @throws IllegalArgumentException if the JSON is invalid
156 */
157 private Instruction decodeL0() {
158 String subType = json.get(InstructionCodec.SUBTYPE).asText();
159
Sho SHIMIZUcc137a92016-03-11 15:10:54 -0800160 if (subType.equals(L0ModificationInstruction.L0SubType.OCH.name())) {
Ray Milkeyd43fe452015-05-29 09:35:12 -0700161 String gridTypeString = nullIsIllegal(json.get(InstructionCodec.GRID_TYPE),
162 InstructionCodec.GRID_TYPE + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
163 GridType gridType = GridType.valueOf(gridTypeString);
164 if (gridType == null) {
165 throw new IllegalArgumentException("Unknown grid type "
166 + gridTypeString);
167 }
168 String channelSpacingString = nullIsIllegal(json.get(InstructionCodec.CHANNEL_SPACING),
169 InstructionCodec.CHANNEL_SPACING + InstructionCodec.MISSING_MEMBER_MESSAGE).asText();
170 ChannelSpacing channelSpacing = ChannelSpacing.valueOf(channelSpacingString);
171 if (channelSpacing == null) {
172 throw new IllegalArgumentException("Unknown channel spacing "
173 + channelSpacingString);
174 }
175 int spacingMultiplier = nullIsIllegal(json.get(InstructionCodec.SPACING_MULTIPLIER),
176 InstructionCodec.SPACING_MULTIPLIER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
177 int slotGranularity = nullIsIllegal(json.get(InstructionCodec.SLOT_GRANULARITY),
178 InstructionCodec.SLOT_GRANULARITY + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
179 return Instructions.modL0Lambda(new OchSignal(gridType, channelSpacing,
180 spacingMultiplier, slotGranularity));
181 }
182 throw new IllegalArgumentException("L0 Instruction subtype "
183 + subType + " is not supported");
184 }
185
186 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300187 * Decodes a Layer 1 instruction.
188 *
189 * @return instruction object decoded from the JSON
190 * @throws IllegalArgumentException if the JSON is invalid
191 */
192 private Instruction decodeL1() {
193 String subType = json.get(InstructionCodec.SUBTYPE).asText();
194 if (subType.equals(L1ModificationInstruction.L1SubType.ODU_SIGID.name())) {
195 int tributaryPortNumber = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_PORT_NUMBER),
196 InstructionCodec.TRIBUTARY_PORT_NUMBER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
197 int tributarySlotLen = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_LEN),
198 InstructionCodec.TRIBUTARY_SLOT_LEN + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
199 byte[] tributarySlotBitmap = null;
200 tributarySlotBitmap = HexString.fromHexString(
201 nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_BITMAP),
202 InstructionCodec.TRIBUTARY_SLOT_BITMAP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
203 return Instructions.modL1OduSignalId(OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen,
204 tributarySlotBitmap));
205 }
206 throw new IllegalArgumentException("L1 Instruction subtype "
207 + subType + " is not supported");
208 }
209
210 /**
Hyunsun Moonfab29502015-08-25 13:39:16 -0700211 * Decodes a Layer 4 instruction.
212 *
213 * @return instruction object decoded from the JSON
214 * @throws IllegalArgumentException if the JSON is invalid
215 */
216 private Instruction decodeL4() {
217 String subType = json.get(InstructionCodec.SUBTYPE).asText();
218
219 if (subType.equals(L4ModificationInstruction.L4SubType.TCP_DST.name())) {
220 TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT),
221 InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
222 return Instructions.modTcpDst(tcpPort);
223 } else if (subType.equals(L4ModificationInstruction.L4SubType.TCP_SRC.name())) {
224 TpPort tcpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.TCP_PORT),
225 InstructionCodec.TCP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
226 return Instructions.modTcpSrc(tcpPort);
227 } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_DST.name())) {
228 TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT),
229 InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
230 return Instructions.modUdpDst(udpPort);
231 } else if (subType.equals(L4ModificationInstruction.L4SubType.UDP_SRC.name())) {
232 TpPort udpPort = TpPort.tpPort(nullIsIllegal(json.get(InstructionCodec.UDP_PORT),
233 InstructionCodec.UDP_PORT + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt());
234 return Instructions.modUdpSrc(udpPort);
235 }
236 throw new IllegalArgumentException("L4 Instruction subtype "
237 + subType + " is not supported");
238 }
239
240 /**
Jian Lidab72562016-04-12 14:10:32 -0700241 * Decodes a extension instruction.
242 *
243 * @return extension treatment
244 */
245 private Instruction decodeExtension() {
246 ObjectNode node = (ObjectNode) json.get(InstructionCodec.EXTENSION);
247 if (node != null) {
248 DeviceId deviceId = getDeviceId();
249
250 ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
251 DeviceService deviceService = serviceDirectory.get(DeviceService.class);
252 Device device = deviceService.getDevice(deviceId);
253
254 if (device.is(ExtensionTreatmentCodec.class)) {
255 ExtensionTreatmentCodec treatmentCodec = device.as(ExtensionTreatmentCodec.class);
256 ExtensionTreatment treatment = treatmentCodec.decode(node, null);
257 return Instructions.extension(treatment, deviceId);
258 } else {
259 log.warn("There is no codec to decode extension for device {}", deviceId.toString());
260 }
261 }
262 return null;
263 }
264
265 /**
266 * Returns device identifier.
267 *
268 * @return device identifier
269 * @throws IllegalArgumentException if the JSON is invalid
270 */
271 private DeviceId getDeviceId() {
272 JsonNode deviceIdNode = json.get(InstructionCodec.DEVICE_ID);
273 if (deviceIdNode != null) {
274 return DeviceId.deviceId(deviceIdNode.asText());
275 }
276 throw new IllegalArgumentException("Empty device identifier");
277 }
278
279 /**
Jian Li70dffe42016-03-08 22:23:02 -0800280 * Extracts port number of the given json node.
281 *
282 * @param jsonNode json node
283 * @return port number
284 */
285 private PortNumber getPortNumber(ObjectNode jsonNode) {
286 PortNumber portNumber;
287 if (jsonNode.get(InstructionCodec.PORT).isLong() || jsonNode.get(InstructionCodec.PORT).isInt()) {
288 portNumber = PortNumber
289 .portNumber(nullIsIllegal(jsonNode.get(InstructionCodec.PORT)
290 .asLong(), InstructionCodec.PORT
291 + InstructionCodec.MISSING_MEMBER_MESSAGE));
292 } else if (jsonNode.get(InstructionCodec.PORT).isTextual()) {
293 portNumber = PortNumber
294 .fromString(nullIsIllegal(jsonNode.get(InstructionCodec.PORT)
295 .textValue(), InstructionCodec.PORT
296 + InstructionCodec.MISSING_MEMBER_MESSAGE));
297 } else {
298 throw new IllegalArgumentException("Port value "
299 + jsonNode.get(InstructionCodec.PORT).toString()
300 + " is not supported");
301 }
302 return portNumber;
303 }
304
305 /**
Ray Milkeyd43fe452015-05-29 09:35:12 -0700306 * Decodes the JSON into an instruction object.
307 *
308 * @return Criterion object
309 * @throws IllegalArgumentException if the JSON is invalid
310 */
311 public Instruction decode() {
312 String type = json.get(InstructionCodec.TYPE).asText();
313
314 if (type.equals(Instruction.Type.OUTPUT.name())) {
Jian Li70dffe42016-03-08 22:23:02 -0800315 return Instructions.createOutput(getPortNumber(json));
Ray Milkey2be39ed2016-02-22 15:54:19 -0800316 } else if (type.equals(Instruction.Type.NOACTION.name())) {
317 return Instructions.createNoAction();
Jian Li1ef82db2016-03-03 14:43:21 -0800318 } else if (type.equals(Instruction.Type.TABLE.name())) {
319 return Instructions.transition(nullIsIllegal(json.get(InstructionCodec.TABLE_ID)
320 .asInt(), InstructionCodec.TABLE_ID + InstructionCodec.MISSING_MEMBER_MESSAGE));
Jian Lice8c5602016-03-03 21:43:24 -0800321 } else if (type.equals(Instruction.Type.GROUP.name())) {
322 GroupId groupId = new DefaultGroupId(nullIsIllegal(json.get(InstructionCodec.GROUP_ID)
323 .asInt(), InstructionCodec.GROUP_ID + InstructionCodec.MISSING_MEMBER_MESSAGE));
324 return Instructions.createGroup(groupId);
Jian Li47b26232016-03-07 09:59:59 -0800325 } else if (type.equals(Instruction.Type.METER.name())) {
326 MeterId meterId = MeterId.meterId(nullIsIllegal(json.get(InstructionCodec.METER_ID)
327 .asLong(), InstructionCodec.METER_ID + InstructionCodec.MISSING_MEMBER_MESSAGE));
328 return Instructions.meterTraffic(meterId);
Jian Li70dffe42016-03-08 22:23:02 -0800329 } else if (type.equals(Instruction.Type.QUEUE.name())) {
330 long queueId = nullIsIllegal(json.get(InstructionCodec.QUEUE_ID)
331 .asLong(), InstructionCodec.QUEUE_ID + InstructionCodec.MISSING_MEMBER_MESSAGE);
332 return Instructions.setQueue(queueId, getPortNumber(json));
Ray Milkeyd43fe452015-05-29 09:35:12 -0700333 } else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
334 return decodeL0();
Yafit Hadar5796d972015-10-15 13:16:11 +0300335 } else if (type.equals(Instruction.Type.L1MODIFICATION.name())) {
336 return decodeL1();
Ray Milkeyd43fe452015-05-29 09:35:12 -0700337 } else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
338 return decodeL2();
339 } else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
340 return decodeL3();
Hyunsun Moonfab29502015-08-25 13:39:16 -0700341 } else if (type.equals(Instruction.Type.L4MODIFICATION.name())) {
342 return decodeL4();
Jian Lidab72562016-04-12 14:10:32 -0700343 } else if (type.equals(Instruction.Type.EXTENSION.name())) {
344 return decodeExtension();
Ray Milkeyd43fe452015-05-29 09:35:12 -0700345 }
346 throw new IllegalArgumentException("Instruction type "
347 + type + " is not supported");
348 }
Ray Milkeyd43fe452015-05-29 09:35:12 -0700349}