blob: 5d0983903aee74d8b552c5aa30e76965f5ef2ced [file] [log] [blame]
samuel3b2743d2015-07-29 10:44:30 +08001/*
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 */
16package org.onosproject.driver.pipeline;
17
18import static org.slf4j.LoggerFactory.getLogger;
19
20import java.util.Collection;
21import java.util.Collections;
22
23import org.onlab.osgi.ServiceDirectory;
lishuai4d6a0ee2015-10-19 19:05:48 +080024import org.onosproject.core.ApplicationId;
samuel3b2743d2015-07-29 10:44:30 +080025import 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.device.DeviceService;
samuel3b2743d2015-07-29 10:44:30 +080030import org.onosproject.net.flow.DefaultFlowRule;
lishuai4d6a0ee2015-10-19 19:05:48 +080031import org.onosproject.net.flow.DefaultTrafficSelector;
samuel3b2743d2015-07-29 10:44:30 +080032import org.onosproject.net.flow.DefaultTrafficTreatment;
33import org.onosproject.net.flow.FlowRule;
34import org.onosproject.net.flow.FlowRuleOperations;
35import org.onosproject.net.flow.FlowRuleOperationsContext;
36import org.onosproject.net.flow.FlowRuleService;
37import org.onosproject.net.flow.TrafficSelector;
38import org.onosproject.net.flow.TrafficTreatment;
39import org.onosproject.net.flow.criteria.Criterion.Type;
40import org.onosproject.net.flow.instructions.Instructions;
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
49/**
50 * Driver for standard OpenVSwitch.
51 */
CNluciusa66c3972015-09-06 20:31:29 +080052public class OpenVSwitchPipeline extends DefaultSingleTablePipeline
samuel3b2743d2015-07-29 10:44:30 +080053 implements Pipeliner {
54
CNluciusa66c3972015-09-06 20:31:29 +080055 private static final String VTN_APP_ID = "org.onosproject.app.vtn";
samuel3b2743d2015-07-29 10:44:30 +080056 private final Logger log = getLogger(getClass());
57 private CoreService coreService;
58 private ServiceDirectory serviceDirectory;
59 protected FlowObjectiveStore flowObjectiveStore;
60 protected DeviceId deviceId;
lishuai4d6a0ee2015-10-19 19:05:48 +080061 protected ApplicationId appId;
samuel3b2743d2015-07-29 10:44:30 +080062 protected FlowRuleService flowRuleService;
63 protected DeviceService deviceService;
samuel3b2743d2015-07-29 10:44:30 +080064 private static final int TIME_OUT = 0;
lishuai4d6a0ee2015-10-19 19:05:48 +080065 private static final int CLASSIFIER_TABLE = 0;
66 private static final int MAC_TABLE = 50;
67 private static final int TABLE_MISS_PRIORITY = 0;
samuel3b2743d2015-07-29 10:44:30 +080068
69 @Override
70 public void init(DeviceId deviceId, PipelinerContext context) {
CNluciusa66c3972015-09-06 20:31:29 +080071 super.init(deviceId, context);
samuel3b2743d2015-07-29 10:44:30 +080072 this.serviceDirectory = context.directory();
73 this.deviceId = deviceId;
74
75 coreService = serviceDirectory.get(CoreService.class);
76 flowRuleService = serviceDirectory.get(FlowRuleService.class);
77 flowObjectiveStore = context.store();
lishuai4d6a0ee2015-10-19 19:05:48 +080078 appId = coreService
samuel3b2743d2015-07-29 10:44:30 +080079 .registerApplication("org.onosproject.driver.OpenVSwitchPipeline");
lishuai4d6a0ee2015-10-19 19:05:48 +080080 initializePipeline();
samuel3b2743d2015-07-29 10:44:30 +080081 }
82
83 @Override
84 public void filter(FilteringObjective filteringObjective) {
CNluciusa66c3972015-09-06 20:31:29 +080085 super.filter(filteringObjective);
samuel3b2743d2015-07-29 10:44:30 +080086 }
87
88 @Override
89 public void forward(ForwardingObjective fwd) {
CNluciusa66c3972015-09-06 20:31:29 +080090 if (!VTN_APP_ID.equals(fwd.appId().name())) {
91 super.forward(fwd);
92 return;
93 }
samuel3b2743d2015-07-29 10:44:30 +080094 Collection<FlowRule> rules;
95 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations
96 .builder();
97
98 rules = processForward(fwd);
99 switch (fwd.op()) {
100 case ADD:
101 rules.stream().filter(rule -> rule != null)
102 .forEach(flowOpsBuilder::add);
103 break;
104 case REMOVE:
105 rules.stream().filter(rule -> rule != null)
106 .forEach(flowOpsBuilder::remove);
107 break;
108 default:
109 fail(fwd, ObjectiveError.UNKNOWN);
110 log.warn("Unknown forwarding type {}", fwd.op());
111 }
112
113 flowRuleService.apply(flowOpsBuilder
114 .build(new FlowRuleOperationsContext() {
115 @Override
116 public void onSuccess(FlowRuleOperations ops) {
117 pass(fwd);
118 }
119
120 @Override
121 public void onError(FlowRuleOperations ops) {
122 fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
123 }
124 }));
125 }
126
127 @Override
128 public void next(NextObjective nextObjective) {
CNluciusa66c3972015-09-06 20:31:29 +0800129 super.next(nextObjective);
samuel3b2743d2015-07-29 10:44:30 +0800130 }
131
lishuai4d6a0ee2015-10-19 19:05:48 +0800132 private void initializePipeline() {
133 processClassifierTable(true);
134 processMacTable(true);
135 }
136
137 private void processClassifierTable(boolean install) {
138 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
139 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
140
141 treatment.transition(MAC_TABLE);
142
143 FlowRule rule;
144 rule = DefaultFlowRule.builder().forDevice(deviceId)
145 .withSelector(selector.build())
146 .withTreatment(treatment.build())
147 .withPriority(TABLE_MISS_PRIORITY).fromApp(appId)
148 .makePermanent().forTable(CLASSIFIER_TABLE).build();
149
150 applyRules(install, rule);
151 }
152
153 private void processMacTable(boolean install) {
154 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
155 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
156
157 treatment.drop();
158
159 FlowRule rule;
160 rule = DefaultFlowRule.builder().forDevice(deviceId)
161 .withSelector(selector.build())
162 .withTreatment(treatment.build())
163 .withPriority(TABLE_MISS_PRIORITY).fromApp(appId)
164 .makePermanent().forTable(MAC_TABLE).build();
165
166 applyRules(install, rule);
167 }
168
169 private void applyRules(boolean install, FlowRule rule) {
170 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
171
172 ops = install ? ops.add(rule) : ops.remove(rule);
173 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
174 @Override
175 public void onSuccess(FlowRuleOperations ops) {
176 log.info("ONOSW provisioned " + rule.tableId() + " table");
177 }
178
179 @Override
180 public void onError(FlowRuleOperations ops) {
181 log.info("ONOSW failed to provision " + rule.tableId() + " table");
182 }
183 }));
184 }
185
samuel3b2743d2015-07-29 10:44:30 +0800186 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
187 switch (fwd.flag()) {
188 case SPECIFIC:
189 return processSpecific(fwd);
190 case VERSATILE:
191 return processVersatile(fwd);
192 default:
193 fail(fwd, ObjectiveError.UNKNOWN);
194 log.warn("Unknown forwarding flag {}", fwd.flag());
195 }
196 return Collections.emptySet();
197 }
198
199 private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
200 log.debug("Processing versatile forwarding objective");
201 return Collections.emptyList();
202 }
203
204 private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
205 log.debug("Processing specific forwarding objective");
206 TrafficSelector selector = fwd.selector();
207 TrafficTreatment tb = fwd.treatment();
208 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
209 .fromApp(fwd.appId()).withPriority(fwd.priority())
210 .forDevice(deviceId).withSelector(selector)
CNluciusa66c3972015-09-06 20:31:29 +0800211 .withTreatment(tb).makeTemporary(TIME_OUT);
212 ruleBuilder.withPriority(fwd.priority());
samuel3b2743d2015-07-29 10:44:30 +0800213 if (fwd.permanent()) {
214 ruleBuilder.makePermanent();
215 }
216 if (selector.getCriterion(Type.ETH_DST) != null
217 || tb.allInstructions().contains(Instructions.createDrop())) {
samuel3b2743d2015-07-29 10:44:30 +0800218 ruleBuilder.withTreatment(tb);
219 ruleBuilder.forTable(MAC_TABLE);
220 } else {
samuel3b2743d2015-07-29 10:44:30 +0800221 TrafficTreatment.Builder newTraffic = DefaultTrafficTreatment.builder();
222 tb.allInstructions().forEach(t -> newTraffic.add(t));
223 newTraffic.transition(MAC_TABLE);
224 ruleBuilder.withTreatment(newTraffic.build());
lishuai4d6a0ee2015-10-19 19:05:48 +0800225 ruleBuilder.forTable(CLASSIFIER_TABLE);
samuel3b2743d2015-07-29 10:44:30 +0800226 }
227 return Collections.singletonList(ruleBuilder.build());
228 }
229
230 private void fail(Objective obj, ObjectiveError error) {
231 if (obj.context().isPresent()) {
232 obj.context().get().onError(obj, error);
233 }
234 }
235
236 private void pass(Objective obj) {
237 if (obj.context().isPresent()) {
238 obj.context().get().onSuccess(obj);
239 }
240 }
241}