blob: bdc6d5e1a5ffc35615a2a1276997226adf707883 [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;
Yi Tseng0b809722017-11-03 10:23:26 -070022import org.onosproject.net.DeviceId;
23import org.onosproject.net.flow.DefaultFlowRule;
24import org.onosproject.net.flow.DefaultTrafficSelector;
25import org.onosproject.net.flow.DefaultTrafficTreatment;
26import org.onosproject.net.flow.FlowRule;
27import org.onosproject.net.flow.TrafficSelector;
28import org.onosproject.net.flow.TrafficTreatment;
29import org.onosproject.net.flow.criteria.Criterion;
30import org.onosproject.net.flow.criteria.EthCriterion;
Yi Tsengdbe05602017-11-17 18:02:43 -080031import org.onosproject.net.flow.criteria.IPCriterion;
Yi Tseng1b154bd2017-11-20 17:48:19 -080032import org.onosproject.net.flow.criteria.MplsCriterion;
Yi Tseng0b809722017-11-03 10:23:26 -070033import org.onosproject.net.flow.criteria.VlanIdCriterion;
34import org.onosproject.net.flowobjective.ForwardingObjective;
35import org.onosproject.net.flowobjective.ObjectiveError;
Yi Tseng47eac892018-07-11 02:17:04 +080036import org.onosproject.net.pi.model.PiActionId;
Yi Tseng0b809722017-11-03 10:23:26 -070037import 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())
Yi Tseng43ee7e82018-04-12 16:37:34 +080087 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_ACL)
Yi Tseng0b809722017-11-03 10:23:26 -070088 .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) {
Yi Tseng47eac892018-07-11 02:17:04 +0800181 treatment = buildSetNextIdTreatment(fwd.nextId(),
182 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800183 }
184
Yi Tseng0b809722017-11-03 10:23:26 -0700185 FlowRule flowRule = DefaultFlowRule.builder()
186 .withSelector(selector)
187 .withTreatment(treatment)
188 .fromApp(fwd.appId())
189 .withPriority(fwd.priority())
190 .makePermanent()
191 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800192 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)
Yi Tseng0b809722017-11-03 10:23:26 -0700193 .build();
194
195 resultBuilder.addFlowRule(flowRule);
196 }
197
198 private void processL2BroadcastRule(VlanIdCriterion vlanIdCriterion,
199 ForwardingObjective fwd,
200 PipelinerTranslationResult.Builder resultBuilder) {
201 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
Yi Tseng0b809722017-11-03 10:23:26 -0700202
203 VlanId vlanId = vlanIdCriterion.vlanId();
204
205 TrafficSelector selector = DefaultTrafficSelector.builder()
206 .matchVlanId(vlanId)
207 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800208 TrafficTreatment treatment = fwd.treatment();
209 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800210 treatment = buildSetNextIdTreatment(fwd.nextId(),
211 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800212 }
Yi Tseng0b809722017-11-03 10:23:26 -0700213 FlowRule flowRule = DefaultFlowRule.builder()
214 .withSelector(selector)
215 .withTreatment(treatment)
216 .fromApp(fwd.appId())
217 .withPriority(fwd.priority())
218 .makePermanent()
219 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800220 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)
Yi Tseng0b809722017-11-03 10:23:26 -0700221 .build();
222
223 resultBuilder.addFlowRule(flowRule);
224 }
225
Yi Tsengdbe05602017-11-17 18:02:43 -0800226 private void processIpv4UnicastRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
227 PipelinerTranslationResult.Builder resultBuilder) {
228 checkNotNull(ipDstCriterion, "IP dst criterion should not be null");
Yi Tsengdbe05602017-11-17 18:02:43 -0800229 TrafficSelector selector = DefaultTrafficSelector.builder()
230 .matchIPDst(ipDstCriterion.ip())
231 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800232 TrafficTreatment treatment = fwd.treatment();
233 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800234 treatment = buildSetNextIdTreatment(fwd.nextId(),
235 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_UNICAST_V4);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800236 }
Yi Tsengdbe05602017-11-17 18:02:43 -0800237 FlowRule flowRule = DefaultFlowRule.builder()
238 .withSelector(selector)
239 .withTreatment(treatment)
240 .fromApp(fwd.appId())
241 .withPriority(fwd.priority())
242 .makePermanent()
243 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800244 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_UNICAST_V4)
Yi Tsengdbe05602017-11-17 18:02:43 -0800245 .build();
246
247 resultBuilder.addFlowRule(flowRule);
248 }
249
Yi Tseng1b154bd2017-11-20 17:48:19 -0800250 private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
251 PipelinerTranslationResult.Builder resultBuilder) {
252 checkNotNull(mplsCriterion, "Mpls criterion should not be null");
Yi Tsengdf3eec52018-02-15 14:56:02 -0800253 TrafficTreatment treatment;
254
255 treatment = fwd.treatment();
256 if (fwd.nextId() != null) {
Charles Chanea89a1c2018-08-13 13:14:18 -0700257 PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, fwd.nextId());
Yi Tsengdf3eec52018-02-15 14:56:02 -0800258 PiAction nextIdAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800259 .withId(FabricConstants.FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT)
Yi Tsengdf3eec52018-02-15 14:56:02 -0800260 .withParameter(nextIdParam)
261 .build();
262 treatment = DefaultTrafficTreatment.builder()
263 .piTableAction(nextIdAction)
264 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800265 }
Yi Tsengdf3eec52018-02-15 14:56:02 -0800266
Yi Tseng1b154bd2017-11-20 17:48:19 -0800267 TrafficSelector selector = DefaultTrafficSelector.builder()
268 .add(mplsCriterion)
269 .build();
270
Yi Tseng1b154bd2017-11-20 17:48:19 -0800271 FlowRule flowRule = DefaultFlowRule.builder()
272 .withSelector(selector)
273 .withTreatment(treatment)
274 .fromApp(fwd.appId())
275 .withPriority(fwd.priority())
276 .makePermanent()
277 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800278 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_MPLS)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800279 .build();
280
281 resultBuilder.addFlowRule(flowRule);
282 }
283
Yi Tsengdf3eec52018-02-15 14:56:02 -0800284 /**
285 * Builds treatment with set_next_id action, returns empty treatment
286 * if next id is null.
287 *
288 * @param nextId the next id for action
289 * @return treatment with set_next_id action; empty treatment if next id is null
290 */
Yi Tseng47eac892018-07-11 02:17:04 +0800291 private static TrafficTreatment buildSetNextIdTreatment(Integer nextId, PiActionId actionId) {
Charles Chanea89a1c2018-08-13 13:14:18 -0700292 PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, nextId);
Yi Tseng0b809722017-11-03 10:23:26 -0700293 PiAction nextIdAction = PiAction.builder()
Yi Tseng47eac892018-07-11 02:17:04 +0800294 .withId(actionId)
Yi Tseng0b809722017-11-03 10:23:26 -0700295 .withParameter(nextIdParam)
296 .build();
297
298 return DefaultTrafficTreatment.builder()
299 .piTableAction(nextIdAction)
300 .build();
301 }
Yi Tseng0b809722017-11-03 10:23:26 -0700302}