blob: 580d398bc79dedc08015797d4a25d75db22e2661 [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;
Charles Chan384aea22018-08-23 22:08:02 -0700148 case IPV4_ROUTING:
149 processIpv4RoutingRule(ipDstCriterion, fwd, resultBuilder);
Yi Tsengdbe05602017-11-17 18:02:43 -0800150 break;
Yi Tseng1b154bd2017-11-20 17:48:19 -0800151 case MPLS:
152 processMplsRule(mplsCriterion, fwd, resultBuilder);
153 break;
Charles Chan384aea22018-08-23 22:08:02 -0700154 case IPV6_ROUTING:
Yi Tseng0b809722017-11-03 10:23:26 -0700155 default:
156 log.warn("Unsupported forwarding function type {}", criteria);
157 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
158 break;
159 }
160 }
161
162 // L2 Unicast: learnt mac address + vlan
163 private void processL2UnicastRule(VlanIdCriterion vlanIdCriterion,
164 EthCriterion ethDstCriterion,
165 ForwardingObjective fwd,
166 PipelinerTranslationResult.Builder resultBuilder) {
167 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
168 checkNotNull(ethDstCriterion, "EthDst criterion should not be null");
169
Yi Tseng0b809722017-11-03 10:23:26 -0700170 VlanId vlanId = vlanIdCriterion.vlanId();
171 MacAddress ethDst = ethDstCriterion.mac();
172
173 TrafficSelector selector = DefaultTrafficSelector.builder()
174 .matchVlanId(vlanId)
Charles Chan384aea22018-08-23 22:08:02 -0700175 .matchEthDstMasked(ethDst, MacAddress.EXACT_MASK)
Yi Tseng0b809722017-11-03 10:23:26 -0700176 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800177 TrafficTreatment treatment = fwd.treatment();
178 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800179 treatment = buildSetNextIdTreatment(fwd.nextId(),
180 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800181 }
182
Yi Tseng0b809722017-11-03 10:23:26 -0700183 FlowRule flowRule = DefaultFlowRule.builder()
184 .withSelector(selector)
185 .withTreatment(treatment)
186 .fromApp(fwd.appId())
187 .withPriority(fwd.priority())
188 .makePermanent()
189 .forDevice(deviceId)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800190 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)
Yi Tseng0b809722017-11-03 10:23:26 -0700191 .build();
192
193 resultBuilder.addFlowRule(flowRule);
194 }
195
196 private void processL2BroadcastRule(VlanIdCriterion vlanIdCriterion,
197 ForwardingObjective fwd,
198 PipelinerTranslationResult.Builder resultBuilder) {
199 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
Yi Tseng0b809722017-11-03 10:23:26 -0700200
201 VlanId vlanId = vlanIdCriterion.vlanId();
202
203 TrafficSelector selector = DefaultTrafficSelector.builder()
204 .matchVlanId(vlanId)
205 .build();
Yi Tsengdf3eec52018-02-15 14:56:02 -0800206 TrafficTreatment treatment = fwd.treatment();
207 if (fwd.nextId() != null) {
Yi Tseng47eac892018-07-11 02:17:04 +0800208 treatment = buildSetNextIdTreatment(fwd.nextId(),
209 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_BRIDGING);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800210 }
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)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800218 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_BRIDGING)
Yi Tseng0b809722017-11-03 10:23:26 -0700219 .build();
220
221 resultBuilder.addFlowRule(flowRule);
222 }
223
Charles Chan384aea22018-08-23 22:08:02 -0700224 private void processIpv4RoutingRule(IPCriterion ipDstCriterion, ForwardingObjective fwd,
Yi Tsengdbe05602017-11-17 18:02:43 -0800225 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) {
Yi Tseng47eac892018-07-11 02:17:04 +0800232 treatment = buildSetNextIdTreatment(fwd.nextId(),
Charles Chan384aea22018-08-23 22:08:02 -0700233 FabricConstants.FABRIC_INGRESS_FORWARDING_SET_NEXT_ID_ROUTING_V4);
Yi Tsengdf3eec52018-02-15 14:56:02 -0800234 }
Yi Tsengdbe05602017-11-17 18:02:43 -0800235 FlowRule flowRule = DefaultFlowRule.builder()
236 .withSelector(selector)
237 .withTreatment(treatment)
238 .fromApp(fwd.appId())
239 .withPriority(fwd.priority())
240 .makePermanent()
241 .forDevice(deviceId)
Charles Chan384aea22018-08-23 22:08:02 -0700242 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_ROUTING_V4)
Yi Tsengdbe05602017-11-17 18:02:43 -0800243 .build();
244
245 resultBuilder.addFlowRule(flowRule);
246 }
247
Yi Tseng1b154bd2017-11-20 17:48:19 -0800248 private void processMplsRule(MplsCriterion mplsCriterion, ForwardingObjective fwd,
249 PipelinerTranslationResult.Builder resultBuilder) {
250 checkNotNull(mplsCriterion, "Mpls criterion should not be null");
Yi Tsengdf3eec52018-02-15 14:56:02 -0800251 TrafficTreatment treatment;
252
253 treatment = fwd.treatment();
254 if (fwd.nextId() != null) {
Charles Chanea89a1c2018-08-13 13:14:18 -0700255 PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, fwd.nextId());
Yi Tsengdf3eec52018-02-15 14:56:02 -0800256 PiAction nextIdAction = PiAction.builder()
Yi Tseng43ee7e82018-04-12 16:37:34 +0800257 .withId(FabricConstants.FABRIC_INGRESS_FORWARDING_POP_MPLS_AND_NEXT)
Yi Tsengdf3eec52018-02-15 14:56:02 -0800258 .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)
Yi Tseng43ee7e82018-04-12 16:37:34 +0800276 .forTable(FabricConstants.FABRIC_INGRESS_FORWARDING_MPLS)
Yi Tseng1b154bd2017-11-20 17:48:19 -0800277 .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 Tseng47eac892018-07-11 02:17:04 +0800289 private static TrafficTreatment buildSetNextIdTreatment(Integer nextId, PiActionId actionId) {
Charles Chanea89a1c2018-08-13 13:14:18 -0700290 PiActionParam nextIdParam = new PiActionParam(FabricConstants.NEXT_ID, nextId);
Yi Tseng0b809722017-11-03 10:23:26 -0700291 PiAction nextIdAction = PiAction.builder()
Yi Tseng47eac892018-07-11 02:17:04 +0800292 .withId(actionId)
Yi Tseng0b809722017-11-03 10:23:26 -0700293 .withParameter(nextIdParam)
294 .build();
295
296 return DefaultTrafficTreatment.builder()
297 .piTableAction(nextIdAction)
298 .build();
299 }
Yi Tseng0b809722017-11-03 10:23:26 -0700300}