blob: a2e4974e8f85b678beb52db3b66c641040993c3b [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;
21import org.onlab.packet.VlanId;
22import org.onlab.util.ImmutableByteSequence;
23import org.onosproject.net.PortNumber;
24import org.onosproject.net.flow.TrafficTreatment;
25import org.onosproject.net.flow.instructions.Instruction;
26import org.onosproject.net.flow.instructions.Instructions;
27import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
28import org.onosproject.net.flow.instructions.L2ModificationInstruction;
29import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
31import org.onosproject.net.pi.model.PiActionId;
32import org.onosproject.net.pi.model.PiPipelineInterpreter.PiInterpreterException;
33import org.onosproject.net.pi.runtime.PiAction;
34import org.onosproject.net.pi.runtime.PiActionParam;
35
36import java.util.List;
37
38import static java.lang.String.format;
39import static org.onosproject.net.flow.instructions.Instruction.Type.L2MODIFICATION;
40import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
41import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_DST;
42import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.ETH_SRC;
43import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_ID;
44import static org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType.VLAN_PUSH;
45
46
47final class FabricTreatmentInterpreter {
48 private static final String INVALID_TREATMENT = "Invalid treatment for %s block: %s";
49
50 // Hide default constructor
51 protected FabricTreatmentInterpreter() {
52 }
53
54 /*
55 * In Filtering block, we need to implement these actions:
56 *
57 * push_internal_vlan
58 * set_vlan
59 * nop
60 *
61 * Unsupported, using PiAction directly:
62 * set_forwarding_type
63 */
64
65 static PiAction mapFilteringTreatment(TrafficTreatment treatment)
66 throws PiInterpreterException {
67 List<Instruction> instructions = treatment.allInstructions();
68 Instruction noActInst = Instructions.createNoAction();
69 if (instructions.isEmpty() || instructions.contains(noActInst)) {
70 // nop
71 return PiAction.builder()
72 .withId(FabricConstants.ACT_NOP_ID)
73 .build();
74 }
75
76 L2ModificationInstruction.ModVlanHeaderInstruction pushVlanInst = null;
77 ModVlanIdInstruction setVlanInst = null;
78
79 for (Instruction inst : instructions) {
80 if (inst.type() == L2MODIFICATION) {
81 L2ModificationInstruction l2Inst = (L2ModificationInstruction) inst;
82
83 if (l2Inst.subtype() == VLAN_PUSH) {
84 pushVlanInst = (L2ModificationInstruction.ModVlanHeaderInstruction) l2Inst;
85
86 } else if (l2Inst.subtype() == VLAN_ID) {
87 setVlanInst = (ModVlanIdInstruction) l2Inst;
88 }
89 }
90 }
91
92 if (setVlanInst == null) {
93 throw new PiInterpreterException(format(INVALID_TREATMENT, "filtering", treatment));
94 }
95
96 VlanId vlanId = setVlanInst.vlanId();
97 PiActionParam param = new PiActionParam(FabricConstants.ACT_PRM_NEW_VLAN_ID_ID,
98 ImmutableByteSequence.copyFrom(vlanId.toShort()));
99 PiActionId actionId;
100 if (pushVlanInst != null) {
101 // push_internal_vlan
102 actionId = FabricConstants.ACT_PUSH_INTERNAL_VLAN_ID;
103 } else {
104 actionId = FabricConstants.ACT_SET_VLAN_ID;
105 }
106
107 // set_vlan
108 return PiAction.builder()
109 .withId(actionId)
110 .withParameter(param)
111 .build();
112 }
113
114 /*
115 * In forwarding block, we need to implement these actions:
116 * duplicate_to_controller
117 *
118 * Unsupported, using PiAction directly:
119 * set_next_id
120 * push_mpls_and_next_v4
121 * push_mpls_and_next_v6
122 */
123
124 public static PiAction mapForwardingTreatment(TrafficTreatment treatment)
125 throws PiInterpreterException {
126 List<Instruction> insts = treatment.allInstructions();
127 OutputInstruction outInst = insts.stream()
128 .filter(inst -> inst.type() == OUTPUT)
129 .map(inst -> (OutputInstruction) inst)
130 .findFirst()
131 .orElse(null);
132
133 if (outInst == null) {
134 throw new PiInterpreterException(format(INVALID_TREATMENT, "forwarding", treatment));
135 }
136
137 PortNumber portNumber = outInst.port();
138 if (!portNumber.equals(PortNumber.CONTROLLER)) {
139 throw new PiInterpreterException(format("Unsupported port number %s," +
140 "supports punt action only",
141 portNumber));
142 }
143
144 return PiAction.builder()
145 .withId(FabricConstants.ACT_DUPLICATE_TO_CONTROLLER_ID)
146 .build();
147 }
148
149 /*
150 * In Next block, we need to implement these actions:
151 * output
152 * output_ecmp
153 * set_vlan_output
154 *
155 * Unsupported, using PiAction directly:
156 * set_mcast_group
157 */
158
159 public static PiAction mapNextTreatment(TrafficTreatment treatment)
160 throws PiInterpreterException {
161 List<Instruction> insts = treatment.allInstructions();
162 OutputInstruction outInst = null;
163 ModEtherInstruction modEthDstInst = null;
164 ModEtherInstruction modEthSrcInst = null;
165 ModVlanIdInstruction modVlanIdInst = null;
166
167 // TODO: use matrix to store the combination of instruction
168 for (Instruction inst : insts) {
169 switch (inst.type()) {
170 case L2MODIFICATION:
171 L2ModificationInstruction l2Inst = (L2ModificationInstruction) inst;
172
173 if (l2Inst.subtype() == ETH_SRC) {
174 modEthSrcInst = (ModEtherInstruction) l2Inst;
175 }
176
177 if (l2Inst.subtype() == ETH_DST) {
178 modEthDstInst = (ModEtherInstruction) l2Inst;
179 }
180
181 if (l2Inst.subtype() == VLAN_ID) {
182 modVlanIdInst = (ModVlanIdInstruction) l2Inst;
183 }
184 break;
185 case OUTPUT:
186 outInst = (OutputInstruction) inst;
187 break;
188 default:
189 break;
190 }
191 }
192
193 if (outInst == null) {
194 throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
195 }
196 short portNum = (short) outInst.port().toLong();
197 PiActionParam portNumParam = new PiActionParam(FabricConstants.ACT_PRM_PORT_NUM_ID,
198 ImmutableByteSequence.copyFrom(portNum));
199 if (modEthDstInst == null && modEthSrcInst == null) {
200 if (modVlanIdInst != null) {
201 VlanId vlanId = modVlanIdInst.vlanId();
202 PiActionParam vlanParam =
203 new PiActionParam(FabricConstants.ACT_PRM_NEW_VLAN_ID_ID,
204 ImmutableByteSequence.copyFrom(vlanId.toShort()));
205 // set_vlan_output
206 return PiAction.builder()
207 .withId(FabricConstants.ACT_SET_VLAN_OUTPUT_ID)
208 .withParameters(ImmutableList.of(portNumParam, vlanParam))
209 .build();
210 } else {
211 // output
212 return PiAction.builder()
213 .withId(FabricConstants.ACT_OUTPUT_ID)
214 .withParameter(portNumParam)
215 .build();
216 }
217 }
218
219 if (modEthDstInst != null && modEthSrcInst != null) {
220 // output and rewrite src/dst mac
221 MacAddress srcMac = modEthSrcInst.mac();
222 MacAddress dstMac = modEthDstInst.mac();
223 PiActionParam srcMacParam = new PiActionParam(FabricConstants.ACT_PRM_SMAC_ID,
224 ImmutableByteSequence.copyFrom(srcMac.toBytes()));
225 PiActionParam dstMacParam = new PiActionParam(FabricConstants.ACT_PRM_DMAC_ID,
226 ImmutableByteSequence.copyFrom(dstMac.toBytes()));
227 return PiAction.builder()
228 .withId(FabricConstants.ACT_L3_ROUTING_ID)
229 .withParameters(ImmutableList.of(portNumParam,
230 srcMacParam,
231 dstMacParam))
232 .build();
233 }
234
235 throw new PiInterpreterException(format(INVALID_TREATMENT, "next", treatment));
236 }
237}