blob: d37402d118deacfd2ad991fd36d195255587a0c4 [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;
32import org.onosproject.net.flow.criteria.VlanIdCriterion;
33import org.onosproject.net.flowobjective.ForwardingObjective;
34import org.onosproject.net.flowobjective.ObjectiveError;
35import org.onosproject.net.pi.runtime.PiAction;
36import org.onosproject.net.pi.runtime.PiActionParam;
37import org.onosproject.pipelines.fabric.FabricConstants;
38import org.slf4j.Logger;
39
40import java.util.Set;
41
42import static com.google.common.base.Preconditions.checkNotNull;
43import static org.slf4j.LoggerFactory.getLogger;
44
45/**
46 * Handling forwarding objective for fabric pipeliner.
47 */
48public class FabricForwardingPipeliner {
49 private static final Logger log = getLogger(FabricForwardingPipeliner.class);
50
51 protected DeviceId deviceId;
52
53 public FabricForwardingPipeliner(DeviceId deviceId) {
54 this.deviceId = deviceId;
55 }
56
57 public PipelinerTranslationResult forward(ForwardingObjective forwardObjective) {
58 PipelinerTranslationResult.Builder resultBuilder = PipelinerTranslationResult.builder();
59 if (forwardObjective.flag() == ForwardingObjective.Flag.VERSATILE) {
60 processVersatileFwd(forwardObjective, resultBuilder);
61 } else {
62 processSpecificFwd(forwardObjective, resultBuilder);
63 }
64 return resultBuilder.build();
65 }
66
67 private void processVersatileFwd(ForwardingObjective fwd,
68 PipelinerTranslationResult.Builder resultBuilder) {
69 // program ACL table only
70 FlowRule flowRule = DefaultFlowRule.builder()
71 .withSelector(fwd.selector())
72 .withTreatment(fwd.treatment())
73 .forTable(FabricConstants.TBL_ACL_ID)
74 .withPriority(fwd.priority())
75 .forDevice(deviceId)
76 .makePermanent()
77 .fromApp(fwd.appId())
78 .build();
79 resultBuilder.addFlowRule(flowRule);
80 }
81
82 private void processSpecificFwd(ForwardingObjective fwd,
83 PipelinerTranslationResult.Builder resultBuilder) {
84 TrafficSelector selector = fwd.selector();
85 TrafficSelector meta = fwd.meta();
86
87 ImmutableSet.Builder<Criterion> criterionSetBuilder = ImmutableSet.builder();
88 criterionSetBuilder.addAll(selector.criteria());
89
90 if (meta != null) {
91 criterionSetBuilder.addAll(meta.criteria());
92 }
93
94 Set<Criterion> criteria = criterionSetBuilder.build();
95
96 VlanIdCriterion vlanIdCriterion = null;
97 EthCriterion ethDstCriterion = null;
98
99 for (Criterion criterion : criteria) {
100 switch (criterion.type()) {
101 case ETH_DST:
102 ethDstCriterion = (EthCriterion) criterion;
103 break;
104 case VLAN_VID:
105 vlanIdCriterion = (VlanIdCriterion) criterion;
106 break;
107 default:
108 log.warn("Unsupported criterion {}", criterion);
109 break;
110 }
111 }
112
113 ForwardingFunctionType forwardingFunctionType =
114 ForwardingFunctionType.getForwardingFunctionType(fwd);
115 switch (forwardingFunctionType) {
116 case L2_UNICAST:
117 processL2UnicastRule(vlanIdCriterion, ethDstCriterion, fwd, resultBuilder);
118 break;
119 case L2_BROADCAST:
120 processL2BroadcastRule(vlanIdCriterion, fwd, resultBuilder);
121 break;
122 case IPV4_UNICAST:
123 case IPV4_MULTICAST:
124 case IPV6_UNICAST:
125 case IPV6_MULTICAST:
126 case MPLS:
127 default:
128 log.warn("Unsupported forwarding function type {}", criteria);
129 resultBuilder.setError(ObjectiveError.UNSUPPORTED);
130 break;
131 }
132 }
133
134 // L2 Unicast: learnt mac address + vlan
135 private void processL2UnicastRule(VlanIdCriterion vlanIdCriterion,
136 EthCriterion ethDstCriterion,
137 ForwardingObjective fwd,
138 PipelinerTranslationResult.Builder resultBuilder) {
139 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
140 checkNotNull(ethDstCriterion, "EthDst criterion should not be null");
141
142 if (fwd.nextId() == null) {
143 log.warn("Forwarding objective for L2 unicast should contains next id");
144 resultBuilder.setError(ObjectiveError.BADPARAMS);
145 return;
146 }
147
148 VlanId vlanId = vlanIdCriterion.vlanId();
149 MacAddress ethDst = ethDstCriterion.mac();
150
151 TrafficSelector selector = DefaultTrafficSelector.builder()
152 .matchVlanId(vlanId)
153 .matchEthDst(ethDst)
154 .build();
155 TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
156 FlowRule flowRule = DefaultFlowRule.builder()
157 .withSelector(selector)
158 .withTreatment(treatment)
159 .fromApp(fwd.appId())
160 .withPriority(fwd.priority())
161 .makePermanent()
162 .forDevice(deviceId)
163 .forTable(FabricConstants.TBL_BRIDGING_ID)
164 .build();
165
166 resultBuilder.addFlowRule(flowRule);
167 }
168
169 private void processL2BroadcastRule(VlanIdCriterion vlanIdCriterion,
170 ForwardingObjective fwd,
171 PipelinerTranslationResult.Builder resultBuilder) {
172 checkNotNull(vlanIdCriterion, "VlanId criterion should not be null");
173 if (fwd.nextId() == null) {
174 log.warn("Forwarding objective for L2 broadcast should contains next id");
175 resultBuilder.setError(ObjectiveError.BADPARAMS);
176 return;
177 }
178
179 VlanId vlanId = vlanIdCriterion.vlanId();
180
181 TrafficSelector selector = DefaultTrafficSelector.builder()
182 .matchVlanId(vlanId)
183 .build();
184 TrafficTreatment treatment = buildSetNextIdTreatment(fwd.nextId());
185 FlowRule flowRule = DefaultFlowRule.builder()
186 .withSelector(selector)
187 .withTreatment(treatment)
188 .fromApp(fwd.appId())
189 .withPriority(fwd.priority())
190 .makePermanent()
191 .forDevice(deviceId)
192 .forTable(FabricConstants.TBL_BRIDGING_ID)
193 .build();
194
195 resultBuilder.addFlowRule(flowRule);
196 }
197
198 private static TrafficTreatment buildSetNextIdTreatment(Integer nextId) {
199 PiActionParam nextIdParam = new PiActionParam(FabricConstants.ACT_PRM_NEXT_ID_ID,
200 ImmutableByteSequence.copyFrom(nextId.byteValue()));
201 PiAction nextIdAction = PiAction.builder()
202 .withId(FabricConstants.ACT_SET_NEXT_ID_ID)
203 .withParameter(nextIdParam)
204 .build();
205
206 return DefaultTrafficTreatment.builder()
207 .piTableAction(nextIdAction)
208 .build();
209 }
210
211}