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