blob: e72042fc7b68c6aeec50eec55b08f6c106ddc03e [file] [log] [blame]
Yi Tseng0b809722017-11-03 10:23:26 -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.pipeliner;
18
19import com.google.common.collect.ImmutableSet;
20import org.onlab.packet.MacAddress;
21import org.onlab.packet.VlanId;
22import org.onlab.util.ImmutableByteSequence;
23import org.onosproject.net.DeviceId;
24import org.onosproject.net.flow.DefaultFlowRule;
25import org.onosproject.net.flow.DefaultTrafficSelector;
26import org.onosproject.net.flow.DefaultTrafficTreatment;
27import org.onosproject.net.flow.FlowRule;
28import org.onosproject.net.flow.TrafficSelector;
29import org.onosproject.net.flow.TrafficTreatment;
30import org.onosproject.net.flow.criteria.Criterion;
31import org.onosproject.net.flow.criteria.EthCriterion;
Yi Tsengdbe05602017-11-17 18:02:43 -080032import org.onosproject.net.flow.criteria.IPCriterion;
Yi Tseng1b154bd2017-11-20 17:48:19 -080033import org.onosproject.net.flow.criteria.MplsCriterion;
Yi Tseng0b809722017-11-03 10:23:26 -070034import org.onosproject.net.flow.criteria.VlanIdCriterion;
35import org.onosproject.net.flowobjective.ForwardingObjective;
36import org.onosproject.net.flowobjective.ObjectiveError;
37import org.onosproject.net.pi.runtime.PiAction;
38import org.onosproject.net.pi.runtime.PiActionParam;
39import org.onosproject.pipelines.fabric.FabricConstants;
40import org.slf4j.Logger;
41
42import java.util.Set;
43
44import static com.google.common.base.Preconditions.checkNotNull;
45import static org.slf4j.LoggerFactory.getLogger;
46
47/**
48 * Handling forwarding objective for fabric pipeliner.
49 */
50public class FabricForwardingPipeliner {
51 private static final Logger log = getLogger(FabricForwardingPipeliner.class);
52
53 protected DeviceId deviceId;
54
55 public FabricForwardingPipeliner(DeviceId deviceId) {
56 this.deviceId = deviceId;
57 }
58
59 public PipelinerTranslationResult forward(ForwardingObjective forwardObjective) {
60 PipelinerTranslationResult.Builder resultBuilder = PipelinerTranslationResult.builder();
61 if (forwardObjective.flag() == ForwardingObjective.Flag.VERSATILE) {
62 processVersatileFwd(forwardObjective, resultBuilder);
63 } else {
64 processSpecificFwd(forwardObjective, resultBuilder);
65 }
66 return resultBuilder.build();
67 }
68
69 private void processVersatileFwd(ForwardingObjective fwd,
70 PipelinerTranslationResult.Builder resultBuilder) {
Yi Tsengc6844f52017-12-19 11:58:25 -080071 // TODO: Move IPv6 match to different ACL table
72
73 boolean unsupported = fwd.selector().criteria().stream()
74 .anyMatch(criterion -> criterion.type() == Criterion.Type.IPV6_DST);
75 unsupported |= fwd.selector().criteria().stream()
76 .anyMatch(criterion -> criterion.type() == Criterion.Type.IPV6_SRC);
77
78 if (unsupported) {
79 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
80 return;
81 }
82
Yi Tseng0b809722017-11-03 10:23:26 -070083 // program ACL table only
84 FlowRule flowRule = DefaultFlowRule.builder()
85 .withSelector(fwd.selector())
86 .withTreatment(fwd.treatment())
87 .forTable(FabricConstants.TBL_ACL_ID)
88 .withPriority(fwd.priority())
89 .forDevice(deviceId)
90 .makePermanent()
91 .fromApp(fwd.appId())
92 .build();
93 resultBuilder.addFlowRule(flowRule);
94 }
95
96 private void processSpecificFwd(ForwardingObjective fwd,
97 PipelinerTranslationResult.Builder resultBuilder) {
98 TrafficSelector selector = fwd.selector();
99 TrafficSelector meta = fwd.meta();
100
101 ImmutableSet.Builder<Criterion> criterionSetBuilder = ImmutableSet.builder();
102 criterionSetBuilder.addAll(selector.criteria());
103
104 if (meta != null) {
105 criterionSetBuilder.addAll(meta.criteria());
106 }
107
108 Set<Criterion> criteria = criterionSetBuilder.build();
109
110 VlanIdCriterion vlanIdCriterion = null;
111 EthCriterion ethDstCriterion = null;
Yi Tsengdbe05602017-11-17 18:02:43 -0800112 IPCriterion ipDstCriterion = null;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800113 MplsCriterion mplsCriterion = null;
Yi Tseng0b809722017-11-03 10:23:26 -0700114
115 for (Criterion criterion : criteria) {
116 switch (criterion.type()) {
117 case ETH_DST:
118 ethDstCriterion = (EthCriterion) criterion;
119 break;
120 case VLAN_VID:
121 vlanIdCriterion = (VlanIdCriterion) criterion;
122 break;
Yi Tsengdbe05602017-11-17 18:02:43 -0800123 case IPV4_DST:
124 ipDstCriterion = (IPCriterion) criterion;
125 break;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800126 case MPLS_LABEL:
127 mplsCriterion = (MplsCriterion) criterion;
128 break;
129 case ETH_TYPE:
130 case MPLS_BOS:
131 // do nothing
132 break;
Yi Tseng0b809722017-11-03 10:23:26 -0700133 default:
134 log.warn("Unsupported criterion {}", criterion);
135 break;
136 }
137 }
138
139 ForwardingFunctionType forwardingFunctionType =
140 ForwardingFunctionType.getForwardingFunctionType(fwd);
141 switch (forwardingFunctionType) {
142 case L2_UNICAST:
143 processL2UnicastRule(vlanIdCriterion, ethDstCriterion, fwd, resultBuilder);
144 break;
145 case L2_BROADCAST:
146 processL2BroadcastRule(vlanIdCriterion, fwd, resultBuilder);
147 break;
148 case IPV4_UNICAST:
Yi Tsengdbe05602017-11-17 18:02:43 -0800149 processIpv4UnicastRule(ipDstCriterion, fwd, resultBuilder);
150 break;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800151 case MPLS:
152 processMplsRule(mplsCriterion, fwd, resultBuilder);
153 break;
Yi Tseng0b809722017-11-03 10:23:26 -0700154 case IPV4_MULTICAST:
155 case IPV6_UNICAST:
156 case IPV6_MULTICAST:
Yi Tseng0b809722017-11-03 10:23:26 -0700157 default:
158 log.warn("Unsupported forwarding function type {}", criteria);
159 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
160 break;
161 }
162 }
163
164 // L2 Unicast: learnt mac address + vlan
165 private void processL2UnicastRule(VlanIdCriterion vlanIdCriterion,
166 EthCriterion ethDstCriterion,
167 ForwardingObjective fwd,
168 PipelinerTranslationResult.Builder resultBuilder) {
169 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
170 checkNotNull(ethDstCriterion, "EthDst criterion should not be null");
171
172 if (fwd.nextId() == null) {
173 log.warn("Forwarding objective for L2 unicast should contains next id");
174 resultBuilder.setError(ObjectiveError.BADPARAMS);
175 return;
176 }
177
178 VlanId vlanId = vlanIdCriterion.vlanId();
179 MacAddress ethDst = ethDstCriterion.mac();
180
181 TrafficSelector selector = DefaultTrafficSelector.builder()
182 .matchVlanId(vlanId)
183 .matchEthDst(ethDst)
184 .build();
185 TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
186 FlowRule flowRule = DefaultFlowRule.builder()
187 .withSelector(selector)
188 .withTreatment(treatment)
189 .fromApp(fwd.appId())
190 .withPriority(fwd.priority())
191 .makePermanent()
192 .forDevice(deviceId)
193 .forTable(FabricConstants.TBL_BRIDGING_ID)
194 .build();
195
196 resultBuilder.addFlowRule(flowRule);
197 }
198
199 private void processL2BroadcastRule(VlanIdCriterion vlanIdCriterion,
200 ForwardingObjective fwd,
201 PipelinerTranslationResult.Builder resultBuilder) {
202 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
203 if (fwd.nextId() == null) {
204 log.warn("Forwarding objective for L2 broadcast should contains next id");
205 resultBuilder.setError(ObjectiveError.BADPARAMS);
206 return;
207 }
208
209 VlanId vlanId = vlanIdCriterion.vlanId();
210
211 TrafficSelector selector = DefaultTrafficSelector.builder()
212 .matchVlanId(vlanId)
213 .build();
214 TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
215 FlowRule flowRule = DefaultFlowRule.builder()
216 .withSelector(selector)
217 .withTreatment(treatment)
218 .fromApp(fwd.appId())
219 .withPriority(fwd.priority())
220 .makePermanent()
221 .forDevice(deviceId)
222 .forTable(FabricConstants.TBL_BRIDGING_ID)
223 .build();
224
225 resultBuilder.addFlowRule(flowRule);
226 }
227
Yi Tsengdbe05602017-11-17 18:02:43 -0800228 private void processIpv4UnicastRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
229 PipelinerTranslationResult.Builder resultBuilder) {
230 checkNotNull(ipDstCriterion, "IP dst criterion should not be null");
231 if (fwd.nextId() == null) {
232 log.warn("Forwarding objective for IPv4 unicast should contains next id");
233 resultBuilder.setError(ObjectiveError.BADPARAMS);
234 return;
235 }
236 TrafficSelector selector = DefaultTrafficSelector.builder()
237 .matchIPDst(ipDstCriterion.ip())
238 .build();
239
240 TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
241 FlowRule flowRule = DefaultFlowRule.builder()
242 .withSelector(selector)
243 .withTreatment(treatment)
244 .fromApp(fwd.appId())
245 .withPriority(fwd.priority())
246 .makePermanent()
247 .forDevice(deviceId)
248 .forTable(FabricConstants.TBL_UNICAST_V4_ID)
249 .build();
250
251 resultBuilder.addFlowRule(flowRule);
252 }
253
Yi Tseng1b154bd2017-11-20 17:48:19 -0800254 private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
255 PipelinerTranslationResult.Builder resultBuilder) {
256 checkNotNull(mplsCriterion, "Mpls criterion should not be null");
257 if (fwd.nextId() == null) {
258 log.warn("Forwarding objective for MPLS should contains next id");
259 resultBuilder.setError(ObjectiveError.BADPARAMS);
260 return;
261 }
262 TrafficSelector selector = DefaultTrafficSelector.builder()
263 .add(mplsCriterion)
264 .build();
265
266 PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
267 ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
268 PiAction nextIdAction = PiAction.builder()
Yi Tsengc6844f52017-12-19 11:58:25 -0800269 .withId(FabricConstants.ACT_FORWARDING_POP_MPLS_AND_NEXT_ID)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800270 .withParameter(nextIdParam)
271 .build();
272 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
273 .piTableAction(nextIdAction)
274 .build();
275
276 FlowRule flowRule = DefaultFlowRule.builder()
277 .withSelector(selector)
278 .withTreatment(treatment)
279 .fromApp(fwd.appId())
280 .withPriority(fwd.priority())
281 .makePermanent()
282 .forDevice(deviceId)
283 .forTable(FabricConstants.TBL_MPLS_ID)
284 .build();
285
286 resultBuilder.addFlowRule(flowRule);
287 }
288
Yi Tseng0b809722017-11-03 10:23:26 -0700289 private static TrafficTreatment buildSetNextIdTreatment(Integer nextId) {
290 PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
291 ImmutableByteSequence.copyFrom(nextId.byteValue()));
292 PiAction nextIdAction = PiAction.builder()
Yi Tsengc6844f52017-12-19 11:58:25 -0800293 .withId(FabricConstants.ACT_FORWARDING_SET_NEXT_ID_ID)
Yi Tseng0b809722017-11-03 10:23:26 -0700294 .withParameter(nextIdParam)
295 .build();
296
297 return DefaultTrafficTreatment.builder()
298 .piTableAction(nextIdAction)
299 .build();
300 }
Yi Tseng0b809722017-11-03 10:23:26 -0700301}