blob: c4ecdfdb0ad129250fac8b6a85e7313d49c7afdc [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;
Yi Tseng47eac892018-07-11 02:17:04 +080037import org.onosproject.net.pi.model.PiActionId;
Yi Tseng0b809722017-11-03 10:23:26 -070038import org.onosproject.net.pi.runtime.PiAction;
39import org.onosproject.net.pi.runtime.PiActionParam;
40import org.onosproject.pipelines.fabric.FabricConstants;
41import org.slf4j.Logger;
42
43import java.util.Set;
44
45import static com.google.common.base.Preconditions.checkNotNull;
46import static org.slf4j.LoggerFactory.getLogger;
47
48/**
49 * Handling forwarding objective for fabric pipeliner.
50 */
51public class FabricForwardingPipeliner {
52 private static final Logger log = getLogger(FabricForwardingPipeliner.class);
53
54 protected DeviceId deviceId;
55
56 public FabricForwardingPipeliner(DeviceId deviceId) {
57 this.deviceId = deviceId;
58 }
59
60 public PipelinerTranslationResult forward(ForwardingObjective forwardObjective) {
61 PipelinerTranslationResult.Builder resultBuilder = PipelinerTranslationResult.builder();
62 if (forwardObjective.flag() == ForwardingObjective.Flag.VERSATILE) {
63 processVersatileFwd(forwardObjective, resultBuilder);
64 } else {
65 processSpecificFwd(forwardObjective, resultBuilder);
66 }
67 return resultBuilder.build();
68 }
69
70 private void processVersatileFwd(ForwardingObjective fwd,
71 PipelinerTranslationResult.Builder resultBuilder) {
Yi Tsengc6844f52017-12-19 11:58:25 -080072 // TODO: Move IPv6 match to different ACL table
73
74 boolean unsupported = fwd.selector().criteria().stream()
75 .anyMatch(criterion -> criterion.type() == Criterion.Type.IPV6_DST);
76 unsupported |= fwd.selector().criteria().stream()
77 .anyMatch(criterion -> criterion.type() == Criterion.Type.IPV6_SRC);
78
79 if (unsupported) {
80 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
81 return;
82 }
83
Yi Tseng0b809722017-11-03 10:23:26 -070084 // program ACL table only
85 FlowRule flowRule = DefaultFlowRule.builder()
86 .withSelector(fwd.selector())
87 .withTreatment(fwd.treatment())
Yi Tseng43ee7e82018-04-12 16:37:34 +080088 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_ACL)
Yi Tseng0b809722017-11-03 10:23:26 -070089 .withPriority(fwd.priority())
90 .forDevice(deviceId)
91 .makePermanent()
92 .fromApp(fwd.appId())
93 .build();
94 resultBuilder.addFlowRule(flowRule);
95 }
96
97 private void processSpecificFwd(ForwardingObjective fwd,
98 PipelinerTranslationResult.Builder resultBuilder) {
99 TrafficSelector selector = fwd.selector();
100 TrafficSelector meta = fwd.meta();
101
102 ImmutableSet.Builder<Criterion> criterionSetBuilder = ImmutableSet.builder();
103 criterionSetBuilder.addAll(selector.criteria());
104
105 if (meta != null) {
106 criterionSetBuilder.addAll(meta.criteria());
107 }
108
109 Set<Criterion> criteria = criterionSetBuilder.build();
110
111 VlanIdCriterion vlanIdCriterion = null;
112 EthCriterion ethDstCriterion = null;
Yi Tsengdbe05602017-11-17 18:02:43 -0800113 IPCriterion ipDstCriterion = null;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800114 MplsCriterion mplsCriterion = null;
Yi Tseng0b809722017-11-03 10:23:26 -0700115
116 for (Criterion criterion : criteria) {
117 switch (criterion.type()) {
118 case ETH_DST:
119 ethDstCriterion = (EthCriterion) criterion;
120 break;
121 case VLAN_VID:
122 vlanIdCriterion = (VlanIdCriterion) criterion;
123 break;
Yi Tsengdbe05602017-11-17 18:02:43 -0800124 case IPV4_DST:
125 ipDstCriterion = (IPCriterion) criterion;
126 break;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800127 case MPLS_LABEL:
128 mplsCriterion = (MplsCriterion) criterion;
129 break;
130 case ETH_TYPE:
131 case MPLS_BOS:
132 // do nothing
133 break;
Yi Tseng0b809722017-11-03 10:23:26 -0700134 default:
135 log.warn("Unsupported criterion {}", criterion);
136 break;
137 }
138 }
139
140 ForwardingFunctionType forwardingFunctionType =
141 ForwardingFunctionType.getForwardingFunctionType(fwd);
142 switch (forwardingFunctionType) {
143 case L2_UNICAST:
144 processL2UnicastRule(vlanIdCriterion, ethDstCriterion, fwd, resultBuilder);
145 break;
146 case L2_BROADCAST:
147 processL2BroadcastRule(vlanIdCriterion, fwd, resultBuilder);
148 break;
149 case IPV4_UNICAST:
Yi Tsengdbe05602017-11-17 18:02:43 -0800150 processIpv4UnicastRule(ipDstCriterion, fwd, resultBuilder);
151 break;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800152 case MPLS:
153 processMplsRule(mplsCriterion, fwd, resultBuilder);
154 break;
Yi Tseng0b809722017-11-03 10:23:26 -0700155 case IPV4_MULTICAST:
156 case IPV6_UNICAST:
157 case IPV6_MULTICAST:
Yi Tseng0b809722017-11-03 10:23:26 -0700158 default:
159 log.warn("Unsupported forwarding function type {}", criteria);
160 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
161 break;
162 }
163 }
164
165 // L2 Unicast: learnt mac address + vlan
166 private void processL2UnicastRule(VlanIdCriterion vlanIdCriterion,
167 EthCriterion ethDstCriterion,
168 ForwardingObjective fwd,
169 PipelinerTranslationResult.Builder resultBuilder) {
170 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
171 checkNotNull(ethDstCriterion, "EthDst criterion should not be null");
172
Yi Tseng0b809722017-11-03 10:23:26 -0700173 VlanId vlanId = vlanIdCriterion.vlanId();
174 MacAddress ethDst = ethDstCriterion.mac();
175
176 TrafficSelector selector = DefaultTrafficSelector.builder()
177 .matchVlanId(vlanId)
178 .matchEthDst(ethDst)
179 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800180 TrafficTreatment treatment = fwd.treatment();
181 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800182 treatment = buildSetNextIdTreatment(fwd.nextId(),
183 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800184 }
185
Yi Tseng0b809722017-11-03 10:23:26 -0700186 FlowRule flowRule = DefaultFlowRule.builder()
187 .withSelector(selector)
188 .withTreatment(treatment)
189 .fromApp(fwd.appId())
190 .withPriority(fwd.priority())
191 .makePermanent()
192 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800193 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)
Yi Tseng0b809722017-11-03 10:23:26 -0700194 .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");
Yi Tseng0b809722017-11-03 10:23:26 -0700203
204 VlanId vlanId = vlanIdCriterion.vlanId();
205
206 TrafficSelector selector = DefaultTrafficSelector.builder()
207 .matchVlanId(vlanId)
208 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800209 TrafficTreatment treatment = fwd.treatment();
210 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800211 treatment = buildSetNextIdTreatment(fwd.nextId(),
212 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800213 }
Yi Tseng0b809722017-11-03 10:23:26 -0700214 FlowRule flowRule = DefaultFlowRule.builder()
215 .withSelector(selector)
216 .withTreatment(treatment)
217 .fromApp(fwd.appId())
218 .withPriority(fwd.priority())
219 .makePermanent()
220 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800221 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)
Yi Tseng0b809722017-11-03 10:23:26 -0700222 .build();
223
224 resultBuilder.addFlowRule(flowRule);
225 }
226
Yi Tsengdbe05602017-11-17 18:02:43 -0800227 private void processIpv4UnicastRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
228 PipelinerTranslationResult.Builder resultBuilder) {
229 checkNotNull(ipDstCriterion, "IP dst criterion should not be null");
Yi Tsengdbe05602017-11-17 18:02:43 -0800230 TrafficSelector selector = DefaultTrafficSelector.builder()
231 .matchIPDst(ipDstCriterion.ip())
232 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800233 TrafficTreatment treatment = fwd.treatment();
234 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800235 treatment = buildSetNextIdTreatment(fwd.nextId(),
236 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_UNICAST_V4);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800237 }
Yi Tsengdbe05602017-11-17 18:02:43 -0800238 FlowRule flowRule = DefaultFlowRule.builder()
239 .withSelector(selector)
240 .withTreatment(treatment)
241 .fromApp(fwd.appId())
242 .withPriority(fwd.priority())
243 .makePermanent()
244 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800245 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_UNICAST_V4)
Yi Tsengdbe05602017-11-17 18:02:43 -0800246 .build();
247
248 resultBuilder.addFlowRule(flowRule);
249 }
250
Yi Tseng1b154bd2017-11-20 17:48:19 -0800251 private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
252 PipelinerTranslationResult.Builder resultBuilder) {
253 checkNotNull(mplsCriterion, "Mpls criterion should not be null");
Yi Tsengdf3eec52018-02-15 14:56:02 -0800254 TrafficTreatment treatment;
255
256 treatment = fwd.treatment();
257 if (fwd.nextId() != null) {
Yi Tseng43ee7e82018-04-12 16:37:34 +0800258 PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID,
Yi Tsengdf3eec52018-02-15 14:56:02 -0800259 ImmutableByteSequence.copyFrom(fwd.nextId().byteValue()));
260 PiAction nextIdAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800261 .withId(FabricConstants.FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT)
Yi Tsengdf3eec52018-02-15 14:56:02 -0800262 .withParameter(nextIdParam)
263 .build();
264 treatment = DefaultTrafficTreatment.builder()
265 .piTableAction(nextIdAction)
266 .build();
Yi Tseng1b154bd2017-11-20 17:48:19 -0800267 }
Yi Tsengdf3eec52018-02-15 14:56:02 -0800268
Yi Tseng1b154bd2017-11-20 17:48:19 -0800269 TrafficSelector selector = DefaultTrafficSelector.builder()
270 .add(mplsCriterion)
271 .build();
272
Yi Tseng1b154bd2017-11-20 17:48:19 -0800273 FlowRule flowRule = DefaultFlowRule.builder()
274 .withSelector(selector)
275 .withTreatment(treatment)
276 .fromApp(fwd.appId())
277 .withPriority(fwd.priority())
278 .makePermanent()
279 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800280 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_MPLS)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800281 .build();
282
283 resultBuilder.addFlowRule(flowRule);
284 }
285
Yi Tsengdf3eec52018-02-15 14:56:02 -0800286 /**
287 * Builds treatment with set_next_id action, returns empty treatment
288 * if next id is null.
289 *
290 * @param nextId the next id for action
291 * @return treatment with set_next_id action; empty treatment if next id is null
292 */
Yi Tseng47eac892018-07-11 02:17:04 +0800293 private static TrafficTreatment buildSetNextIdTreatment(Integer nextId, PiActionId actionId) {
Yi Tseng43ee7e82018-04-12 16:37:34 +0800294 PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID,
Yi Tseng0b809722017-11-03 10:23:26 -0700295 ImmutableByteSequence.copyFrom(nextId.byteValue()));
296 PiAction nextIdAction = PiAction.builder()
Yi Tseng47eac892018-07-11 02:17:04 +0800297 .withId(actionId)
Yi Tseng0b809722017-11-03 10:23:26 -0700298 .withParameter(nextIdParam)
299 .build();
300
301 return DefaultTrafficTreatment.builder()
302 .piTableAction(nextIdAction)
303 .build();
304 }
Yi Tseng0b809722017-11-03 10:23:26 -0700305}