blob: 268a6ac73cc599edb691876bb21618ab3cf95562 [file] [log] [blame]
danielc8620b12015-11-30 15:50:59 +09001package 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
22import org.onlab.osgi.ServiceDirectory;
23import org.onlab.packet.Ethernet;
24import org.onosproject.core.ApplicationId;
25import org.onosproject.core.CoreService;
26import org.onosproject.net.DeviceId;
27import org.onosproject.net.behaviour.Pipeliner;
28import org.onosproject.net.behaviour.PipelinerContext;
29import org.onosproject.net.flow.DefaultFlowRule;
30import org.onosproject.net.flow.DefaultTrafficSelector;
31import org.onosproject.net.flow.DefaultTrafficTreatment;
32import org.onosproject.net.flow.FlowRule;
33import org.onosproject.net.flow.FlowRuleOperations;
34import org.onosproject.net.flow.FlowRuleOperationsContext;
35import org.onosproject.net.flow.FlowRuleService;
36import org.onosproject.net.flow.TrafficSelector;
37import org.onosproject.net.flow.TrafficTreatment;
38import org.onosproject.net.flow.criteria.Criterion;
39import org.onosproject.net.flow.criteria.EthTypeCriterion;
40import org.onosproject.net.flow.criteria.UdpPortCriterion;
41import org.onosproject.net.flowobjective.FilteringObjective;
42import org.onosproject.net.flowobjective.FlowObjectiveStore;
43import org.onosproject.net.flowobjective.ForwardingObjective;
44import org.onosproject.net.flowobjective.NextObjective;
45import org.onosproject.net.flowobjective.Objective;
46import org.onosproject.net.flowobjective.ObjectiveError;
47import org.slf4j.Logger;
48
49import java.util.Collection;
50import java.util.Collections;
51
52import static org.slf4j.LoggerFactory.getLogger;
53
54/**
55 * Driver for OpenstackSwitching.
56 */
57public 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