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
Showing
1 changed file
with
290 additions
and
0 deletions
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 | + |
-
Please register or login to post a comment