blob: 5424a492399f77d99049da20231306cd626efdde [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
Yi Tseng0b809722017-11-03 10:23:26 -0700172 VlanId vlanId = vlanIdCriterion.vlanId();
173 MacAddress ethDst = ethDstCriterion.mac();
174
175 TrafficSelector selector = DefaultTrafficSelector.builder()
176 .matchVlanId(vlanId)
177 .matchEthDst(ethDst)
178 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800179 TrafficTreatment treatment = fwd.treatment();
180 if (fwd.nextId() != null) {
181 treatment = buildSetNextIdTreatment(fwd.nextId());
182 }
183
Yi Tseng0b809722017-11-03 10:23:26 -0700184 FlowRule flowRule = DefaultFlowRule.builder()
185 .withSelector(selector)
186 .withTreatment(treatment)
187 .fromApp(fwd.appId())
188 .withPriority(fwd.priority())
189 .makePermanent()
190 .forDevice(deviceId)
191 .forTable(FabricConstants.TBL_BRIDGING_ID)
192 .build();
193
194 resultBuilder.addFlowRule(flowRule);
195 }
196
197 private void processL2BroadcastRule(VlanIdCriterion vlanIdCriterion,
198 ForwardingObjective fwd,
199 PipelinerTranslationResult.Builder resultBuilder) {
200 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
Yi Tseng0b809722017-11-03 10:23:26 -0700201
202 VlanId vlanId = vlanIdCriterion.vlanId();
203
204 TrafficSelector selector = DefaultTrafficSelector.builder()
205 .matchVlanId(vlanId)
206 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800207 TrafficTreatment treatment = fwd.treatment();
208 if (fwd.nextId() != null) {
209 treatment = buildSetNextIdTreatment(fwd.nextId());
210 }
Yi Tseng0b809722017-11-03 10:23:26 -0700211 FlowRule flowRule = DefaultFlowRule.builder()
212 .withSelector(selector)
213 .withTreatment(treatment)
214 .fromApp(fwd.appId())
215 .withPriority(fwd.priority())
216 .makePermanent()
217 .forDevice(deviceId)
218 .forTable(FabricConstants.TBL_BRIDGING_ID)
219 .build();
220
221 resultBuilder.addFlowRule(flowRule);
222 }
223
Yi Tsengdbe05602017-11-17 18:02:43 -0800224 private void processIpv4UnicastRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
225 PipelinerTranslationResult.Builder resultBuilder) {
226 checkNotNull(ipDstCriterion, "IP dst criterion should not be null");
Yi Tsengdbe05602017-11-17 18:02:43 -0800227 TrafficSelector selector = DefaultTrafficSelector.builder()
228 .matchIPDst(ipDstCriterion.ip())
229 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800230 TrafficTreatment treatment = fwd.treatment();
231 if (fwd.nextId() != null) {
232 treatment = buildSetNextIdTreatment(fwd.nextId());
233 }
Yi Tsengdbe05602017-11-17 18:02:43 -0800234 FlowRule flowRule = DefaultFlowRule.builder()
235 .withSelector(selector)
236 .withTreatment(treatment)
237 .fromApp(fwd.appId())
238 .withPriority(fwd.priority())
239 .makePermanent()
240 .forDevice(deviceId)
241 .forTable(FabricConstants.TBL_UNICAST_V4_ID)
242 .build();
243
244 resultBuilder.addFlowRule(flowRule);
245 }
246
Yi Tseng1b154bd2017-11-20 17:48:19 -0800247 private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
248 PipelinerTranslationResult.Builder resultBuilder) {
249 checkNotNull(mplsCriterion, "Mpls criterion should not be null");
Yi Tsengdf3eec52018-02-15 14:56:02 -0800250 TrafficTreatment treatment;
251
252 treatment = fwd.treatment();
253 if (fwd.nextId() != null) {
254 PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
255 ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
256 PiAction nextIdAction = PiAction.builder()
257 .withId(FabricConstants.ACT_FORWARDING_POP_MPLS_AND_NEXT_ID)
258 .withParameter(nextIdParam)
259 .build();
260 treatment = DefaultTrafficTreatment.builder()
261 .piTableAction(nextIdAction)
262 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800263 }
Yi Tsengdf3eec52018-02-15 14:56:02 -0800264
Yi Tseng1b154bd2017-11-20 17:48:19 -0800265 TrafficSelector selector = DefaultTrafficSelector.builder()
266 .add(mplsCriterion)
267 .build();
268
Yi Tseng1b154bd2017-11-20 17:48:19 -0800269 FlowRule flowRule = DefaultFlowRule.builder()
270 .withSelector(selector)
271 .withTreatment(treatment)
272 .fromApp(fwd.appId())
273 .withPriority(fwd.priority())
274 .makePermanent()
275 .forDevice(deviceId)
276 .forTable(FabricConstants.TBL_MPLS_ID)
277 .build();
278
279 resultBuilder.addFlowRule(flowRule);
280 }
281
Yi Tsengdf3eec52018-02-15 14:56:02 -0800282 /**
283 * Builds treatment with set_next_id action, returns empty treatment
284 * if next id is null.
285 *
286 * @param nextId the next id for action
287 * @return treatment with set_next_id action; empty treatment if next id is null
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}