blob: 234e541de1013006d51525f64ba610353280acc3 [file] [log] [blame]
Yi Tsengfa4a1c72017-11-03 10:22:38 -07001/*
2 * Copyright 2017-present Open Networking Foundation
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
17package org.onosproject.pipelines.fabric;
18
19import com.google.common.collect.ImmutableList;
20import org.onlab.packet.MacAddress;
Yi Tseng1b154bd2017-11-20 17:48:19 -080021import org.onlab.packet.MplsLabel;
Yi Tsengfa4a1c72017-11-03 10:22:38 -070022import org.onlab.packet.VlanId;
23import org.onlab.util.ImmutableByteSequence;
24import org.onosproject.net.PortNumber;
25import org.onosproject.net.flow.TrafficTreatment;
26import org.onosproject.net.flow.instructions.Instruction;
27import org.onosproject.net.flow.instructions.Instructions;
28import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
29import org.onosproject.net.flow.instructions.L2ModificationInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
Yi Tseng1b154bd2017-11-20 17:48:19 -080031import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
Yi Tsengfa4a1c72017-11-03 10:22:38 -070032import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
33import org.onosproject.net.pi.model.PiActionId;
34import org.onosproject.net.pi.model.PiPipelineInterpreter.PiInterpreterException;
35import org.onosproject.net.pi.runtime.PiAction;
36import org.onosproject.net.pi.runtime.PiActionParam;
Yi Tseng1b154bd2017-11-20 17:48:19 -080037import org.slf4j.Logger;
Yi Tsengfa4a1c72017-11-03 10:22:38 -070038
39import java.util.List;
40
41import static java.lang.String.format;
42import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
43import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
Yi Tsengfa4a1c72017-11-03 10:22:38 -070044import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
45import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
Yi Tseng1b154bd2017-11-20 17:48:19 -080046import static org.slf4j.LoggerFactory.getLogger;
Yi Tsengfa4a1c72017-11-03 10:22:38 -070047
48
49final class FabricTreatmentInterpreter {
Yi Tseng1b154bd2017-11-20 17:48:19 -080050 private static final Logger log = getLogger(FabricTreatmentInterpreter.class);
Yi Tsengfa4a1c72017-11-03 10:22:38 -070051 private static final String INVALID_TREATMENT = "Invalid treatment for %s block: %s";
52
53 // Hide default constructor
54 protected FabricTreatmentInterpreter() {
55 }
56
57 /*
58 * In Filtering block, we need to implement these actions:
59 *
60 * push_internal_vlan
61 * set_vlan
62 * nop
63 *
64 * Unsupported, using PiAction directly:
65 * set_forwarding_type
66 */
67
68 static PiAction mapFilteringTreatment(TrafficTreatment treatment)
69 throws PiInterpreterException {
70 List<Instruction> instructions = treatment.allInstructions();
71 Instruction noActInst = Instructions.createNoAction();
72 if (instructions.isEmpty() || instructions.contains(noActInst)) {
73 // nop
74 return PiAction.builder()
75 .withId(FabricConstants.ACT_NOP_ID)
76 .build();
77 }
78
79 L2ModificationInstruction.ModVlanHeaderInstruction pushVlanInst = null;
80 ModVlanIdInstruction setVlanInst = null;
81
82 for (Instruction inst : instructions) {
83 if (inst.type() == L2MODIFICATION) {
84 L2ModificationInstruction l2Inst = (L2ModificationInstruction) inst;
85
86 if (l2Inst.subtype() == VLAN_PUSH) {
87 pushVlanInst = (L2ModificationInstruction.ModVlanHeaderInstruction) l2Inst;
88
89 } else if (l2Inst.subtype() == VLAN_ID) {
90 setVlanInst = (ModVlanIdInstruction) l2Inst;
91 }
92 }
93 }
94
95 if (setVlanInst == null) {
96 throw new PiInterpreterException(format(INVALID_TREATMENT, "filtering", treatment));
97 }
98
99 VlanId vlanId = setVlanInst.vlanId();
100 PiActionParam param = new PiActionParam(FabricConstants.ACT_PRM_NEW_VLAN_ID_ID,
101 ImmutableByteSequence.copyFrom(vlanId.toShort()));
102 PiActionId actionId;
103 if (pushVlanInst != null) {
104 // push_internal_vlan
105 actionId = FabricConstants.ACT_PUSH_INTERNAL_VLAN_ID;
106 } else {
107 actionId = FabricConstants.ACT_SET_VLAN_ID;
108 }
109
110 // set_vlan
111 return PiAction.builder()
112 .withId(actionId)
113 .withParameter(param)
114 .build();
115 }
116
117 /*
118 * In forwarding block, we need to implement these actions:
119 * duplicate_to_controller
120 *
121 * Unsupported, using PiAction directly:
122 * set_next_id
123 * push_mpls_and_next_v4
124 * push_mpls_and_next_v6
125 */
126
127 public static PiAction mapForwardingTreatment(TrafficTreatment treatment)
128 throws PiInterpreterException {
129 List<Instruction> insts = treatment.allInstructions();
130 OutputInstruction outInst = insts.stream()
131 .filter(inst -> inst.type() == OUTPUT)
132 .map(inst -> (OutputInstruction) inst)
133 .findFirst()
134 .orElse(null);
135
136 if (outInst == null) {
137 throw new PiInterpreterException(format(INVALID_TREATMENT, "forwarding", treatment));
138 }
139
140 PortNumber portNumber = outInst.port();
141 if (!portNumber.equals(PortNumber.CONTROLLER)) {
142 throw new PiInterpreterException(format("Unsupported port number %s," +
143 "supports punt action only",
144 portNumber));
145 }
146
147 return PiAction.builder()
148 .withId(FabricConstants.ACT_DUPLICATE_TO_CONTROLLER_ID)
149 .build();
150 }
151
152 /*
153 * In Next block, we need to implement these actions:
154 * output
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700155 * set_vlan_output
Yi Tseng1b154bd2017-11-20 17:48:19 -0800156 * l3_routing
157 * mpls_routing_v4
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700158 *
159 * Unsupported, using PiAction directly:
Yi Tseng1b154bd2017-11-20 17:48:19 -0800160 * set_next_type
161 *
162 * Unsupported, need to find a way to implement it
163 * mpls_routing_v6
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700164 */
165
166 public static PiAction mapNextTreatment(TrafficTreatment treatment)
167 throws PiInterpreterException {
168 List<Instruction> insts = treatment.allInstructions();
169 OutputInstruction outInst = null;
170 ModEtherInstruction modEthDstInst = null;
171 ModEtherInstruction modEthSrcInst = null;
172 ModVlanIdInstruction modVlanIdInst = null;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800173 ModMplsLabelInstruction modMplsInst = null;
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700174
Yi Tseng1b154bd2017-11-20 17:48:19 -0800175 // TODO: add NextFunctionType (like ForwardingFunctionType)
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700176 for (Instruction inst : insts) {
177 switch (inst.type()) {
178 case L2MODIFICATION:
179 L2ModificationInstruction l2Inst = (L2ModificationInstruction) inst;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800180 switch (l2Inst.subtype()) {
181 case ETH_SRC:
182 modEthSrcInst = (ModEtherInstruction) l2Inst;
183 break;
184 case ETH_DST:
185 modEthDstInst = (ModEtherInstruction) l2Inst;
186 break;
187 case VLAN_ID:
188 modVlanIdInst = (ModVlanIdInstruction) l2Inst;
189 break;
190 case MPLS_LABEL:
191 modMplsInst = (ModMplsLabelInstruction) l2Inst;
192 break;
193 default:
194 log.warn("Unsupported l2 instruction sub type: {}", l2Inst.subtype());
195 break;
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700196 }
197 break;
198 case OUTPUT:
199 outInst = (OutputInstruction) inst;
200 break;
201 default:
Yi Tseng1b154bd2017-11-20 17:48:19 -0800202 log.warn("Unsupported instruction sub type: {}", inst.type());
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700203 break;
204 }
205 }
206
207 if (outInst == null) {
208 throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
209 }
210 short portNum = (short) outInst.port().toLong();
211 PiActionParam portNumParam = new PiActionParam(FabricConstants.ACT_PRM_PORT_NUM_ID,
212 ImmutableByteSequence.copyFrom(portNum));
213 if (modEthDstInst == null && modEthSrcInst == null) {
214 if (modVlanIdInst != null) {
215 VlanId vlanId = modVlanIdInst.vlanId();
216 PiActionParam vlanParam =
217 new PiActionParam(FabricConstants.ACT_PRM_NEW_VLAN_ID_ID,
218 ImmutableByteSequence.copyFrom(vlanId.toShort()));
219 // set_vlan_output
220 return PiAction.builder()
221 .withId(FabricConstants.ACT_SET_VLAN_OUTPUT_ID)
222 .withParameters(ImmutableList.of(portNumParam, vlanParam))
223 .build();
224 } else {
225 // output
226 return PiAction.builder()
227 .withId(FabricConstants.ACT_OUTPUT_ID)
228 .withParameter(portNumParam)
229 .build();
230 }
231 }
232
233 if (modEthDstInst != null && modEthSrcInst != null) {
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700234 MacAddress srcMac = modEthSrcInst.mac();
235 MacAddress dstMac = modEthDstInst.mac();
236 PiActionParam srcMacParam = new PiActionParam(FabricConstants.ACT_PRM_SMAC_ID,
237 ImmutableByteSequence.copyFrom(srcMac.toBytes()));
238 PiActionParam dstMacParam = new PiActionParam(FabricConstants.ACT_PRM_DMAC_ID,
239 ImmutableByteSequence.copyFrom(dstMac.toBytes()));
Yi Tseng1b154bd2017-11-20 17:48:19 -0800240
241 if (modMplsInst != null) {
242 // MPLS routing
243 MplsLabel mplsLabel = modMplsInst.label();
244 try {
245 ImmutableByteSequence mplsValue =
246 ImmutableByteSequence.fit(ImmutableByteSequence.copyFrom(mplsLabel.toInt()), 20);
247 PiActionParam mplsParam = new PiActionParam(FabricConstants.ACT_PRM_LABEL_ID, mplsValue);
248 return PiAction.builder()
249 // FIXME: fins a way to determine v4 or v6
250 .withId(FabricConstants.ACT_MPLS_ROUTING_V4_ID)
251 .withParameters(ImmutableList.of(portNumParam,
252 srcMacParam,
253 dstMacParam,
254 mplsParam))
255 .build();
256 } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
257 // Basically this won't happened because we already limited
258 // size of mpls value to 20 bits (0xFFFFF)
259 throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
260 }
261 }
262
263 // L3 routing
Yi Tsengfa4a1c72017-11-03 10:22:38 -0700264 return PiAction.builder()
265 .withId(FabricConstants.ACT_L3_ROUTING_ID)
266 .withParameters(ImmutableList.of(portNumParam,
267 srcMacParam,
268 dstMacParam))
269 .build();
270 }
271
272 throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
273 }
274}