daniel
Committed by Gerrit Code Review

SONA: Pipeline for SONA

- Open vSwitch Pipeline for SONA added
- Only OpenStackSwitching app will use this
- Bug fixed
- Pipeline renamed

Change-Id: I0cee06c84db4f130c01dfea37dbab44bf9c1fd26
1 +package org.onosproject.driver.pipeline;
2 +
3 +/**
4 + * Created by mcpark on 15. 12. 3.
5 + */
6 +/*
7 + * Copyright 2015 Open Networking Laboratory
8 + *
9 + * Licensed under the Apache License, Version 2.0 (the "License");
10 + * you may not use this file except in compliance with the License.
11 + * You may obtain a copy of the License at
12 + *
13 + * http://www.apache.org/licenses/LICENSE-2.0
14 + *
15 + * Unless required by applicable law or agreed to in writing, software
16 + * distributed under the License is distributed on an "AS IS" BASIS,
17 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 + * See the License for the specific language governing permissions and
19 + * limitations under the License.
20 + */
21 +
22 +import org.onlab.osgi.ServiceDirectory;
23 +import org.onlab.packet.Ethernet;
24 +import org.onosproject.core.ApplicationId;
25 +import org.onosproject.core.CoreService;
26 +import org.onosproject.net.DeviceId;
27 +import org.onosproject.net.behaviour.Pipeliner;
28 +import org.onosproject.net.behaviour.PipelinerContext;
29 +import org.onosproject.net.flow.DefaultFlowRule;
30 +import org.onosproject.net.flow.DefaultTrafficSelector;
31 +import org.onosproject.net.flow.DefaultTrafficTreatment;
32 +import org.onosproject.net.flow.FlowRule;
33 +import org.onosproject.net.flow.FlowRuleOperations;
34 +import org.onosproject.net.flow.FlowRuleOperationsContext;
35 +import org.onosproject.net.flow.FlowRuleService;
36 +import org.onosproject.net.flow.TrafficSelector;
37 +import org.onosproject.net.flow.TrafficTreatment;
38 +import org.onosproject.net.flow.criteria.Criterion;
39 +import org.onosproject.net.flow.criteria.EthTypeCriterion;
40 +import org.onosproject.net.flow.criteria.UdpPortCriterion;
41 +import org.onosproject.net.flowobjective.FilteringObjective;
42 +import org.onosproject.net.flowobjective.FlowObjectiveStore;
43 +import org.onosproject.net.flowobjective.ForwardingObjective;
44 +import org.onosproject.net.flowobjective.NextObjective;
45 +import org.onosproject.net.flowobjective.Objective;
46 +import org.onosproject.net.flowobjective.ObjectiveError;
47 +import org.slf4j.Logger;
48 +
49 +import java.util.Collection;
50 +import java.util.Collections;
51 +
52 +import static org.slf4j.LoggerFactory.getLogger;
53 +
54 +/**
55 + * Driver for OpenstackSwitching.
56 + */
57 +public class OpenstackPipeline extends DefaultSingleTablePipeline
58 + implements Pipeliner {
59 +
60 + private final Logger log = getLogger(getClass());
61 + private CoreService coreService;
62 + private ServiceDirectory serviceDirectory;
63 + protected FlowObjectiveStore flowObjectiveStore;
64 + protected DeviceId deviceId;
65 + protected ApplicationId appId;
66 + protected FlowRuleService flowRuleService;
67 +
68 + protected static final int VNI_TABLE = 0;
69 + protected static final int FORWARDING_TABLE = 1;
70 +
71 + private static final int DROP_PRIORITY = 0;
72 + private static final int TIME_OUT = 0;
73 + private static final int DHCP_SERVER_PORT = 67;
74 + private static final int DHCP_CLIENT_PORT = 68;
75 +
76 +
77 + @Override
78 + public void init(DeviceId deviceId, PipelinerContext context) {
79 + super.init(deviceId, context);
80 + this.serviceDirectory = context.directory();
81 + this.deviceId = deviceId;
82 +
83 + coreService = serviceDirectory.get(CoreService.class);
84 + flowRuleService = serviceDirectory.get(FlowRuleService.class);
85 + flowObjectiveStore = context.store();
86 +
87 + appId = coreService.registerApplication(
88 + "org.onosproject.driver.OpenstackPipeline");
89 +
90 + initializePipeline();
91 + }
92 +
93 + @Override
94 + public void filter(FilteringObjective filteringObjective) {
95 + super.filter(filteringObjective);
96 + }
97 +
98 + @Override
99 + public void next(NextObjective nextObjective) {
100 + super.next(nextObjective);
101 + }
102 +
103 + @Override
104 + public void forward(ForwardingObjective forwardingObjective) {
105 + Collection<FlowRule> rules;
106 + FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
107 +
108 + rules = processForward(forwardingObjective);
109 +
110 + switch (forwardingObjective.op()) {
111 + case ADD:
112 + rules.stream()
113 + .filter(rule -> rule != null)
114 + .forEach(flowOpsBuilder::add);
115 + break;
116 + case REMOVE:
117 + rules.stream()
118 + .filter(rule -> rule != null)
119 + .forEach(flowOpsBuilder::remove);
120 + break;
121 + default:
122 + fail(forwardingObjective, ObjectiveError.UNKNOWN);
123 + log.warn("Unknown forwarding type {}");
124 + }
125 +
126 + flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
127 + @Override
128 + public void onSuccess(FlowRuleOperations ops) {
129 + pass(forwardingObjective);
130 + }
131 +
132 + @Override
133 + public void onError(FlowRuleOperations ops) {
134 + fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
135 + }
136 + }));
137 + }
138 +
139 + private void initializePipeline() {
140 + processVNITable(true);
141 + processForwardingTable(true);
142 + }
143 +
144 + private void processVNITable(boolean install) {
145 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
146 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
147 +
148 + treatment.transition(FORWARDING_TABLE);
149 +
150 + FlowRule flowRule = DefaultFlowRule.builder()
151 + .forDevice(deviceId)
152 + .withSelector(selector.build())
153 + .withTreatment(treatment.build())
154 + .withPriority(DROP_PRIORITY)
155 + .fromApp(appId)
156 + .makePermanent()
157 + .forTable(VNI_TABLE)
158 + .build();
159 +
160 + applyRules(install, flowRule);
161 + }
162 +
163 + private void processForwardingTable(boolean install) {
164 + TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
165 + TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
166 +
167 + treatment.drop();
168 +
169 + FlowRule flowRule = DefaultFlowRule.builder()
170 + .forDevice(deviceId)
171 + .withSelector(selector.build())
172 + .withTreatment(treatment.build())
173 + .withPriority(DROP_PRIORITY)
174 + .fromApp(appId)
175 + .makePermanent()
176 + .forTable(FORWARDING_TABLE)
177 + .build();
178 +
179 + applyRules(install, flowRule);
180 + }
181 +
182 + private void applyRules(boolean install, FlowRule flowRule) {
183 + FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
184 +
185 + flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
186 +
187 + flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
188 + @Override
189 + public void onSuccess(FlowRuleOperations ops) {
190 + log.debug("Provisioned vni or forwarding table");
191 + }
192 +
193 + @Override
194 + public void onError(FlowRuleOperations ops) {
195 + log.debug("Failed to privision vni or forwarding table");
196 + }
197 + }));
198 + }
199 +
200 + private Collection<FlowRule> processForward(ForwardingObjective forwardingObjective) {
201 + switch (forwardingObjective.flag()) {
202 + case SPECIFIC:
203 + return processSpecific(forwardingObjective);
204 + case VERSATILE:
205 + return processVersatile(forwardingObjective);
206 + default:
207 + fail(forwardingObjective, ObjectiveError.UNKNOWN);
208 + log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
209 + }
210 + return Collections.emptySet();
211 + }
212 +
213 + private Collection<FlowRule> processVersatile(ForwardingObjective forwardingObjective) {
214 + log.debug("Processing versatile forwarding objective");
215 +
216 + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
217 + .forDevice(deviceId)
218 + .withSelector(forwardingObjective.selector())
219 + .withTreatment(forwardingObjective.treatment())
220 + .withPriority(forwardingObjective.priority())
221 + .fromApp(forwardingObjective.appId());
222 +
223 + if (forwardingObjective.permanent()) {
224 + ruleBuilder.makePermanent();
225 + } else {
226 + ruleBuilder.makeTemporary(TIME_OUT);
227 + }
228 +
229 + //ARP & DHCP Rule
230 + EthTypeCriterion ethCriterion =
231 + (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE);
232 + UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective
233 + .selector().getCriterion(Criterion.Type.UDP_DST);
234 + if (ethCriterion != null) {
235 + if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP ||
236 + ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) {
237 + ruleBuilder.forTable(VNI_TABLE);
238 + return Collections.singletonList(ruleBuilder.build());
239 + } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) {
240 + ruleBuilder.forTable(VNI_TABLE);
241 + return Collections.singletonList(ruleBuilder.build());
242 + }
243 + }
244 + return Collections.emptySet();
245 + }
246 +
247 + private Collection<FlowRule> processSpecific(ForwardingObjective forwardingObjective) {
248 + log.debug("Processing specific forwarding objective");
249 +
250 + FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
251 + .forDevice(deviceId)
252 + .withSelector(forwardingObjective.selector())
253 + .withTreatment(forwardingObjective.treatment())
254 + .withPriority(forwardingObjective.priority())
255 + .fromApp(forwardingObjective.appId());
256 +
257 + if (forwardingObjective.permanent()) {
258 + ruleBuilder.makePermanent();
259 + } else {
260 + ruleBuilder.makeTemporary(TIME_OUT);
261 + }
262 +
263 + //VNI Table Rule
264 + if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) {
265 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
266 + forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
267 + tBuilder.transition(FORWARDING_TABLE);
268 + ruleBuilder.withTreatment(tBuilder.build());
269 + ruleBuilder.forTable(VNI_TABLE);
270 + } else {
271 + ruleBuilder.forTable(FORWARDING_TABLE);
272 + }
273 +
274 + return Collections.singletonList(ruleBuilder.build());
275 + }
276 +
277 +
278 + private void pass(Objective obj) {
279 + if (obj.context().isPresent()) {
280 + obj.context().get().onSuccess(obj);
281 + }
282 + }
283 +
284 + private void fail(Objective obj, ObjectiveError error) {
285 + if (obj.context().isPresent()) {
286 + obj.context().get().onError(obj, error);
287 + }
288 + }
289 +}
290 +