blob: 038b949e4b6869f4b33ec316f59cdeb30497db55 [file] [log] [blame]
danielc8620b12015-11-30 15:50:59 +09001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
danielc8620b12015-11-30 15:50:59 +09003 *
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;
sangho90088532016-02-25 18:06:12 +090067 protected static final int ACL_TABLE = 2;
danielc8620b12015-11-30 15:50:59 +090068
69 private static final int DROP_PRIORITY = 0;
70 private static final int TIME_OUT = 0;
71 private static final int DHCP_SERVER_PORT = 67;
72 private static final int DHCP_CLIENT_PORT = 68;
73
74
75 @Override
76 public void init(DeviceId deviceId, PipelinerContext context) {
77 super.init(deviceId, context);
78 this.serviceDirectory = context.directory();
79 this.deviceId = deviceId;
80
81 coreService = serviceDirectory.get(CoreService.class);
82 flowRuleService = serviceDirectory.get(FlowRuleService.class);
83 flowObjectiveStore = context.store();
84
85 appId = coreService.registerApplication(
86 "org.onosproject.driver.OpenstackPipeline");
87
88 initializePipeline();
89 }
90
91 @Override
92 public void filter(FilteringObjective filteringObjective) {
93 super.filter(filteringObjective);
94 }
95
96 @Override
97 public void next(NextObjective nextObjective) {
98 super.next(nextObjective);
99 }
100
101 @Override
102 public void forward(ForwardingObjective forwardingObjective) {
103 Collection<FlowRule> rules;
104 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
105
106 rules = processForward(forwardingObjective);
107
108 switch (forwardingObjective.op()) {
109 case ADD:
110 rules.stream()
Sho SHIMIZU45906042016-01-13 23:05:54 -0800111 .filter(Objects::nonNull)
danielc8620b12015-11-30 15:50:59 +0900112 .forEach(flowOpsBuilder::add);
113 break;
114 case REMOVE:
115 rules.stream()
Sho SHIMIZU45906042016-01-13 23:05:54 -0800116 .filter(Objects::nonNull)
danielc8620b12015-11-30 15:50:59 +0900117 .forEach(flowOpsBuilder::remove);
118 break;
119 default:
120 fail(forwardingObjective, ObjectiveError.UNKNOWN);
121 log.warn("Unknown forwarding type {}");
122 }
123
124 flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
125 @Override
126 public void onSuccess(FlowRuleOperations ops) {
127 pass(forwardingObjective);
128 }
129
130 @Override
131 public void onError(FlowRuleOperations ops) {
132 fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
133 }
134 }));
135 }
136
137 private void initializePipeline() {
Jonathan Hart51539b82015-10-29 09:53:04 -0700138 processVniTable(true);
danielc8620b12015-11-30 15:50:59 +0900139 processForwardingTable(true);
sangho90088532016-02-25 18:06:12 +0900140 processAclTable(true);
danielc8620b12015-11-30 15:50:59 +0900141 }
142
Jonathan Hart51539b82015-10-29 09:53:04 -0700143 private void processVniTable(boolean install) {
danielc8620b12015-11-30 15:50:59 +0900144 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
145 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
146
147 treatment.transition(FORWARDING_TABLE);
148
149 FlowRule flowRule = DefaultFlowRule.builder()
150 .forDevice(deviceId)
151 .withSelector(selector.build())
152 .withTreatment(treatment.build())
153 .withPriority(DROP_PRIORITY)
154 .fromApp(appId)
155 .makePermanent()
156 .forTable(VNI_TABLE)
157 .build();
158
159 applyRules(install, flowRule);
160 }
161
162 private void processForwardingTable(boolean install) {
163 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
164 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
165
166 treatment.drop();
167
168 FlowRule flowRule = DefaultFlowRule.builder()
169 .forDevice(deviceId)
170 .withSelector(selector.build())
171 .withTreatment(treatment.build())
172 .withPriority(DROP_PRIORITY)
173 .fromApp(appId)
174 .makePermanent()
175 .forTable(FORWARDING_TABLE)
176 .build();
177
178 applyRules(install, flowRule);
179 }
180
sangho90088532016-02-25 18:06:12 +0900181 private void processAclTable(boolean install) {
182 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
183 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
184
185 treatment.wipeDeferred();
186 treatment.drop();
187
188 FlowRule flowRule = DefaultFlowRule.builder()
189 .forDevice(deviceId)
190 .withSelector(selector.build())
191 .withTreatment(treatment.build())
192 .withPriority(DROP_PRIORITY)
193 .fromApp(appId)
194 .makePermanent()
195 .forTable(ACL_TABLE)
196 .build();
197
198 applyRules(install, flowRule);
199 }
200
danielc8620b12015-11-30 15:50:59 +0900201 private void applyRules(boolean install, FlowRule flowRule) {
202 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
203
204 flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
205
206 flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
207 @Override
208 public void onSuccess(FlowRuleOperations ops) {
209 log.debug("Provisioned vni or forwarding table");
210 }
211
212 @Override
213 public void onError(FlowRuleOperations ops) {
214 log.debug("Failed to privision vni or forwarding table");
215 }
216 }));
217 }
218
219 private Collection<FlowRule> processForward(ForwardingObjective forwardingObjective) {
220 switch (forwardingObjective.flag()) {
221 case SPECIFIC:
222 return processSpecific(forwardingObjective);
223 case VERSATILE:
224 return processVersatile(forwardingObjective);
225 default:
226 fail(forwardingObjective, ObjectiveError.UNKNOWN);
227 log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
228 }
229 return Collections.emptySet();
230 }
231
232 private Collection<FlowRule> processVersatile(ForwardingObjective forwardingObjective) {
233 log.debug("Processing versatile forwarding objective");
234
235 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
236 .forDevice(deviceId)
237 .withSelector(forwardingObjective.selector())
238 .withTreatment(forwardingObjective.treatment())
239 .withPriority(forwardingObjective.priority())
240 .fromApp(forwardingObjective.appId());
241
242 if (forwardingObjective.permanent()) {
243 ruleBuilder.makePermanent();
244 } else {
245 ruleBuilder.makeTemporary(TIME_OUT);
246 }
247
248 //ARP & DHCP Rule
249 EthTypeCriterion ethCriterion =
250 (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE);
251 UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective
252 .selector().getCriterion(Criterion.Type.UDP_DST);
253 if (ethCriterion != null) {
254 if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP ||
255 ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) {
256 ruleBuilder.forTable(VNI_TABLE);
257 return Collections.singletonList(ruleBuilder.build());
258 } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) {
259 ruleBuilder.forTable(VNI_TABLE);
260 return Collections.singletonList(ruleBuilder.build());
261 }
262 }
263 return Collections.emptySet();
264 }
265
266 private Collection<FlowRule> processSpecific(ForwardingObjective forwardingObjective) {
267 log.debug("Processing specific forwarding objective");
268
269 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
270 .forDevice(deviceId)
271 .withSelector(forwardingObjective.selector())
272 .withTreatment(forwardingObjective.treatment())
273 .withPriority(forwardingObjective.priority())
274 .fromApp(forwardingObjective.appId());
275
276 if (forwardingObjective.permanent()) {
277 ruleBuilder.makePermanent();
278 } else {
279 ruleBuilder.makeTemporary(TIME_OUT);
280 }
281
282 //VNI Table Rule
283 if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) {
284 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
285 forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
286 tBuilder.transition(FORWARDING_TABLE);
287 ruleBuilder.withTreatment(tBuilder.build());
288 ruleBuilder.forTable(VNI_TABLE);
sangho90088532016-02-25 18:06:12 +0900289 } else if (forwardingObjective.selector().getCriterion(Criterion.Type.TUNNEL_ID) != null) {
290 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
291 tBuilder.deferred();
292 forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
293 tBuilder.transition(ACL_TABLE);
294 ruleBuilder.withTreatment(tBuilder.build());
danielc8620b12015-11-30 15:50:59 +0900295 ruleBuilder.forTable(FORWARDING_TABLE);
sangho90088532016-02-25 18:06:12 +0900296 } else {
297 ruleBuilder.forTable(ACL_TABLE);
danielc8620b12015-11-30 15:50:59 +0900298 }
299
300 return Collections.singletonList(ruleBuilder.build());
301 }
302
303
304 private void pass(Objective obj) {
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800305 obj.context().ifPresent(context -> context.onSuccess(obj));
danielc8620b12015-11-30 15:50:59 +0900306 }
307
308 private void fail(Objective obj, ObjectiveError error) {
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800309 obj.context().ifPresent(context -> context.onError(obj, error));
danielc8620b12015-11-30 15:50:59 +0900310 }
311}
312