blob: b74b46282f3ebe3f1be18b99b13e8f083a9d0e3b [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;
sanghofb3b5012016-11-10 15:47:53 +090019import org.onlab.packet.MacAddress;
danielc8620b12015-11-30 15:50:59 +090020import 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;
sanghofb3b5012016-11-10 15:47:53 +090035import org.onosproject.net.flow.criteria.IPCriterion;
36import org.onosproject.net.flow.criteria.PortCriterion;
37import org.onosproject.net.flow.criteria.TunnelIdCriterion;
sanghofb3b5012016-11-10 15:47:53 +090038import org.onosproject.net.flow.instructions.Instruction;
danielc8620b12015-11-30 15:50:59 +090039import org.onosproject.net.flowobjective.FilteringObjective;
40import org.onosproject.net.flowobjective.FlowObjectiveStore;
41import org.onosproject.net.flowobjective.ForwardingObjective;
42import org.onosproject.net.flowobjective.NextObjective;
43import org.onosproject.net.flowobjective.Objective;
44import org.onosproject.net.flowobjective.ObjectiveError;
45import org.slf4j.Logger;
46
sanghofb3b5012016-11-10 15:47:53 +090047import java.util.Optional;
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());
danielc8620b12015-11-30 15:50:59 +090058 protected FlowObjectiveStore flowObjectiveStore;
59 protected DeviceId deviceId;
60 protected ApplicationId appId;
61 protected FlowRuleService flowRuleService;
62
Hyunsun Moon4e252f22017-02-18 02:07:49 +090063 private static final int SRC_VNI_TABLE = 0;
64 private static final int JUMP_TABLE = 1;
65 private static final int ROUTING_TABLE = 2;
66 private static final int FORWARDING_TABLE = 3;
67 private static final int DUMMY_TABLE = 10;
68 private static final int LAST_TABLE = FORWARDING_TABLE;
danielc8620b12015-11-30 15:50:59 +090069
70 private static final int DROP_PRIORITY = 0;
sanghofb3b5012016-11-10 15:47:53 +090071 private static final int HIGH_PRIORITY = 30000;
danielc8620b12015-11-30 15:50:59 +090072 private static final int TIME_OUT = 0;
sanghofb3b5012016-11-10 15:47:53 +090073 private static final String VIRTUAL_GATEWAY_MAC = "fe:00:00:00:00:02";
danielc8620b12015-11-30 15:50:59 +090074
75
76 @Override
77 public void init(DeviceId deviceId, PipelinerContext context) {
78 super.init(deviceId, context);
Hyunsun Moon4e252f22017-02-18 02:07:49 +090079 ServiceDirectory serviceDirectory = context.directory();
danielc8620b12015-11-30 15:50:59 +090080 this.deviceId = deviceId;
81
Hyunsun Moon4e252f22017-02-18 02:07:49 +090082 CoreService coreService = serviceDirectory.get(CoreService.class);
danielc8620b12015-11-30 15:50:59 +090083 flowRuleService = serviceDirectory.get(FlowRuleService.class);
84 flowObjectiveStore = context.store();
85
86 appId = coreService.registerApplication(
87 "org.onosproject.driver.OpenstackPipeline");
88
89 initializePipeline();
90 }
91
92 @Override
93 public void filter(FilteringObjective filteringObjective) {
94 super.filter(filteringObjective);
95 }
96
97 @Override
98 public void next(NextObjective nextObjective) {
99 super.next(nextObjective);
100 }
101
102 @Override
103 public void forward(ForwardingObjective forwardingObjective) {
sanghofb3b5012016-11-10 15:47:53 +0900104 FlowRule flowRule;
danielc8620b12015-11-30 15:50:59 +0900105
sanghofb3b5012016-11-10 15:47:53 +0900106 switch (forwardingObjective.flag()) {
107 case SPECIFIC:
108 flowRule = processSpecific(forwardingObjective);
danielc8620b12015-11-30 15:50:59 +0900109 break;
sanghofb3b5012016-11-10 15:47:53 +0900110 case VERSATILE:
111 flowRule = processVersatile(forwardingObjective);
danielc8620b12015-11-30 15:50:59 +0900112 break;
113 default:
114 fail(forwardingObjective, ObjectiveError.UNKNOWN);
sanghofb3b5012016-11-10 15:47:53 +0900115 log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
116 return;
danielc8620b12015-11-30 15:50:59 +0900117 }
118
sanghofb3b5012016-11-10 15:47:53 +0900119 if (forwardingObjective.op().equals(Objective.Operation.ADD)) {
120 applyRules(true, flowRule);
121 } else {
122 applyRules(false, flowRule);
123 }
danielc8620b12015-11-30 15:50:59 +0900124
danielc8620b12015-11-30 15:50:59 +0900125 }
126
127 private void initializePipeline() {
sanghoc6ae1eb2017-02-08 17:14:01 +0900128 //TODO: For now, we do not support security group feature temporarily.
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900129 connectTables(SRC_VNI_TABLE, JUMP_TABLE); // Table 0 -> Table 1
sanghofb3b5012016-11-10 15:47:53 +0900130 setupJumpTable();
danielc8620b12015-11-30 15:50:59 +0900131 }
132
sanghofb3b5012016-11-10 15:47:53 +0900133 private void connectTables(int fromTable, int toTable) {
danielc8620b12015-11-30 15:50:59 +0900134 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
135 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
136
sanghofb3b5012016-11-10 15:47:53 +0900137 treatment.transition(toTable);
138
139 FlowRule flowRule = DefaultFlowRule.builder()
140 .forDevice(deviceId)
141 .withSelector(selector.build())
142 .withTreatment(treatment.build())
143 .withPriority(DROP_PRIORITY)
144 .fromApp(appId)
145 .makePermanent()
146 .forTable(fromTable)
147 .build();
148
149 applyRules(true, flowRule);
150 }
151
sanghofb3b5012016-11-10 15:47:53 +0900152 private void setupJumpTable() {
153 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
154 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
155
156 selector.matchEthDst(MacAddress.valueOf(VIRTUAL_GATEWAY_MAC));
157 treatment.transition(ROUTING_TABLE);
158
159 FlowRule flowRule = DefaultFlowRule.builder()
160 .forDevice(deviceId)
161 .withSelector(selector.build())
162 .withTreatment(treatment.build())
163 .withPriority(HIGH_PRIORITY)
164 .fromApp(appId)
165 .makePermanent()
166 .forTable(JUMP_TABLE)
167 .build();
168
169 applyRules(true, flowRule);
170
171 selector = DefaultTrafficSelector.builder();
172 treatment = DefaultTrafficTreatment.builder();
173
danielc8620b12015-11-30 15:50:59 +0900174 treatment.transition(FORWARDING_TABLE);
175
sanghofb3b5012016-11-10 15:47:53 +0900176 flowRule = DefaultFlowRule.builder()
danielc8620b12015-11-30 15:50:59 +0900177 .forDevice(deviceId)
178 .withSelector(selector.build())
179 .withTreatment(treatment.build())
180 .withPriority(DROP_PRIORITY)
181 .fromApp(appId)
182 .makePermanent()
sanghofb3b5012016-11-10 15:47:53 +0900183 .forTable(JUMP_TABLE)
danielc8620b12015-11-30 15:50:59 +0900184 .build();
185
sanghofb3b5012016-11-10 15:47:53 +0900186 applyRules(true, flowRule);
sangho90088532016-02-25 18:06:12 +0900187 }
188
danielc8620b12015-11-30 15:50:59 +0900189 private void applyRules(boolean install, FlowRule flowRule) {
190 FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
191
192 flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
193
194 flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
195 @Override
196 public void onSuccess(FlowRuleOperations ops) {
197 log.debug("Provisioned vni or forwarding table");
198 }
199
200 @Override
201 public void onError(FlowRuleOperations ops) {
202 log.debug("Failed to privision vni or forwarding table");
203 }
204 }));
205 }
206
sanghofb3b5012016-11-10 15:47:53 +0900207 private FlowRule processVersatile(ForwardingObjective forwardingObjective) {
danielc8620b12015-11-30 15:50:59 +0900208 log.debug("Processing versatile forwarding objective");
209
210 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
211 .forDevice(deviceId)
212 .withSelector(forwardingObjective.selector())
213 .withTreatment(forwardingObjective.treatment())
214 .withPriority(forwardingObjective.priority())
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900215 .fromApp(forwardingObjective.appId())
216 .forTable(SRC_VNI_TABLE);
danielc8620b12015-11-30 15:50:59 +0900217
218 if (forwardingObjective.permanent()) {
219 ruleBuilder.makePermanent();
220 } else {
221 ruleBuilder.makeTemporary(TIME_OUT);
222 }
223
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900224 return ruleBuilder.build();
danielc8620b12015-11-30 15:50:59 +0900225 }
226
sanghofb3b5012016-11-10 15:47:53 +0900227 private FlowRule processSpecific(ForwardingObjective forwardingObjective) {
danielc8620b12015-11-30 15:50:59 +0900228 log.debug("Processing specific forwarding objective");
229
sanghofb3b5012016-11-10 15:47:53 +0900230 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
sanghofb3b5012016-11-10 15:47:53 +0900231 Optional<Instruction> group = forwardingObjective.treatment().immediate().stream()
232 .filter(i -> i.type() == Instruction.Type.GROUP).findAny();
233 int tableType = tableType(forwardingObjective);
234 if (tableType != LAST_TABLE && !group.isPresent()) {
235 treatment.transition(nextTable(tableType));
236 }
237 forwardingObjective.treatment().allInstructions().stream()
238 .filter(i -> i.type() != Instruction.Type.NOACTION).forEach(treatment::add);
239
danielc8620b12015-11-30 15:50:59 +0900240 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
241 .forDevice(deviceId)
242 .withSelector(forwardingObjective.selector())
sanghofb3b5012016-11-10 15:47:53 +0900243 .withTreatment(treatment.build())
danielc8620b12015-11-30 15:50:59 +0900244 .withPriority(forwardingObjective.priority())
sanghofb3b5012016-11-10 15:47:53 +0900245 .fromApp(forwardingObjective.appId())
246 .forTable(tableType);
danielc8620b12015-11-30 15:50:59 +0900247
248 if (forwardingObjective.permanent()) {
249 ruleBuilder.makePermanent();
250 } else {
251 ruleBuilder.makeTemporary(TIME_OUT);
252 }
253
sanghofb3b5012016-11-10 15:47:53 +0900254 return ruleBuilder.build();
danielc8620b12015-11-30 15:50:59 +0900255 }
256
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900257 private int tableType(ForwardingObjective fo) {
danielc8620b12015-11-30 15:50:59 +0900258
sanghofb3b5012016-11-10 15:47:53 +0900259 IPCriterion ipSrc = (IPCriterion) fo.selector().getCriterion(Criterion.Type.IPV4_SRC);
260 IPCriterion ipDst = (IPCriterion) fo.selector().getCriterion(Criterion.Type.IPV4_DST);
261 TunnelIdCriterion tunnelId =
262 (TunnelIdCriterion) fo.selector().getCriterion(Criterion.Type.TUNNEL_ID);
263 PortCriterion inPort = (PortCriterion) fo.selector().getCriterion(Criterion.Type.IN_PORT);
264 Optional<Instruction> output = fo.treatment().immediate().stream()
265 .filter(i -> i.type() == Instruction.Type.OUTPUT).findAny();
266 Optional<Instruction> group = fo.treatment().immediate().stream()
267 .filter(i -> i.type() == Instruction.Type.GROUP).findAny();
268
269 // TODO: Add the Connection Tracking Table
270 if (inPort != null) {
271 return SRC_VNI_TABLE;
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900272 } else if ((tunnelId != null && ipSrc != null && ipDst != null) ||
273 (ipSrc != null && group.isPresent())) {
sanghofb3b5012016-11-10 15:47:53 +0900274 return ROUTING_TABLE;
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900275 } else if (output.isPresent() || (ipDst != null && group.isPresent())) {
276 return FORWARDING_TABLE;
sanghofb3b5012016-11-10 15:47:53 +0900277 }
278
279 return DUMMY_TABLE;
280 }
281
Hyunsun Moon4e252f22017-02-18 02:07:49 +0900282 private int nextTable(int baseTable) {
sanghofb3b5012016-11-10 15:47:53 +0900283 return baseTable + 1;
danielc8620b12015-11-30 15:50:59 +0900284 }
285
286 private void fail(Objective obj, ObjectiveError error) {
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800287 obj.context().ifPresent(context -> context.onError(obj, error));
danielc8620b12015-11-30 15:50:59 +0900288 }
289}
290