blob: d56e7fa7fdbf62cceecf486c01e8b44b164d38d7 [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;
Saurav Das3d038262015-04-23 12:36:58 -070022
alshabibaebe7752015-04-07 17:45:42 -070023import org.onlab.osgi.ServiceDirectory;
24import org.onlab.packet.Ethernet;
Saurav Das3d038262015-04-23 12:36:58 -070025import org.onlab.packet.IPv4;
alshabibaebe7752015-04-07 17:45:42 -070026import org.onlab.packet.MacAddress;
27import org.onlab.packet.VlanId;
alshabib2a441c62015-04-13 18:39:38 -070028import org.onlab.util.KryoNamespace;
alshabibaebe7752015-04-07 17:45:42 -070029import org.onosproject.core.ApplicationId;
30import org.onosproject.core.CoreService;
31import org.onosproject.net.DeviceId;
alshabib2a441c62015-04-13 18:39:38 -070032import org.onosproject.net.behaviour.NextGroup;
alshabibaebe7752015-04-07 17:45:42 -070033import org.onosproject.net.behaviour.Pipeliner;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070034import org.onosproject.net.behaviour.PipelinerContext;
Thomas Vachuskafacc3f52015-04-10 08:58:36 -070035import org.onosproject.net.driver.AbstractHandlerBehaviour;
alshabibaebe7752015-04-07 17:45:42 -070036import org.onosproject.net.flow.DefaultFlowRule;
37import org.onosproject.net.flow.DefaultTrafficSelector;
38import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.FlowRule;
40import org.onosproject.net.flow.FlowRuleOperations;
41import org.onosproject.net.flow.FlowRuleOperationsContext;
42import org.onosproject.net.flow.FlowRuleService;
43import org.onosproject.net.flow.TrafficSelector;
44import org.onosproject.net.flow.TrafficTreatment;
alshabib910aff12015-04-09 16:55:57 -070045import org.onosproject.net.flow.criteria.Criteria;
46import org.onosproject.net.flow.criteria.Criterion;
alshabibaebe7752015-04-07 17:45:42 -070047import org.onosproject.net.flowobjective.FilteringObjective;
alshabib2a441c62015-04-13 18:39:38 -070048import org.onosproject.net.flowobjective.FlowObjectiveStore;
alshabibaebe7752015-04-07 17:45:42 -070049import org.onosproject.net.flowobjective.ForwardingObjective;
50import org.onosproject.net.flowobjective.NextObjective;
alshabib910aff12015-04-09 16:55:57 -070051import org.onosproject.net.flowobjective.Objective;
alshabib2a441c62015-04-13 18:39:38 -070052import org.onosproject.net.flowobjective.ObjectiveError;
53import org.onosproject.net.group.DefaultGroupBucket;
54import org.onosproject.net.group.DefaultGroupDescription;
55import org.onosproject.net.group.DefaultGroupKey;
56import org.onosproject.net.group.Group;
57import org.onosproject.net.group.GroupBucket;
58import org.onosproject.net.group.GroupBuckets;
59import org.onosproject.net.group.GroupDescription;
60import org.onosproject.net.group.GroupEvent;
61import org.onosproject.net.group.GroupKey;
62import org.onosproject.net.group.GroupListener;
63import org.onosproject.net.group.GroupService;
alshabibaebe7752015-04-07 17:45:42 -070064import org.slf4j.Logger;
65
66import java.util.Collection;
alshabib2a441c62015-04-13 18:39:38 -070067import java.util.Collections;
68import java.util.Set;
69import java.util.concurrent.Executors;
70import java.util.concurrent.ScheduledExecutorService;
71import java.util.concurrent.TimeUnit;
72import java.util.stream.Collectors;
alshabibaebe7752015-04-07 17:45:42 -070073
alshabib2a441c62015-04-13 18:39:38 -070074import static org.onlab.util.Tools.groupedThreads;
alshabibaebe7752015-04-07 17:45:42 -070075import static org.slf4j.LoggerFactory.getLogger;
76
77/**
alshabib2a441c62015-04-13 18:39:38 -070078 * OpenvSwitch emulation of the Corsa pipeline handler.
alshabibaebe7752015-04-07 17:45:42 -070079 */
Thomas Vachuskafacc3f52015-04-10 08:58:36 -070080public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
alshabibaebe7752015-04-07 17:45:42 -070081
alshabibd17abc22015-04-21 18:26:35 -070082
83
Saurav Das3ea46622015-04-22 14:01:34 -070084 protected static final int MAC_TABLE = 0;
alshabibd17abc22015-04-21 18:26:35 -070085 protected static final int VLAN_MPLS_TABLE = 1;
86 protected static final int VLAN_TABLE = 2;
87 //protected static final int MPLS_TABLE = 3;
88 protected static final int ETHER_TABLE = 4;
89 protected static final int COS_MAP_TABLE = 5;
90 protected static final int FIB_TABLE = 6;
91 protected static final int LOCAL_TABLE = 9;
92
93
alshabibaebe7752015-04-07 17:45:42 -070094 private static final int CONTROLLER_PRIORITY = 255;
95 private static final int DROP_PRIORITY = 0;
96 private static final int HIGHEST_PRIORITY = 0xffff;
97
98 private final Logger log = getLogger(getClass());
99
100 private ServiceDirectory serviceDirectory;
101 private FlowRuleService flowRuleService;
102 private CoreService coreService;
alshabib2a441c62015-04-13 18:39:38 -0700103 private GroupService groupService;
104 private FlowObjectiveStore flowObjectiveStore;
alshabibaebe7752015-04-07 17:45:42 -0700105 private DeviceId deviceId;
106 private ApplicationId appId;
107
alshabib2a441c62015-04-13 18:39:38 -0700108 private KryoNamespace appKryo = new KryoNamespace.Builder()
109 .register(GroupKey.class)
110 .register(DefaultGroupKey.class)
111 .register(CorsaGroup.class)
112 .register(byte[].class)
113 .build();
114
115 private Cache<GroupKey, NextObjective> pendingGroups;
116
117 private ScheduledExecutorService groupChecker =
118 Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
119 "ovs-corsa-%d"));
120
alshabibaebe7752015-04-07 17:45:42 -0700121 @Override
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700122 public void init(DeviceId deviceId, PipelinerContext context) {
123 this.serviceDirectory = context.directory();
alshabibaebe7752015-04-07 17:45:42 -0700124 this.deviceId = deviceId;
125
alshabib2a441c62015-04-13 18:39:38 -0700126 pendingGroups = CacheBuilder.newBuilder()
127 .expireAfterWrite(20, TimeUnit.SECONDS)
128 .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
129 if (notification.getCause() == RemovalCause.EXPIRED) {
130 fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
131 }
132 }).build();
133
134 groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
alshabibaebe7752015-04-07 17:45:42 -0700135
136 coreService = serviceDirectory.get(CoreService.class);
137 flowRuleService = serviceDirectory.get(FlowRuleService.class);
alshabib2a441c62015-04-13 18:39:38 -0700138 groupService = serviceDirectory.get(GroupService.class);
139 flowObjectiveStore = context.store();
140
141 groupService.addListener(new InnerGroupListener());
alshabibaebe7752015-04-07 17:45:42 -0700142
143 appId = coreService.registerApplication(
144 "org.onosproject.driver.OVSCorsaPipeline");
145
146 pushDefaultRules();
alshabibaebe7752015-04-07 17:45:42 -0700147 }
148
149 @Override
alshabib2a441c62015-04-13 18:39:38 -0700150 public void filter(FilteringObjective filteringObjective) {
151 if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
152 processFilter(filteringObjective,
153 filteringObjective.op() == Objective.Operation.ADD,
154 filteringObjective.appId());
155 } else {
156 fail(filteringObjective, ObjectiveError.UNSUPPORTED);
157 }
158 }
alshabib910aff12015-04-09 16:55:57 -0700159
alshabib2a441c62015-04-13 18:39:38 -0700160 @Override
161 public void forward(ForwardingObjective fwd) {
162 Collection<FlowRule> rules;
163 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
164
165 rules = processForward(fwd);
166 switch (fwd.op()) {
167 case ADD:
168 rules.stream()
169 .filter(rule -> rule != null)
170 .forEach(flowBuilder::add);
171 break;
172 case REMOVE:
173 rules.stream()
174 .filter(rule -> rule != null)
175 .forEach(flowBuilder::remove);
176 break;
177 default:
178 fail(fwd, ObjectiveError.UNKNOWN);
179 log.warn("Unknown forwarding type {}", fwd.op());
180 }
181
182
183 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
184 @Override
185 public void onSuccess(FlowRuleOperations ops) {
186 pass(fwd);
187 }
188
189 @Override
190 public void onError(FlowRuleOperations ops) {
191 fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
192 }
193 }));
alshabib910aff12015-04-09 16:55:57 -0700194
195 }
196
alshabib2a441c62015-04-13 18:39:38 -0700197 @Override
198 public void next(NextObjective nextObjective) {
199 switch (nextObjective.type()) {
200 case SIMPLE:
201 Collection<TrafficTreatment> treatments = nextObjective.next();
202 if (treatments.size() == 1) {
203 TrafficTreatment treatment = treatments.iterator().next();
204 GroupBucket bucket =
205 DefaultGroupBucket.createIndirectGroupBucket(treatment);
206 final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
207 GroupDescription groupDescription
208 = new DefaultGroupDescription(deviceId,
209 GroupDescription.Type.INDIRECT,
210 new GroupBuckets(Collections
211 .singletonList(bucket)),
212 key,
213 nextObjective.appId());
214 groupService.addGroup(groupDescription);
215 pendingGroups.put(key, nextObjective);
216 }
217 break;
218 case HASHED:
219 case BROADCAST:
220 case FAILOVER:
221 fail(nextObjective, ObjectiveError.UNSUPPORTED);
222 log.warn("Unsupported next objective type {}", nextObjective.type());
223 break;
224 default:
225 fail(nextObjective, ObjectiveError.UNKNOWN);
226 log.warn("Unknown next objective type {}", nextObjective.type());
227 }
228
229 }
230
231 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
232 switch (fwd.flag()) {
233 case SPECIFIC:
234 return processSpecific(fwd);
235 case VERSATILE:
236 return processVersatile(fwd);
237 default:
238 fail(fwd, ObjectiveError.UNKNOWN);
239 log.warn("Unknown forwarding flag {}", fwd.flag());
240 }
241 return Collections.emptySet();
242 }
243
244 private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
Saurav Das3d038262015-04-23 12:36:58 -0700245 log.debug("Processing versatile forwarding objective");
246 TrafficSelector selector = fwd.selector();
247
248 Criteria.EthTypeCriterion ethType =
249 (Criteria.EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
250 if (ethType == null) {
251 log.error("Versatile forwarding objective must include ethType");
252 fail(fwd, ObjectiveError.UNKNOWN);
253 return Collections.emptySet();
254 }
255 if (ethType.ethType() == Ethernet.TYPE_ARP) {
256 log.warn("Driver automatically handles ARP packets by punting to controller "
257 + " from ETHER table");
258 pass(fwd);
259 return Collections.emptySet();
260 } else if (ethType.ethType() == Ethernet.TYPE_LLDP ||
261 ethType.ethType() == Ethernet.TYPE_BSN) {
262 log.warn("Driver currently does not currently handle LLDP packets");
263 fail(fwd, ObjectiveError.UNSUPPORTED);
264 return Collections.emptySet();
265 } else if (ethType.ethType() == Ethernet.TYPE_IPV4) {
266 Criteria.IPCriterion ipSrc = (Criteria.IPCriterion) selector
267 .getCriterion(Criterion.Type.IPV4_SRC);
268 Criteria.IPCriterion ipDst = (Criteria.IPCriterion) selector
269 .getCriterion(Criterion.Type.IPV4_DST);
270 Criteria.IPProtocolCriterion ipProto = (Criteria.IPProtocolCriterion) selector
271 .getCriterion(Criterion.Type.IP_PROTO);
272 if (ipSrc != null) {
273 log.warn("Driver currently does not currently handle matching Src IP");
274 fail(fwd, ObjectiveError.UNSUPPORTED);
275 return Collections.emptySet();
276 }
277 if (ipDst != null) {
278 log.error("Driver handles Dst IP matching as specific forwarding "
279 + "objective, not versatile");
280 fail(fwd, ObjectiveError.UNSUPPORTED);
281 return Collections.emptySet();
282 }
283 if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) {
284 log.warn("Driver automatically punts all packets reaching the "
285 + "LOCAL table to the controller");
286 pass(fwd);
287 return Collections.emptySet();
288 }
289 }
290
291 log.warn("Driver does not support given versatile forwarding objective");
alshabib2a441c62015-04-13 18:39:38 -0700292 fail(fwd, ObjectiveError.UNSUPPORTED);
293 return Collections.emptySet();
294 }
295
296 private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
Saurav Das3d038262015-04-23 12:36:58 -0700297 log.debug("Processing specific forwarding objective");
alshabib2a441c62015-04-13 18:39:38 -0700298 TrafficSelector selector = fwd.selector();
299 Criteria.EthTypeCriterion ethType =
300 (Criteria.EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
301 if (ethType == null || ethType.ethType() != Ethernet.TYPE_IPV4) {
302 fail(fwd, ObjectiveError.UNSUPPORTED);
303 return Collections.emptySet();
304 }
305
306 TrafficSelector filteredSelector =
307 DefaultTrafficSelector.builder()
308 .matchEthType(Ethernet.TYPE_IPV4)
309 .matchIPDst(
310 ((Criteria.IPCriterion)
311 selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
312 .build();
313
314 NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
315
316 GroupKey key = appKryo.deserialize(next.data());
317
318 Group group = groupService.getGroup(deviceId, key);
319
320 if (group == null) {
321 log.warn("The group left!");
322 fail(fwd, ObjectiveError.GROUPMISSING);
323 return Collections.emptySet();
324 }
325
326 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
327 .group(group.id())
328 .build();
329
alshabibd17abc22015-04-21 18:26:35 -0700330 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
331 .fromApp(fwd.appId())
332 .withPriority(fwd.priority())
333 .forDevice(deviceId)
334 .withSelector(filteredSelector)
335 .withTreatment(treatment);
336
337 if (fwd.permanent()) {
338 ruleBuilder.makePermanent();
339 } else {
340 ruleBuilder.makeTemporary(fwd.timeout());
341 }
342
343 ruleBuilder.forTable(FIB_TABLE);
344
345
346 return Collections.singletonList(ruleBuilder.build());
alshabib2a441c62015-04-13 18:39:38 -0700347
348 }
349
350 private void processFilter(FilteringObjective filt, boolean install,
alshabib910aff12015-04-09 16:55:57 -0700351 ApplicationId applicationId) {
Saurav Dascfd63d22015-04-13 16:08:24 -0700352 // This driver only processes filtering criteria defined with switch
353 // ports as the key
alshabib2a441c62015-04-13 18:39:38 -0700354 Criteria.PortCriterion p;
Saurav Dascfd63d22015-04-13 16:08:24 -0700355 if (!filt.key().equals(Criteria.dummy()) &&
356 filt.key().type() == Criterion.Type.IN_PORT) {
357 p = (Criteria.PortCriterion) filt.key();
358 } else {
359 log.warn("No key defined in filtering objective from app: {}. Not"
360 + "processing filtering objective", applicationId);
alshabib2a441c62015-04-13 18:39:38 -0700361 fail(filt, ObjectiveError.UNKNOWN);
362 return;
alshabib910aff12015-04-09 16:55:57 -0700363 }
Saurav Dascfd63d22015-04-13 16:08:24 -0700364 // convert filtering conditions for switch-intfs into flowrules
365 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
366 for (Criterion c : filt.conditions()) {
367 if (c.type() == Criterion.Type.ETH_DST) {
368 Criteria.EthCriterion e = (Criteria.EthCriterion) c;
369 log.debug("adding rule for MAC: {}", e.mac());
370 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
371 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
372 selector.matchEthDst(e.mac());
alshabibd17abc22015-04-21 18:26:35 -0700373 treatment.transition(VLAN_MPLS_TABLE);
374 FlowRule rule = DefaultFlowRule.builder()
375 .forDevice(deviceId)
376 .withSelector(selector.build())
377 .withTreatment(treatment.build())
378 .withPriority(CONTROLLER_PRIORITY)
379 .fromApp(applicationId)
380 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700381 .forTable(MAC_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700382 ops = install ? ops.add(rule) : ops.remove(rule);
383 } else if (c.type() == Criterion.Type.VLAN_VID) {
384 Criteria.VlanIdCriterion v = (Criteria.VlanIdCriterion) c;
385 log.debug("adding rule for VLAN: {}", v.vlanId());
386 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
387 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
388 selector.matchVlanId(v.vlanId());
389 selector.matchInPort(p.port());
alshabibd17abc22015-04-21 18:26:35 -0700390 treatment.transition(ETHER_TABLE);
Saurav Dascfd63d22015-04-13 16:08:24 -0700391 treatment.deferred().popVlan();
alshabibd17abc22015-04-21 18:26:35 -0700392 FlowRule rule = DefaultFlowRule.builder()
393 .forDevice(deviceId)
394 .withSelector(selector.build())
395 .withTreatment(treatment.build())
396 .withPriority(CONTROLLER_PRIORITY)
397 .fromApp(applicationId)
398 .makePermanent()
399 .forTable(VLAN_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700400 ops = install ? ops.add(rule) : ops.remove(rule);
401 } else if (c.type() == Criterion.Type.IPV4_DST) {
402 Criteria.IPCriterion ip = (Criteria.IPCriterion) c;
403 log.debug("adding rule for IP: {}", ip.ip());
404 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
405 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
406 selector.matchEthType(Ethernet.TYPE_IPV4);
407 selector.matchIPDst(ip.ip());
alshabibd17abc22015-04-21 18:26:35 -0700408 treatment.transition(LOCAL_TABLE);
409 FlowRule rule = DefaultFlowRule.builder()
410 .forDevice(deviceId)
411 .withSelector(selector.build())
412 .withTreatment(treatment.build())
413 .withPriority(HIGHEST_PRIORITY)
414 .fromApp(applicationId)
415 .makePermanent()
416 .forTable(FIB_TABLE).build();
417
Saurav Dascfd63d22015-04-13 16:08:24 -0700418 ops = install ? ops.add(rule) : ops.remove(rule);
419 } else {
420 log.warn("Driver does not currently process filtering condition"
421 + " of type: {}", c.type());
alshabib2a441c62015-04-13 18:39:38 -0700422 fail(filt, ObjectiveError.UNSUPPORTED);
Saurav Dascfd63d22015-04-13 16:08:24 -0700423 }
424 }
425 // apply filtering flow rules
426 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
427 @Override
428 public void onSuccess(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700429 pass(filt);
Saurav Das3ea46622015-04-22 14:01:34 -0700430 log.info("Applied filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700431 }
432
433 @Override
434 public void onError(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700435 fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
Saurav Das3ea46622015-04-22 14:01:34 -0700436 log.info("Failed to apply filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700437 }
438 }));
alshabibaebe7752015-04-07 17:45:42 -0700439 }
440
alshabib2a441c62015-04-13 18:39:38 -0700441 private void pass(Objective obj) {
442 if (obj.context().isPresent()) {
443 obj.context().get().onSuccess(obj);
444 }
alshabibaebe7752015-04-07 17:45:42 -0700445 }
446
alshabib2a441c62015-04-13 18:39:38 -0700447 private void fail(Objective obj, ObjectiveError error) {
448 if (obj.context().isPresent()) {
449 obj.context().get().onError(obj, error);
450 }
alshabibaebe7752015-04-07 17:45:42 -0700451 }
452
alshabibaebe7752015-04-07 17:45:42 -0700453 private void pushDefaultRules() {
Saurav Das3ea46622015-04-22 14:01:34 -0700454 processMacTable(true);
455 processVlanMplsTable(true);
456 processVlanTable(true);
457 processEtherTable(true);
458 processCosTable(true);
459 processFibTable(true);
460 processLocalTable(true);
alshabibaebe7752015-04-07 17:45:42 -0700461 }
462
Saurav Das3ea46622015-04-22 14:01:34 -0700463 private void processMacTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700464 TrafficSelector.Builder selector;
465 TrafficTreatment.Builder treatment;
466
467 // Bcast rule
468 selector = DefaultTrafficSelector.builder();
469 treatment = DefaultTrafficTreatment.builder();
470
471 selector.matchEthDst(MacAddress.BROADCAST);
alshabibd17abc22015-04-21 18:26:35 -0700472 treatment.transition(VLAN_MPLS_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700473
alshabibd17abc22015-04-21 18:26:35 -0700474 FlowRule rule = DefaultFlowRule.builder()
475 .forDevice(deviceId)
476 .withSelector(selector.build())
477 .withTreatment(treatment.build())
478 .withPriority(CONTROLLER_PRIORITY)
479 .fromApp(appId)
480 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700481 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700482
alshabibaebe7752015-04-07 17:45:42 -0700483
484 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
485
486 ops = install ? ops.add(rule) : ops.remove(rule);
487
488
alshabibaebe7752015-04-07 17:45:42 -0700489 //Drop rule
490 selector = DefaultTrafficSelector.builder();
491 treatment = DefaultTrafficTreatment.builder();
492
493 treatment.drop();
494
alshabibd17abc22015-04-21 18:26:35 -0700495 rule = DefaultFlowRule.builder()
496 .forDevice(deviceId)
497 .withSelector(selector.build())
498 .withTreatment(treatment.build())
499 .withPriority(DROP_PRIORITY)
500 .fromApp(appId)
501 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700502 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700503
alshabibaebe7752015-04-07 17:45:42 -0700504
505 ops = install ? ops.add(rule) : ops.remove(rule);
506
507 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
508 @Override
509 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700510 log.info("Provisioned mac table");
alshabibaebe7752015-04-07 17:45:42 -0700511 }
512
513 @Override
514 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700515 log.info("Failed to provision mac table");
alshabibaebe7752015-04-07 17:45:42 -0700516 }
517 }));
518
519 }
520
Saurav Das3ea46622015-04-22 14:01:34 -0700521 private void processVlanMplsTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700522 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
523 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
524 .builder();
525 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
526 FlowRule rule;
527
528 selector.matchVlanId(VlanId.ANY);
alshabibd17abc22015-04-21 18:26:35 -0700529 treatment.transition(VLAN_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700530
alshabibd17abc22015-04-21 18:26:35 -0700531 rule = DefaultFlowRule.builder()
532 .forDevice(deviceId)
533 .withSelector(selector.build())
534 .withTreatment(treatment.build())
535 .withPriority(CONTROLLER_PRIORITY)
536 .fromApp(appId)
537 .makePermanent()
538 .forTable(VLAN_MPLS_TABLE).build();
539
alshabibaebe7752015-04-07 17:45:42 -0700540
541 ops = install ? ops.add(rule) : ops.remove(rule);
542
543 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
544 @Override
545 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700546 log.info("Provisioned vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700547 }
548
549 @Override
550 public void onError(FlowRuleOperations ops) {
551 log.info(
Saurav Das3ea46622015-04-22 14:01:34 -0700552 "Failed to provision vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700553 }
554 }));
555
556 }
557
Saurav Das3ea46622015-04-22 14:01:34 -0700558 private void processVlanTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700559 TrafficSelector.Builder selector;
560 TrafficTreatment.Builder treatment;
561 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
562 FlowRule rule;
563
564
alshabibaebe7752015-04-07 17:45:42 -0700565 //Drop rule
566 selector = DefaultTrafficSelector.builder();
567 treatment = DefaultTrafficTreatment.builder();
568
569 treatment.drop();
570
alshabibd17abc22015-04-21 18:26:35 -0700571 rule = DefaultFlowRule.builder()
572 .forDevice(deviceId)
573 .withSelector(selector.build())
574 .withTreatment(treatment.build())
575 .withPriority(DROP_PRIORITY)
576 .fromApp(appId)
577 .makePermanent()
578 .forTable(VLAN_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700579
580 ops = install ? ops.add(rule) : ops.remove(rule);
581
582 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
583 @Override
584 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700585 log.info("Provisioned vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700586 }
587
588 @Override
589 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700590 log.info("Failed to provision vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700591 }
592 }));
593 }
594
Saurav Das3ea46622015-04-22 14:01:34 -0700595 private void processEtherTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700596 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
597 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
598 .builder();
599 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
600 FlowRule rule;
601
602 selector.matchEthType(Ethernet.TYPE_ARP);
603 treatment.punt();
604
alshabibd17abc22015-04-21 18:26:35 -0700605 rule = DefaultFlowRule.builder()
606 .forDevice(deviceId)
607 .withSelector(selector.build())
608 .withTreatment(treatment.build())
609 .withPriority(CONTROLLER_PRIORITY)
610 .fromApp(appId)
611 .makePermanent()
612 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700613
614 ops = install ? ops.add(rule) : ops.remove(rule);
615
616 selector = DefaultTrafficSelector.builder();
617 treatment = DefaultTrafficTreatment.builder();
618
619 selector.matchEthType(Ethernet.TYPE_IPV4);
alshabibd17abc22015-04-21 18:26:35 -0700620 treatment.transition(COS_MAP_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700621
alshabibd17abc22015-04-21 18:26:35 -0700622 rule = DefaultFlowRule.builder()
623 .forDevice(deviceId)
624 .withPriority(CONTROLLER_PRIORITY)
625 .withSelector(selector.build())
626 .withTreatment(treatment.build())
627 .fromApp(appId)
628 .makePermanent()
629 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700630
631 ops = install ? ops.add(rule) : ops.remove(rule);
632
633 //Drop rule
634 selector = DefaultTrafficSelector.builder();
635 treatment = DefaultTrafficTreatment.builder();
636
637 treatment.drop();
638
alshabibd17abc22015-04-21 18:26:35 -0700639 rule = DefaultFlowRule.builder()
640 .forDevice(deviceId)
641 .withSelector(selector.build())
642 .withTreatment(treatment.build())
643 .withPriority(DROP_PRIORITY)
644 .fromApp(appId)
645 .makePermanent()
646 .forTable(ETHER_TABLE).build();
647
alshabibaebe7752015-04-07 17:45:42 -0700648
649 ops = install ? ops.add(rule) : ops.remove(rule);
650
651 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
652 @Override
653 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700654 log.info("Provisioned ether table");
alshabibaebe7752015-04-07 17:45:42 -0700655 }
656
657 @Override
658 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700659 log.info("Failed to provision ether table");
alshabibaebe7752015-04-07 17:45:42 -0700660 }
661 }));
662
663 }
664
Saurav Das3ea46622015-04-22 14:01:34 -0700665 private void processCosTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700666 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
667 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
668 .builder();
669 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
670 FlowRule rule;
671
alshabibd17abc22015-04-21 18:26:35 -0700672 treatment.transition(FIB_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700673
alshabibd17abc22015-04-21 18:26:35 -0700674 rule = DefaultFlowRule.builder()
675 .forDevice(deviceId)
676 .withSelector(selector.build())
677 .withTreatment(treatment.build())
678 .withPriority(DROP_PRIORITY)
679 .fromApp(appId)
680 .makePermanent()
681 .forTable(COS_MAP_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700682
683 ops = install ? ops.add(rule) : ops.remove(rule);
684
685 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
686 @Override
687 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700688 log.info("Provisioned cos table");
alshabibaebe7752015-04-07 17:45:42 -0700689 }
690
691 @Override
692 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700693 log.info("Failed to provision cos table");
alshabibaebe7752015-04-07 17:45:42 -0700694 }
695 }));
696
697 }
698
Saurav Das3ea46622015-04-22 14:01:34 -0700699 private void processFibTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700700 TrafficSelector.Builder selector;
701 TrafficTreatment.Builder treatment;
702 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
703 FlowRule rule;
704
705 //Drop rule
706 selector = DefaultTrafficSelector.builder();
707 treatment = DefaultTrafficTreatment.builder();
708
709 treatment.drop();
710
alshabibd17abc22015-04-21 18:26:35 -0700711 rule = DefaultFlowRule.builder()
712 .forDevice(deviceId)
713 .withSelector(selector.build())
714 .withTreatment(treatment.build())
715 .withPriority(DROP_PRIORITY)
716 .fromApp(appId)
717 .makePermanent()
718 .forTable(FIB_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700719
720 ops = install ? ops.add(rule) : ops.remove(rule);
721
722 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
723 @Override
724 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700725 log.info("Provisioned FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700726 }
727
728 @Override
729 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700730 log.info("Failed to provision FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700731 }
732 }));
733 }
734
Saurav Das3ea46622015-04-22 14:01:34 -0700735 private void processLocalTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700736 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
737 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
738 .builder();
739 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
740 FlowRule rule;
741
742 treatment.punt();
743
alshabibd17abc22015-04-21 18:26:35 -0700744 rule = DefaultFlowRule.builder()
745 .forDevice(deviceId)
746 .withSelector(selector.build())
747 .withTreatment(treatment.build())
748 .withPriority(CONTROLLER_PRIORITY)
749 .fromApp(appId)
750 .makePermanent()
751 .forTable(LOCAL_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700752
753 ops = install ? ops.add(rule) : ops.remove(rule);
754
755 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
756 @Override
757 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700758 log.info("Provisioned Local table");
alshabibaebe7752015-04-07 17:45:42 -0700759 }
760
761 @Override
762 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700763 log.info("Failed to provision Local table");
alshabibaebe7752015-04-07 17:45:42 -0700764 }
765 }));
766 }
767
alshabib2a441c62015-04-13 18:39:38 -0700768 private class InnerGroupListener implements GroupListener {
769 @Override
770 public void event(GroupEvent event) {
771 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
772 GroupKey key = event.subject().appCookie();
773
774 NextObjective obj = pendingGroups.getIfPresent(key);
775 if (obj != null) {
776 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
777 pass(obj);
778 pendingGroups.invalidate(key);
779 }
780 }
781 }
782 }
783
784
785 private class GroupChecker implements Runnable {
786
787 @Override
788 public void run() {
789 Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
790 .filter(key -> groupService.getGroup(deviceId, key) != null)
791 .collect(Collectors.toSet());
792
793 keys.stream().forEach(key -> {
794 NextObjective obj = pendingGroups.getIfPresent(key);
795 if (obj == null) {
796 return;
797 }
798 pass(obj);
799 pendingGroups.invalidate(key);
Saurav Das3ea46622015-04-22 14:01:34 -0700800 log.info("Heard back from group service for group {}", obj.id());
alshabib2a441c62015-04-13 18:39:38 -0700801 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
802 });
803 }
804 }
805
806 private class CorsaGroup implements NextGroup {
807
808 private final GroupKey key;
809
810 public CorsaGroup(GroupKey key) {
811 this.key = key;
812 }
813
814 public GroupKey key() {
815 return key;
816 }
817
818 @Override
819 public byte[] data() {
820 return appKryo.serialize(key);
821 }
822
823 }
alshabibaebe7752015-04-07 17:45:42 -0700824}