blob: 4d1284b57a67336d7e5698fce9ac4ff26b33d696 [file] [log] [blame]
alshabibaebe7752015-04-07 17:45:42 -07001/*
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
alshabib2a441c62015-04-13 18:39:38 -070018import com.google.common.cache.Cache;
19import com.google.common.cache.CacheBuilder;
20import com.google.common.cache.RemovalCause;
21import com.google.common.cache.RemovalNotification;
alshabibaebe7752015-04-07 17:45:42 -070022import org.onlab.osgi.ServiceDirectory;
23import org.onlab.packet.Ethernet;
24import org.onlab.packet.MacAddress;
25import org.onlab.packet.VlanId;
alshabib2a441c62015-04-13 18:39:38 -070026import org.onlab.util.KryoNamespace;
alshabibaebe7752015-04-07 17:45:42 -070027import org.onosproject.core.ApplicationId;
28import org.onosproject.core.CoreService;
29import org.onosproject.net.DeviceId;
alshabib2a441c62015-04-13 18:39:38 -070030import org.onosproject.net.behaviour.NextGroup;
alshabibaebe7752015-04-07 17:45:42 -070031import org.onosproject.net.behaviour.Pipeliner;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070032import org.onosproject.net.behaviour.PipelinerContext;
Thomas Vachuskafacc3f52015-04-10 08:58:36 -070033import org.onosproject.net.driver.AbstractHandlerBehaviour;
alshabibaebe7752015-04-07 17:45:42 -070034import org.onosproject.net.flow.DefaultFlowRule;
35import org.onosproject.net.flow.DefaultTrafficSelector;
36import org.onosproject.net.flow.DefaultTrafficTreatment;
37import org.onosproject.net.flow.FlowRule;
38import org.onosproject.net.flow.FlowRuleOperations;
39import org.onosproject.net.flow.FlowRuleOperationsContext;
40import org.onosproject.net.flow.FlowRuleService;
41import org.onosproject.net.flow.TrafficSelector;
42import org.onosproject.net.flow.TrafficTreatment;
alshabib910aff12015-04-09 16:55:57 -070043import org.onosproject.net.flow.criteria.Criteria;
44import org.onosproject.net.flow.criteria.Criterion;
alshabibaebe7752015-04-07 17:45:42 -070045import org.onosproject.net.flowobjective.FilteringObjective;
alshabib2a441c62015-04-13 18:39:38 -070046import org.onosproject.net.flowobjective.FlowObjectiveStore;
alshabibaebe7752015-04-07 17:45:42 -070047import org.onosproject.net.flowobjective.ForwardingObjective;
48import org.onosproject.net.flowobjective.NextObjective;
alshabib910aff12015-04-09 16:55:57 -070049import org.onosproject.net.flowobjective.Objective;
alshabib2a441c62015-04-13 18:39:38 -070050import org.onosproject.net.flowobjective.ObjectiveError;
51import org.onosproject.net.group.DefaultGroupBucket;
52import org.onosproject.net.group.DefaultGroupDescription;
53import org.onosproject.net.group.DefaultGroupKey;
54import org.onosproject.net.group.Group;
55import org.onosproject.net.group.GroupBucket;
56import org.onosproject.net.group.GroupBuckets;
57import org.onosproject.net.group.GroupDescription;
58import org.onosproject.net.group.GroupEvent;
59import org.onosproject.net.group.GroupKey;
60import org.onosproject.net.group.GroupListener;
61import org.onosproject.net.group.GroupService;
alshabibaebe7752015-04-07 17:45:42 -070062import org.slf4j.Logger;
63
64import java.util.Collection;
alshabib2a441c62015-04-13 18:39:38 -070065import java.util.Collections;
66import java.util.Set;
67import java.util.concurrent.Executors;
68import java.util.concurrent.ScheduledExecutorService;
69import java.util.concurrent.TimeUnit;
70import java.util.stream.Collectors;
alshabibaebe7752015-04-07 17:45:42 -070071
alshabib2a441c62015-04-13 18:39:38 -070072import static org.onlab.util.Tools.groupedThreads;
alshabibaebe7752015-04-07 17:45:42 -070073import static org.slf4j.LoggerFactory.getLogger;
74
75/**
alshabib2a441c62015-04-13 18:39:38 -070076 * OpenvSwitch emulation of the Corsa pipeline handler.
alshabibaebe7752015-04-07 17:45:42 -070077 */
Thomas Vachuskafacc3f52015-04-10 08:58:36 -070078public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
alshabibaebe7752015-04-07 17:45:42 -070079
alshabibd17abc22015-04-21 18:26:35 -070080
81
Saurav Das3ea46622015-04-22 14:01:34 -070082 protected static final int MAC_TABLE = 0;
alshabibd17abc22015-04-21 18:26:35 -070083 protected static final int VLAN_MPLS_TABLE = 1;
84 protected static final int VLAN_TABLE = 2;
85 //protected static final int MPLS_TABLE = 3;
86 protected static final int ETHER_TABLE = 4;
87 protected static final int COS_MAP_TABLE = 5;
88 protected static final int FIB_TABLE = 6;
89 protected static final int LOCAL_TABLE = 9;
90
91
alshabibaebe7752015-04-07 17:45:42 -070092 private static final int CONTROLLER_PRIORITY = 255;
93 private static final int DROP_PRIORITY = 0;
94 private static final int HIGHEST_PRIORITY = 0xffff;
95
96 private final Logger log = getLogger(getClass());
97
98 private ServiceDirectory serviceDirectory;
99 private FlowRuleService flowRuleService;
100 private CoreService coreService;
alshabib2a441c62015-04-13 18:39:38 -0700101 private GroupService groupService;
102 private FlowObjectiveStore flowObjectiveStore;
alshabibaebe7752015-04-07 17:45:42 -0700103 private DeviceId deviceId;
104 private ApplicationId appId;
105
alshabib2a441c62015-04-13 18:39:38 -0700106 private KryoNamespace appKryo = new KryoNamespace.Builder()
107 .register(GroupKey.class)
108 .register(DefaultGroupKey.class)
109 .register(CorsaGroup.class)
110 .register(byte[].class)
111 .build();
112
113 private Cache<GroupKey, NextObjective> pendingGroups;
114
115 private ScheduledExecutorService groupChecker =
116 Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
117 "ovs-corsa-%d"));
118
alshabibaebe7752015-04-07 17:45:42 -0700119 @Override
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700120 public void init(DeviceId deviceId, PipelinerContext context) {
121 this.serviceDirectory = context.directory();
alshabibaebe7752015-04-07 17:45:42 -0700122 this.deviceId = deviceId;
123
alshabib2a441c62015-04-13 18:39:38 -0700124 pendingGroups = CacheBuilder.newBuilder()
125 .expireAfterWrite(20, TimeUnit.SECONDS)
126 .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
127 if (notification.getCause() == RemovalCause.EXPIRED) {
128 fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
129 }
130 }).build();
131
132 groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
alshabibaebe7752015-04-07 17:45:42 -0700133
134 coreService = serviceDirectory.get(CoreService.class);
135 flowRuleService = serviceDirectory.get(FlowRuleService.class);
alshabib2a441c62015-04-13 18:39:38 -0700136 groupService = serviceDirectory.get(GroupService.class);
137 flowObjectiveStore = context.store();
138
139 groupService.addListener(new InnerGroupListener());
alshabibaebe7752015-04-07 17:45:42 -0700140
141 appId = coreService.registerApplication(
142 "org.onosproject.driver.OVSCorsaPipeline");
143
144 pushDefaultRules();
alshabibaebe7752015-04-07 17:45:42 -0700145 }
146
147 @Override
alshabib2a441c62015-04-13 18:39:38 -0700148 public void filter(FilteringObjective filteringObjective) {
149 if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
150 processFilter(filteringObjective,
151 filteringObjective.op() == Objective.Operation.ADD,
152 filteringObjective.appId());
153 } else {
154 fail(filteringObjective, ObjectiveError.UNSUPPORTED);
155 }
156 }
alshabib910aff12015-04-09 16:55:57 -0700157
alshabib2a441c62015-04-13 18:39:38 -0700158 @Override
159 public void forward(ForwardingObjective fwd) {
160 Collection<FlowRule> rules;
161 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
162
163 rules = processForward(fwd);
164 switch (fwd.op()) {
165 case ADD:
166 rules.stream()
167 .filter(rule -> rule != null)
168 .forEach(flowBuilder::add);
169 break;
170 case REMOVE:
171 rules.stream()
172 .filter(rule -> rule != null)
173 .forEach(flowBuilder::remove);
174 break;
175 default:
176 fail(fwd, ObjectiveError.UNKNOWN);
177 log.warn("Unknown forwarding type {}", fwd.op());
178 }
179
180
181 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
182 @Override
183 public void onSuccess(FlowRuleOperations ops) {
184 pass(fwd);
185 }
186
187 @Override
188 public void onError(FlowRuleOperations ops) {
189 fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
190 }
191 }));
alshabib910aff12015-04-09 16:55:57 -0700192
193 }
194
alshabib2a441c62015-04-13 18:39:38 -0700195 @Override
196 public void next(NextObjective nextObjective) {
197 switch (nextObjective.type()) {
198 case SIMPLE:
199 Collection<TrafficTreatment> treatments = nextObjective.next();
200 if (treatments.size() == 1) {
201 TrafficTreatment treatment = treatments.iterator().next();
202 GroupBucket bucket =
203 DefaultGroupBucket.createIndirectGroupBucket(treatment);
204 final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
205 GroupDescription groupDescription
206 = new DefaultGroupDescription(deviceId,
207 GroupDescription.Type.INDIRECT,
208 new GroupBuckets(Collections
209 .singletonList(bucket)),
210 key,
211 nextObjective.appId());
212 groupService.addGroup(groupDescription);
213 pendingGroups.put(key, nextObjective);
214 }
215 break;
216 case HASHED:
217 case BROADCAST:
218 case FAILOVER:
219 fail(nextObjective, ObjectiveError.UNSUPPORTED);
220 log.warn("Unsupported next objective type {}", nextObjective.type());
221 break;
222 default:
223 fail(nextObjective, ObjectiveError.UNKNOWN);
224 log.warn("Unknown next objective type {}", nextObjective.type());
225 }
226
227 }
228
229 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
230 switch (fwd.flag()) {
231 case SPECIFIC:
232 return processSpecific(fwd);
233 case VERSATILE:
234 return processVersatile(fwd);
235 default:
236 fail(fwd, ObjectiveError.UNKNOWN);
237 log.warn("Unknown forwarding flag {}", fwd.flag());
238 }
239 return Collections.emptySet();
240 }
241
242 private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
243 fail(fwd, ObjectiveError.UNSUPPORTED);
244 return Collections.emptySet();
245 }
246
247 private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
248 log.warn("Processing specific");
249 TrafficSelector selector = fwd.selector();
250 Criteria.EthTypeCriterion ethType =
251 (Criteria.EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
252 if (ethType == null || ethType.ethType() != Ethernet.TYPE_IPV4) {
253 fail(fwd, ObjectiveError.UNSUPPORTED);
254 return Collections.emptySet();
255 }
256
257 TrafficSelector filteredSelector =
258 DefaultTrafficSelector.builder()
259 .matchEthType(Ethernet.TYPE_IPV4)
260 .matchIPDst(
261 ((Criteria.IPCriterion)
262 selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
263 .build();
264
265 NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
266
267 GroupKey key = appKryo.deserialize(next.data());
268
269 Group group = groupService.getGroup(deviceId, key);
270
271 if (group == null) {
272 log.warn("The group left!");
273 fail(fwd, ObjectiveError.GROUPMISSING);
274 return Collections.emptySet();
275 }
276
277 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
278 .group(group.id())
279 .build();
280
alshabibd17abc22015-04-21 18:26:35 -0700281 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
282 .fromApp(fwd.appId())
283 .withPriority(fwd.priority())
284 .forDevice(deviceId)
285 .withSelector(filteredSelector)
286 .withTreatment(treatment);
287
288 if (fwd.permanent()) {
289 ruleBuilder.makePermanent();
290 } else {
291 ruleBuilder.makeTemporary(fwd.timeout());
292 }
293
294 ruleBuilder.forTable(FIB_TABLE);
295
296
297 return Collections.singletonList(ruleBuilder.build());
alshabib2a441c62015-04-13 18:39:38 -0700298
299 }
300
301 private void processFilter(FilteringObjective filt, boolean install,
alshabib910aff12015-04-09 16:55:57 -0700302 ApplicationId applicationId) {
Saurav Dascfd63d22015-04-13 16:08:24 -0700303 // This driver only processes filtering criteria defined with switch
304 // ports as the key
alshabib2a441c62015-04-13 18:39:38 -0700305 Criteria.PortCriterion p;
Saurav Dascfd63d22015-04-13 16:08:24 -0700306 if (!filt.key().equals(Criteria.dummy()) &&
307 filt.key().type() == Criterion.Type.IN_PORT) {
308 p = (Criteria.PortCriterion) filt.key();
309 } else {
310 log.warn("No key defined in filtering objective from app: {}. Not"
311 + "processing filtering objective", applicationId);
alshabib2a441c62015-04-13 18:39:38 -0700312 fail(filt, ObjectiveError.UNKNOWN);
313 return;
alshabib910aff12015-04-09 16:55:57 -0700314 }
Saurav Dascfd63d22015-04-13 16:08:24 -0700315 // convert filtering conditions for switch-intfs into flowrules
316 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
317 for (Criterion c : filt.conditions()) {
318 if (c.type() == Criterion.Type.ETH_DST) {
319 Criteria.EthCriterion e = (Criteria.EthCriterion) c;
320 log.debug("adding rule for MAC: {}", e.mac());
321 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
322 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
323 selector.matchEthDst(e.mac());
alshabibd17abc22015-04-21 18:26:35 -0700324 treatment.transition(VLAN_MPLS_TABLE);
325 FlowRule rule = DefaultFlowRule.builder()
326 .forDevice(deviceId)
327 .withSelector(selector.build())
328 .withTreatment(treatment.build())
329 .withPriority(CONTROLLER_PRIORITY)
330 .fromApp(applicationId)
331 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700332 .forTable(MAC_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700333 ops = install ? ops.add(rule) : ops.remove(rule);
334 } else if (c.type() == Criterion.Type.VLAN_VID) {
335 Criteria.VlanIdCriterion v = (Criteria.VlanIdCriterion) c;
336 log.debug("adding rule for VLAN: {}", v.vlanId());
337 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
338 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
339 selector.matchVlanId(v.vlanId());
340 selector.matchInPort(p.port());
alshabibd17abc22015-04-21 18:26:35 -0700341 treatment.transition(ETHER_TABLE);
Saurav Dascfd63d22015-04-13 16:08:24 -0700342 treatment.deferred().popVlan();
alshabibd17abc22015-04-21 18:26:35 -0700343 FlowRule rule = DefaultFlowRule.builder()
344 .forDevice(deviceId)
345 .withSelector(selector.build())
346 .withTreatment(treatment.build())
347 .withPriority(CONTROLLER_PRIORITY)
348 .fromApp(applicationId)
349 .makePermanent()
350 .forTable(VLAN_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700351 ops = install ? ops.add(rule) : ops.remove(rule);
352 } else if (c.type() == Criterion.Type.IPV4_DST) {
353 Criteria.IPCriterion ip = (Criteria.IPCriterion) c;
354 log.debug("adding rule for IP: {}", ip.ip());
355 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
356 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
357 selector.matchEthType(Ethernet.TYPE_IPV4);
358 selector.matchIPDst(ip.ip());
alshabibd17abc22015-04-21 18:26:35 -0700359 treatment.transition(LOCAL_TABLE);
360 FlowRule rule = DefaultFlowRule.builder()
361 .forDevice(deviceId)
362 .withSelector(selector.build())
363 .withTreatment(treatment.build())
364 .withPriority(HIGHEST_PRIORITY)
365 .fromApp(applicationId)
366 .makePermanent()
367 .forTable(FIB_TABLE).build();
368
Saurav Dascfd63d22015-04-13 16:08:24 -0700369 ops = install ? ops.add(rule) : ops.remove(rule);
370 } else {
371 log.warn("Driver does not currently process filtering condition"
372 + " of type: {}", c.type());
alshabib2a441c62015-04-13 18:39:38 -0700373 fail(filt, ObjectiveError.UNSUPPORTED);
Saurav Dascfd63d22015-04-13 16:08:24 -0700374 }
375 }
376 // apply filtering flow rules
377 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
378 @Override
379 public void onSuccess(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700380 pass(filt);
Saurav Das3ea46622015-04-22 14:01:34 -0700381 log.info("Applied filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700382 }
383
384 @Override
385 public void onError(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700386 fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
Saurav Das3ea46622015-04-22 14:01:34 -0700387 log.info("Failed to apply filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700388 }
389 }));
alshabibaebe7752015-04-07 17:45:42 -0700390 }
391
alshabib2a441c62015-04-13 18:39:38 -0700392 private void pass(Objective obj) {
393 if (obj.context().isPresent()) {
394 obj.context().get().onSuccess(obj);
395 }
alshabibaebe7752015-04-07 17:45:42 -0700396 }
397
alshabib2a441c62015-04-13 18:39:38 -0700398 private void fail(Objective obj, ObjectiveError error) {
399 if (obj.context().isPresent()) {
400 obj.context().get().onError(obj, error);
401 }
alshabibaebe7752015-04-07 17:45:42 -0700402 }
403
alshabibaebe7752015-04-07 17:45:42 -0700404 private void pushDefaultRules() {
Saurav Das3ea46622015-04-22 14:01:34 -0700405 processMacTable(true);
406 processVlanMplsTable(true);
407 processVlanTable(true);
408 processEtherTable(true);
409 processCosTable(true);
410 processFibTable(true);
411 processLocalTable(true);
alshabibaebe7752015-04-07 17:45:42 -0700412 }
413
Saurav Das3ea46622015-04-22 14:01:34 -0700414 private void processMacTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700415 TrafficSelector.Builder selector;
416 TrafficTreatment.Builder treatment;
417
418 // Bcast rule
419 selector = DefaultTrafficSelector.builder();
420 treatment = DefaultTrafficTreatment.builder();
421
422 selector.matchEthDst(MacAddress.BROADCAST);
alshabibd17abc22015-04-21 18:26:35 -0700423 treatment.transition(VLAN_MPLS_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700424
alshabibd17abc22015-04-21 18:26:35 -0700425 FlowRule rule = DefaultFlowRule.builder()
426 .forDevice(deviceId)
427 .withSelector(selector.build())
428 .withTreatment(treatment.build())
429 .withPriority(CONTROLLER_PRIORITY)
430 .fromApp(appId)
431 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700432 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700433
alshabibaebe7752015-04-07 17:45:42 -0700434
435 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
436
437 ops = install ? ops.add(rule) : ops.remove(rule);
438
439
alshabibaebe7752015-04-07 17:45:42 -0700440 //Drop rule
441 selector = DefaultTrafficSelector.builder();
442 treatment = DefaultTrafficTreatment.builder();
443
444 treatment.drop();
445
alshabibd17abc22015-04-21 18:26:35 -0700446 rule = DefaultFlowRule.builder()
447 .forDevice(deviceId)
448 .withSelector(selector.build())
449 .withTreatment(treatment.build())
450 .withPriority(DROP_PRIORITY)
451 .fromApp(appId)
452 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700453 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700454
alshabibaebe7752015-04-07 17:45:42 -0700455
456 ops = install ? ops.add(rule) : ops.remove(rule);
457
458 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
459 @Override
460 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700461 log.info("Provisioned mac table");
alshabibaebe7752015-04-07 17:45:42 -0700462 }
463
464 @Override
465 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700466 log.info("Failed to provision mac table");
alshabibaebe7752015-04-07 17:45:42 -0700467 }
468 }));
469
470 }
471
Saurav Das3ea46622015-04-22 14:01:34 -0700472 private void processVlanMplsTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700473 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
474 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
475 .builder();
476 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
477 FlowRule rule;
478
479 selector.matchVlanId(VlanId.ANY);
alshabibd17abc22015-04-21 18:26:35 -0700480 treatment.transition(VLAN_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700481
alshabibd17abc22015-04-21 18:26:35 -0700482 rule = DefaultFlowRule.builder()
483 .forDevice(deviceId)
484 .withSelector(selector.build())
485 .withTreatment(treatment.build())
486 .withPriority(CONTROLLER_PRIORITY)
487 .fromApp(appId)
488 .makePermanent()
489 .forTable(VLAN_MPLS_TABLE).build();
490
alshabibaebe7752015-04-07 17:45:42 -0700491
492 ops = install ? ops.add(rule) : ops.remove(rule);
493
494 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
495 @Override
496 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700497 log.info("Provisioned vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700498 }
499
500 @Override
501 public void onError(FlowRuleOperations ops) {
502 log.info(
Saurav Das3ea46622015-04-22 14:01:34 -0700503 "Failed to provision vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700504 }
505 }));
506
507 }
508
Saurav Das3ea46622015-04-22 14:01:34 -0700509 private void processVlanTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700510 TrafficSelector.Builder selector;
511 TrafficTreatment.Builder treatment;
512 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
513 FlowRule rule;
514
515
alshabibaebe7752015-04-07 17:45:42 -0700516 //Drop rule
517 selector = DefaultTrafficSelector.builder();
518 treatment = DefaultTrafficTreatment.builder();
519
520 treatment.drop();
521
alshabibd17abc22015-04-21 18:26:35 -0700522 rule = DefaultFlowRule.builder()
523 .forDevice(deviceId)
524 .withSelector(selector.build())
525 .withTreatment(treatment.build())
526 .withPriority(DROP_PRIORITY)
527 .fromApp(appId)
528 .makePermanent()
529 .forTable(VLAN_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700530
531 ops = install ? ops.add(rule) : ops.remove(rule);
532
533 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
534 @Override
535 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700536 log.info("Provisioned vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700537 }
538
539 @Override
540 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700541 log.info("Failed to provision vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700542 }
543 }));
544 }
545
Saurav Das3ea46622015-04-22 14:01:34 -0700546 private void processEtherTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700547 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
548 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
549 .builder();
550 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
551 FlowRule rule;
552
553 selector.matchEthType(Ethernet.TYPE_ARP);
554 treatment.punt();
555
alshabibd17abc22015-04-21 18:26:35 -0700556 rule = DefaultFlowRule.builder()
557 .forDevice(deviceId)
558 .withSelector(selector.build())
559 .withTreatment(treatment.build())
560 .withPriority(CONTROLLER_PRIORITY)
561 .fromApp(appId)
562 .makePermanent()
563 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700564
565 ops = install ? ops.add(rule) : ops.remove(rule);
566
567 selector = DefaultTrafficSelector.builder();
568 treatment = DefaultTrafficTreatment.builder();
569
570 selector.matchEthType(Ethernet.TYPE_IPV4);
alshabibd17abc22015-04-21 18:26:35 -0700571 treatment.transition(COS_MAP_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700572
alshabibd17abc22015-04-21 18:26:35 -0700573 rule = DefaultFlowRule.builder()
574 .forDevice(deviceId)
575 .withPriority(CONTROLLER_PRIORITY)
576 .withSelector(selector.build())
577 .withTreatment(treatment.build())
578 .fromApp(appId)
579 .makePermanent()
580 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700581
582 ops = install ? ops.add(rule) : ops.remove(rule);
583
584 //Drop rule
585 selector = DefaultTrafficSelector.builder();
586 treatment = DefaultTrafficTreatment.builder();
587
588 treatment.drop();
589
alshabibd17abc22015-04-21 18:26:35 -0700590 rule = DefaultFlowRule.builder()
591 .forDevice(deviceId)
592 .withSelector(selector.build())
593 .withTreatment(treatment.build())
594 .withPriority(DROP_PRIORITY)
595 .fromApp(appId)
596 .makePermanent()
597 .forTable(ETHER_TABLE).build();
598
alshabibaebe7752015-04-07 17:45:42 -0700599
600 ops = install ? ops.add(rule) : ops.remove(rule);
601
602 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
603 @Override
604 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700605 log.info("Provisioned ether table");
alshabibaebe7752015-04-07 17:45:42 -0700606 }
607
608 @Override
609 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700610 log.info("Failed to provision ether table");
alshabibaebe7752015-04-07 17:45:42 -0700611 }
612 }));
613
614 }
615
Saurav Das3ea46622015-04-22 14:01:34 -0700616 private void processCosTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700617 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
618 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
619 .builder();
620 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
621 FlowRule rule;
622
alshabibd17abc22015-04-21 18:26:35 -0700623 treatment.transition(FIB_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700624
alshabibd17abc22015-04-21 18:26:35 -0700625 rule = DefaultFlowRule.builder()
626 .forDevice(deviceId)
627 .withSelector(selector.build())
628 .withTreatment(treatment.build())
629 .withPriority(DROP_PRIORITY)
630 .fromApp(appId)
631 .makePermanent()
632 .forTable(COS_MAP_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700633
634 ops = install ? ops.add(rule) : ops.remove(rule);
635
636 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
637 @Override
638 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700639 log.info("Provisioned cos table");
alshabibaebe7752015-04-07 17:45:42 -0700640 }
641
642 @Override
643 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700644 log.info("Failed to provision cos table");
alshabibaebe7752015-04-07 17:45:42 -0700645 }
646 }));
647
648 }
649
Saurav Das3ea46622015-04-22 14:01:34 -0700650 private void processFibTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700651 TrafficSelector.Builder selector;
652 TrafficTreatment.Builder treatment;
653 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
654 FlowRule rule;
655
656 //Drop rule
657 selector = DefaultTrafficSelector.builder();
658 treatment = DefaultTrafficTreatment.builder();
659
660 treatment.drop();
661
alshabibd17abc22015-04-21 18:26:35 -0700662 rule = DefaultFlowRule.builder()
663 .forDevice(deviceId)
664 .withSelector(selector.build())
665 .withTreatment(treatment.build())
666 .withPriority(DROP_PRIORITY)
667 .fromApp(appId)
668 .makePermanent()
669 .forTable(FIB_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700670
671 ops = install ? ops.add(rule) : ops.remove(rule);
672
673 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
674 @Override
675 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700676 log.info("Provisioned FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700677 }
678
679 @Override
680 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700681 log.info("Failed to provision FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700682 }
683 }));
684 }
685
Saurav Das3ea46622015-04-22 14:01:34 -0700686 private void processLocalTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700687 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
688 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
689 .builder();
690 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
691 FlowRule rule;
692
693 treatment.punt();
694
alshabibd17abc22015-04-21 18:26:35 -0700695 rule = DefaultFlowRule.builder()
696 .forDevice(deviceId)
697 .withSelector(selector.build())
698 .withTreatment(treatment.build())
699 .withPriority(CONTROLLER_PRIORITY)
700 .fromApp(appId)
701 .makePermanent()
702 .forTable(LOCAL_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700703
704 ops = install ? ops.add(rule) : ops.remove(rule);
705
706 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
707 @Override
708 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700709 log.info("Provisioned Local table");
alshabibaebe7752015-04-07 17:45:42 -0700710 }
711
712 @Override
713 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700714 log.info("Failed to provision Local table");
alshabibaebe7752015-04-07 17:45:42 -0700715 }
716 }));
717 }
718
alshabib2a441c62015-04-13 18:39:38 -0700719 private class InnerGroupListener implements GroupListener {
720 @Override
721 public void event(GroupEvent event) {
722 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
723 GroupKey key = event.subject().appCookie();
724
725 NextObjective obj = pendingGroups.getIfPresent(key);
726 if (obj != null) {
727 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
728 pass(obj);
729 pendingGroups.invalidate(key);
730 }
731 }
732 }
733 }
734
735
736 private class GroupChecker implements Runnable {
737
738 @Override
739 public void run() {
740 Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
741 .filter(key -> groupService.getGroup(deviceId, key) != null)
742 .collect(Collectors.toSet());
743
744 keys.stream().forEach(key -> {
745 NextObjective obj = pendingGroups.getIfPresent(key);
746 if (obj == null) {
747 return;
748 }
749 pass(obj);
750 pendingGroups.invalidate(key);
Saurav Das3ea46622015-04-22 14:01:34 -0700751 log.info("Heard back from group service for group {}", obj.id());
alshabib2a441c62015-04-13 18:39:38 -0700752 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
753 });
754 }
755 }
756
757 private class CorsaGroup implements NextGroup {
758
759 private final GroupKey key;
760
761 public CorsaGroup(GroupKey key) {
762 this.key = key;
763 }
764
765 public GroupKey key() {
766 return key;
767 }
768
769 @Override
770 public byte[] data() {
771 return appKryo.serialize(key);
772 }
773
774 }
alshabibaebe7752015-04-07 17:45:42 -0700775}