blob: 2a89b262c0cdf83ce5bf7a478b64ff6ae5f768b4 [file] [log] [blame]
Charles Chancad338a2016-09-16 18:03:11 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Charles Chancad338a2016-09-16 18:03:11 -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 */
16
17package org.onosproject.driver.extensions;
18
Jonghwan Hyun360b02f2017-08-11 14:00:07 -070019import com.fasterxml.jackson.databind.node.ObjectNode;
Pier Ventre6f630052016-10-18 09:58:41 -070020import org.onlab.packet.VlanId;
Jonghwan Hyun360b02f2017-08-11 14:00:07 -070021import org.onosproject.codec.CodecContext;
Charles Chancad338a2016-09-16 18:03:11 -070022import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
23import org.onosproject.net.driver.AbstractHandlerBehaviour;
24import org.onosproject.net.flow.instructions.ExtensionTreatment;
25import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
26import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter;
27import org.projectfloodlight.openflow.protocol.OFActionType;
28import org.projectfloodlight.openflow.protocol.OFFactory;
29import org.projectfloodlight.openflow.protocol.action.OFAction;
Pier Ventreee4a8f22016-10-22 15:45:36 -070030import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
31import org.projectfloodlight.openflow.protocol.action.OFActionOfdpa;
Charles Chancad338a2016-09-16 18:03:11 -070032import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
33import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
Pier Ventre9cf536b2016-10-21 13:30:18 -070034import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaMplsL2Port;
Charles Chancad338a2016-09-16 18:03:11 -070035import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaMplsType;
Pier Ventre6f630052016-10-18 09:58:41 -070036import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaOvid;
Pier Ventredb252cc2016-10-21 21:54:26 -070037import org.projectfloodlight.openflow.protocol.oxm.OFOxmOfdpaQosIndex;
Charles Chancad338a2016-09-16 18:03:11 -070038import org.projectfloodlight.openflow.types.U16;
Pier Ventre9cf536b2016-10-21 13:30:18 -070039import org.projectfloodlight.openflow.types.U32;
Pier Ventredb252cc2016-10-21 21:54:26 -070040import org.projectfloodlight.openflow.types.U8;
Pier Ventre6f630052016-10-18 09:58:41 -070041import org.slf4j.Logger;
42import org.slf4j.LoggerFactory;
Charles Chancad338a2016-09-16 18:03:11 -070043
Jonghwan Hyun360b02f2017-08-11 14:00:07 -070044import static com.google.common.base.Preconditions.checkNotNull;
45import static org.onlab.util.Tools.nullIsIllegal;
46
Charles Chancad338a2016-09-16 18:03:11 -070047/**
48 * Interpreter for OFDPA3 OpenFlow treatment extensions.
49 */
50public class Ofdpa3ExtensionTreatmentInterpreter extends AbstractHandlerBehaviour
51 implements ExtensionTreatmentInterpreter, ExtensionTreatmentResolver {
Pier Ventre6f630052016-10-18 09:58:41 -070052
Pier Ventreee4a8f22016-10-22 15:45:36 -070053 private static final int TYPE_OFDPA = 0x1018;
54 private static final int SUB_TYPE_PUSH_L2_HEADER = 1;
55 private static final int SUB_TYPE_POP_L2_HEADER = 2;
56 private static final int SUB_TYPE_PUSH_CW = 3;
57 private static final int SUB_TYPE_POP_CW = 4;
58
Jonghwan Hyun360b02f2017-08-11 14:00:07 -070059 private static final String TYPE = "type";
60 private static final String MISSING_MEMBER_MESSAGE = " member is required in Ofdpa3ExtensionTreatmentInterpreter";
61 private static final String MISSING_TREATMENT_MESSAGE = "Extension treatment cannot be null";
62 private static final String NOT_SUPPORTED_MESSAGE = "Driver does not support extension type of ";
63
Pier Ventre6f630052016-10-18 09:58:41 -070064 private final Logger log = LoggerFactory.getLogger(getClass());
65
Charles Chancad338a2016-09-16 18:03:11 -070066 @Override
67 public boolean supported(ExtensionTreatmentType extensionTreatmentType) {
68 if (extensionTreatmentType.equals(
69 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.type())) {
70 return true;
Pier Ventre6f630052016-10-18 09:58:41 -070071 } else if (extensionTreatmentType.equals(
72 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.type())) {
73 return true;
Pier Ventre9cf536b2016-10-21 13:30:18 -070074 } else if (extensionTreatmentType.equals(
75 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
76 return true;
Pier Ventredb252cc2016-10-21 21:54:26 -070077 } else if (extensionTreatmentType.equals(
78 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
79 return true;
Pier Ventreee4a8f22016-10-22 15:45:36 -070080 } else if (extensionTreatmentType.equals(
81 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.type())) {
82 return true;
83 } else if (extensionTreatmentType.equals(
84 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.type())) {
85 return true;
86 } else if (extensionTreatmentType.equals(
87 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.type())) {
88 return true;
89 } else if (extensionTreatmentType.equals(
90 ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.type())) {
91 return true;
Charles Chancad338a2016-09-16 18:03:11 -070092 }
93 return false;
94 }
95
96 @Override
97 public OFAction mapInstruction(OFFactory factory, ExtensionTreatment extensionTreatment) {
98 ExtensionTreatmentType type = extensionTreatment.type();
99 if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.type())) {
100 short mplsType = ((Ofdpa3SetMplsType) extensionTreatment).mplsType();
101 return factory.actions().setField(factory.oxms().ofdpaMplsType(
102 U16.ofRaw(mplsType)));
Pier Ventre6f630052016-10-18 09:58:41 -0700103 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.type())) {
104 // OFDPA requires isPresent bit set to 1 for OVID.
105 VlanId vlanId = ((Ofdpa3SetOvid) extensionTreatment).vlanId();
106 short mask = (short) 0x1000;
107 short oVid = (short) (mask | vlanId.toShort());
108 return factory.actions().setField(factory.oxms().ofdpaOvid(
109 U16.ofRaw(oVid)));
Pier Ventre9cf536b2016-10-21 13:30:18 -0700110 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
111 Integer mplsL2Port = ((Ofdpa3SetMplsL2Port) extensionTreatment).mplsL2Port();
112 /*
113 * 0x0000XXXX UNI Interface.
114 * 0x0002XXXX NNI Interface
115 */
116 if ((mplsL2Port >= 0 && mplsL2Port <= 0x0000FFFF) ||
117 (mplsL2Port >= 0x00020000 && mplsL2Port <= 0x0002FFFF)) {
118 return factory.actions().setField(
119 factory.oxms().ofdpaMplsL2Port(U32.ofRaw(mplsL2Port))
120 );
121 }
122 throw new UnsupportedOperationException(
123 "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
Pier Ventredb252cc2016-10-21 21:54:26 -0700124 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
125 Integer qosIndex = ((Ofdpa3SetQosIndex) extensionTreatment).qosIndex();
126 /*
127 * Qos index is a single byte [0...255]
128 */
129 if (qosIndex >= 0 && qosIndex <= 255) {
130 return factory.actions().setField(
131 factory.oxms().ofdpaQosIndex(U8.ofRaw((byte) (qosIndex & 0xFF)))
132 );
133 }
134 throw new UnsupportedOperationException(
135 "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
Pier Ventreee4a8f22016-10-22 15:45:36 -0700136 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.type())) {
137 return factory.actions().ofdpaPushL2Header();
138 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.type())) {
139 return factory.actions().ofdpaPushCw();
140 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.type())) {
141 return factory.actions().ofdpaPopL2Header();
142 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.type())) {
143 return factory.actions().ofdpaPopCw();
Charles Chancad338a2016-09-16 18:03:11 -0700144 }
145 throw new UnsupportedOperationException(
146 "Unexpected ExtensionTreatment: " + extensionTreatment.toString());
147 }
148
149 @Override
150 public ExtensionTreatment mapAction(OFAction action) throws UnsupportedOperationException {
151 if (action.getType().equals(OFActionType.SET_FIELD)) {
152 OFActionSetField setFieldAction = (OFActionSetField) action;
153 OFOxm<?> oxm = setFieldAction.getField();
154 switch (oxm.getMatchField().id) {
155 case OFDPA_MPLS_TYPE:
156 OFOxmOfdpaMplsType mplsType = (OFOxmOfdpaMplsType) oxm;
157 return new Ofdpa3SetMplsType(mplsType.getValue().getRaw());
Pier Ventre6f630052016-10-18 09:58:41 -0700158 case OFDPA_OVID:
159 OFOxmOfdpaOvid ovid = ((OFOxmOfdpaOvid) oxm);
160 short mask = (short) 0x0FFF;
161 short oVid = (short) (mask & ovid.getValue().getRaw());
162 VlanId vlanId = VlanId.vlanId(oVid);
163 return new Ofdpa3SetOvid(vlanId);
Pier Ventre9cf536b2016-10-21 13:30:18 -0700164 case OFDPA_MPLS_L2_PORT:
165 OFOxmOfdpaMplsL2Port mplsl2Port = ((OFOxmOfdpaMplsL2Port) oxm);
166 Integer mplsL2Port = mplsl2Port.getValue().getRaw();
167 if ((mplsL2Port >= 0 && mplsL2Port <= 0x0000FFFF) ||
168 (mplsL2Port >= 0x00020000 && mplsL2Port <= 0x0002FFFF)) {
169 return new Ofdpa3SetMplsL2Port(mplsL2Port);
170 }
Pier Ventredb252cc2016-10-21 21:54:26 -0700171 break;
172 case OFDPA_QOS_INDEX:
173 OFOxmOfdpaQosIndex qosindex = ((OFOxmOfdpaQosIndex) oxm);
174 Integer qosIndex = (int) qosindex.getValue().getRaw();
175 if (qosIndex >= 0 && qosIndex <= 255) {
176 return new Ofdpa3SetQosIndex(qosIndex);
177 }
178 break;
Charles Chancad338a2016-09-16 18:03:11 -0700179 default:
180 throw new UnsupportedOperationException(
181 "Driver does not support extension type " + oxm.getMatchField().id);
182 }
Pier Ventreee4a8f22016-10-22 15:45:36 -0700183 } else if (action.getType().equals(OFActionType.EXPERIMENTER)) {
184 OFActionExperimenter experimenter = (OFActionExperimenter) action;
185 if (Long.valueOf(experimenter.getExperimenter()).intValue() == TYPE_OFDPA) {
186 OFActionOfdpa ofdpa = (OFActionOfdpa) experimenter;
187 switch (ofdpa.getExpType()) {
188 case SUB_TYPE_PUSH_L2_HEADER:
189 return new Ofdpa3PushL2Header();
190 case SUB_TYPE_POP_L2_HEADER:
191 return new Ofdpa3PopL2Header();
192 case SUB_TYPE_PUSH_CW:
193 return new Ofdpa3PushCw();
194 case SUB_TYPE_POP_CW:
195 return new Ofdpa3PopCw();
196 default:
197 throw new UnsupportedOperationException(
198 "Unexpected OFAction: " + action.toString());
199 }
200 }
201 throw new UnsupportedOperationException(
202 "Unexpected OFAction: " + action.toString());
Charles Chancad338a2016-09-16 18:03:11 -0700203 }
204 throw new UnsupportedOperationException(
205 "Unexpected OFAction: " + action.toString());
206 }
207
208 @Override
209 public ExtensionTreatment getExtensionInstruction(ExtensionTreatmentType type) {
210 if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.type())) {
211 return new Ofdpa3SetMplsType();
Pier Ventre6f630052016-10-18 09:58:41 -0700212 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.type())) {
213 return new Ofdpa3SetOvid();
Pier Ventre9cf536b2016-10-21 13:30:18 -0700214 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
215 return new Ofdpa3SetMplsL2Port();
Pier Ventredb252cc2016-10-21 21:54:26 -0700216 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
217 return new Ofdpa3SetQosIndex();
Pier Ventreee4a8f22016-10-22 15:45:36 -0700218 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.type())) {
219 return new Ofdpa3PushL2Header();
220 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.type())) {
221 return new Ofdpa3PushCw();
222 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.type())) {
223 return new Ofdpa3PopL2Header();
224 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.type())) {
225 return new Ofdpa3PopCw();
Charles Chancad338a2016-09-16 18:03:11 -0700226 }
Jonghwan Hyun360b02f2017-08-11 14:00:07 -0700227 throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE + type.toString());
228 }
229
230 @Override
231 public ObjectNode encode(ExtensionTreatment extensionTreatment, CodecContext context) {
232 checkNotNull(extensionTreatment, MISSING_TREATMENT_MESSAGE);
233 ExtensionTreatmentType type = extensionTreatment.type();
234 ObjectNode root = context.mapper().createObjectNode();
235
236 if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.type())) {
237 Ofdpa3SetMplsType setMplsType = (Ofdpa3SetMplsType) extensionTreatment;
238 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.name());
239 root.setAll(context.codec(Ofdpa3SetMplsType.class).encode(setMplsType, context));
240 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.type())) {
241 Ofdpa3SetOvid setOvid = (Ofdpa3SetOvid) extensionTreatment;
242 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.name());
243 root.setAll(context.codec(Ofdpa3SetOvid.class).encode(setOvid, context));
244 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.type())) {
245 Ofdpa3SetMplsL2Port setMplsL2Port = (Ofdpa3SetMplsL2Port) extensionTreatment;
246 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.name());
247 root.setAll(context.codec(Ofdpa3SetMplsL2Port.class).encode(setMplsL2Port, context));
248 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.type())) {
249 Ofdpa3SetQosIndex setQosIndex = (Ofdpa3SetQosIndex) extensionTreatment;
250 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.name());
251 root.setAll(context.codec(Ofdpa3SetQosIndex.class).encode(setQosIndex, context));
252 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.type())) {
253 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.name());
254 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.type())) {
255 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.name());
256 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.type())) {
257 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.name());
258 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.type())) {
259 root.put(TYPE, ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.name());
260 }
261
262 return root;
263 }
264
265 @Override
266 public ExtensionTreatment decode(ObjectNode json, CodecContext context) {
267 if (json == null || !json.isObject()) {
268 return null;
269 }
270
271 String type = nullIsIllegal(json.get(TYPE), TYPE + MISSING_MEMBER_MESSAGE).asText();
272
273 if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_TYPE.name())) {
274 return context.codec(Ofdpa3SetMplsType.class).decode(json, context);
275 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_OVID.name())) {
276 return context.codec(Ofdpa3SetOvid.class).decode(json, context);
277 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_MPLS_L2_PORT.name())) {
278 return context.codec(Ofdpa3SetMplsL2Port.class).decode(json, context);
279 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_SET_QOS_INDEX.name())) {
280 return context.codec(Ofdpa3SetQosIndex.class).decode(json, context);
281 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_L2_HEADER.name())) {
282 return new Ofdpa3PushL2Header();
283 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_PUSH_CW.name())) {
284 return new Ofdpa3PushCw();
285 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_L2_HEADER.name())) {
286 return new Ofdpa3PopL2Header();
287 } else if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.OFDPA_POP_CW.name())) {
288 return new Ofdpa3PopCw();
289 } else {
290 throw new UnsupportedOperationException(NOT_SUPPORTED_MESSAGE + type.toString());
291 }
Charles Chancad338a2016-09-16 18:03:11 -0700292 }
293}