blob: ddcb4d9f9e183c824e52feef22d6835fcf887b7e [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;
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -070047import org.onosproject.net.flow.criteria.EthCriterion;
48import org.onosproject.net.flow.criteria.EthTypeCriterion;
49import org.onosproject.net.flow.criteria.IPCriterion;
50import org.onosproject.net.flow.criteria.IPProtocolCriterion;
51import org.onosproject.net.flow.criteria.PortCriterion;
52import org.onosproject.net.flow.criteria.VlanIdCriterion;
alshabibaebe7752015-04-07 17:45:42 -070053import org.onosproject.net.flowobjective.FilteringObjective;
alshabib2a441c62015-04-13 18:39:38 -070054import org.onosproject.net.flowobjective.FlowObjectiveStore;
alshabibaebe7752015-04-07 17:45:42 -070055import org.onosproject.net.flowobjective.ForwardingObjective;
56import org.onosproject.net.flowobjective.NextObjective;
alshabib910aff12015-04-09 16:55:57 -070057import org.onosproject.net.flowobjective.Objective;
alshabib2a441c62015-04-13 18:39:38 -070058import org.onosproject.net.flowobjective.ObjectiveError;
59import org.onosproject.net.group.DefaultGroupBucket;
60import org.onosproject.net.group.DefaultGroupDescription;
61import org.onosproject.net.group.DefaultGroupKey;
62import org.onosproject.net.group.Group;
63import org.onosproject.net.group.GroupBucket;
64import org.onosproject.net.group.GroupBuckets;
65import org.onosproject.net.group.GroupDescription;
66import org.onosproject.net.group.GroupEvent;
67import org.onosproject.net.group.GroupKey;
68import org.onosproject.net.group.GroupListener;
69import org.onosproject.net.group.GroupService;
alshabibaebe7752015-04-07 17:45:42 -070070import org.slf4j.Logger;
71
72import java.util.Collection;
alshabib2a441c62015-04-13 18:39:38 -070073import java.util.Collections;
74import java.util.Set;
75import java.util.concurrent.Executors;
76import java.util.concurrent.ScheduledExecutorService;
77import java.util.concurrent.TimeUnit;
78import java.util.stream.Collectors;
alshabibaebe7752015-04-07 17:45:42 -070079
alshabib2a441c62015-04-13 18:39:38 -070080import static org.onlab.util.Tools.groupedThreads;
alshabibaebe7752015-04-07 17:45:42 -070081import static org.slf4j.LoggerFactory.getLogger;
82
83/**
alshabib2a441c62015-04-13 18:39:38 -070084 * OpenvSwitch emulation of the Corsa pipeline handler.
alshabibaebe7752015-04-07 17:45:42 -070085 */
Thomas Vachuskafacc3f52015-04-10 08:58:36 -070086public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
alshabibaebe7752015-04-07 17:45:42 -070087
Saurav Das3ea46622015-04-22 14:01:34 -070088 protected static final int MAC_TABLE = 0;
alshabibd17abc22015-04-21 18:26:35 -070089 protected static final int VLAN_MPLS_TABLE = 1;
90 protected static final int VLAN_TABLE = 2;
91 //protected static final int MPLS_TABLE = 3;
92 protected static final int ETHER_TABLE = 4;
93 protected static final int COS_MAP_TABLE = 5;
94 protected static final int FIB_TABLE = 6;
95 protected static final int LOCAL_TABLE = 9;
96
97
Saurav Dasd8b97002015-05-14 23:42:49 -070098 protected static final int CONTROLLER_PRIORITY = 255;
alshabibaebe7752015-04-07 17:45:42 -070099 private static final int DROP_PRIORITY = 0;
100 private static final int HIGHEST_PRIORITY = 0xffff;
101
102 private final Logger log = getLogger(getClass());
103
104 private ServiceDirectory serviceDirectory;
Saurav Dasd8b97002015-05-14 23:42:49 -0700105 protected FlowRuleService flowRuleService;
alshabibaebe7752015-04-07 17:45:42 -0700106 private CoreService coreService;
alshabib2a441c62015-04-13 18:39:38 -0700107 private GroupService groupService;
108 private FlowObjectiveStore flowObjectiveStore;
Saurav Dasd8b97002015-05-14 23:42:49 -0700109 protected DeviceId deviceId;
110 protected ApplicationId appId;
alshabibaebe7752015-04-07 17:45:42 -0700111
alshabib2a441c62015-04-13 18:39:38 -0700112 private KryoNamespace appKryo = new KryoNamespace.Builder()
113 .register(GroupKey.class)
114 .register(DefaultGroupKey.class)
115 .register(CorsaGroup.class)
116 .register(byte[].class)
117 .build();
118
119 private Cache<GroupKey, NextObjective> pendingGroups;
120
121 private ScheduledExecutorService groupChecker =
122 Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
123 "ovs-corsa-%d"));
124
alshabibaebe7752015-04-07 17:45:42 -0700125 @Override
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700126 public void init(DeviceId deviceId, PipelinerContext context) {
127 this.serviceDirectory = context.directory();
alshabibaebe7752015-04-07 17:45:42 -0700128 this.deviceId = deviceId;
129
alshabib2a441c62015-04-13 18:39:38 -0700130 pendingGroups = CacheBuilder.newBuilder()
131 .expireAfterWrite(20, TimeUnit.SECONDS)
132 .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
133 if (notification.getCause() == RemovalCause.EXPIRED) {
134 fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
135 }
136 }).build();
137
138 groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
alshabibaebe7752015-04-07 17:45:42 -0700139
140 coreService = serviceDirectory.get(CoreService.class);
141 flowRuleService = serviceDirectory.get(FlowRuleService.class);
alshabib2a441c62015-04-13 18:39:38 -0700142 groupService = serviceDirectory.get(GroupService.class);
143 flowObjectiveStore = context.store();
144
145 groupService.addListener(new InnerGroupListener());
alshabibaebe7752015-04-07 17:45:42 -0700146
147 appId = coreService.registerApplication(
148 "org.onosproject.driver.OVSCorsaPipeline");
149
Saurav Das100e3b82015-04-30 11:12:10 -0700150 initializePipeline();
alshabibaebe7752015-04-07 17:45:42 -0700151 }
152
153 @Override
alshabib2a441c62015-04-13 18:39:38 -0700154 public void filter(FilteringObjective filteringObjective) {
155 if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
156 processFilter(filteringObjective,
157 filteringObjective.op() == Objective.Operation.ADD,
158 filteringObjective.appId());
159 } else {
160 fail(filteringObjective, ObjectiveError.UNSUPPORTED);
161 }
162 }
alshabib910aff12015-04-09 16:55:57 -0700163
alshabib2a441c62015-04-13 18:39:38 -0700164 @Override
165 public void forward(ForwardingObjective fwd) {
166 Collection<FlowRule> rules;
167 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
168
169 rules = processForward(fwd);
170 switch (fwd.op()) {
171 case ADD:
172 rules.stream()
173 .filter(rule -> rule != null)
174 .forEach(flowBuilder::add);
175 break;
176 case REMOVE:
177 rules.stream()
178 .filter(rule -> rule != null)
179 .forEach(flowBuilder::remove);
180 break;
181 default:
182 fail(fwd, ObjectiveError.UNKNOWN);
183 log.warn("Unknown forwarding type {}", fwd.op());
184 }
185
186
187 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
188 @Override
189 public void onSuccess(FlowRuleOperations ops) {
190 pass(fwd);
191 }
192
193 @Override
194 public void onError(FlowRuleOperations ops) {
195 fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
196 }
197 }));
alshabib910aff12015-04-09 16:55:57 -0700198
199 }
200
alshabib2a441c62015-04-13 18:39:38 -0700201 @Override
202 public void next(NextObjective nextObjective) {
203 switch (nextObjective.type()) {
204 case SIMPLE:
205 Collection<TrafficTreatment> treatments = nextObjective.next();
206 if (treatments.size() == 1) {
207 TrafficTreatment treatment = treatments.iterator().next();
208 GroupBucket bucket =
209 DefaultGroupBucket.createIndirectGroupBucket(treatment);
210 final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
211 GroupDescription groupDescription
212 = new DefaultGroupDescription(deviceId,
213 GroupDescription.Type.INDIRECT,
214 new GroupBuckets(Collections
215 .singletonList(bucket)),
216 key,
Saurav Das100e3b82015-04-30 11:12:10 -0700217 null, // let group service determine group id
alshabib2a441c62015-04-13 18:39:38 -0700218 nextObjective.appId());
219 groupService.addGroup(groupDescription);
220 pendingGroups.put(key, nextObjective);
221 }
222 break;
223 case HASHED:
224 case BROADCAST:
225 case FAILOVER:
226 fail(nextObjective, ObjectiveError.UNSUPPORTED);
227 log.warn("Unsupported next objective type {}", nextObjective.type());
228 break;
229 default:
230 fail(nextObjective, ObjectiveError.UNKNOWN);
231 log.warn("Unknown next objective type {}", nextObjective.type());
232 }
233
234 }
235
236 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
237 switch (fwd.flag()) {
238 case SPECIFIC:
239 return processSpecific(fwd);
240 case VERSATILE:
241 return processVersatile(fwd);
242 default:
243 fail(fwd, ObjectiveError.UNKNOWN);
244 log.warn("Unknown forwarding flag {}", fwd.flag());
245 }
246 return Collections.emptySet();
247 }
248
249 private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
Saurav Das3d038262015-04-23 12:36:58 -0700250 log.debug("Processing versatile forwarding objective");
251 TrafficSelector selector = fwd.selector();
252
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700253 EthTypeCriterion ethType =
254 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
Saurav Das3d038262015-04-23 12:36:58 -0700255 if (ethType == null) {
256 log.error("Versatile forwarding objective must include ethType");
257 fail(fwd, ObjectiveError.UNKNOWN);
258 return Collections.emptySet();
259 }
260 if (ethType.ethType() == Ethernet.TYPE_ARP) {
261 log.warn("Driver automatically handles ARP packets by punting to controller "
262 + " from ETHER table");
263 pass(fwd);
264 return Collections.emptySet();
265 } else if (ethType.ethType() == Ethernet.TYPE_LLDP ||
266 ethType.ethType() == Ethernet.TYPE_BSN) {
267 log.warn("Driver currently does not currently handle LLDP packets");
268 fail(fwd, ObjectiveError.UNSUPPORTED);
269 return Collections.emptySet();
270 } else if (ethType.ethType() == Ethernet.TYPE_IPV4) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700271 IPCriterion ipSrc = (IPCriterion) selector
Saurav Das3d038262015-04-23 12:36:58 -0700272 .getCriterion(Criterion.Type.IPV4_SRC);
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700273 IPCriterion ipDst = (IPCriterion) selector
Saurav Das3d038262015-04-23 12:36:58 -0700274 .getCriterion(Criterion.Type.IPV4_DST);
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700275 IPProtocolCriterion ipProto = (IPProtocolCriterion) selector
Saurav Das3d038262015-04-23 12:36:58 -0700276 .getCriterion(Criterion.Type.IP_PROTO);
277 if (ipSrc != null) {
Saurav Dasbd7f7422015-04-23 16:31:47 -0700278 log.warn("Driver does not currently handle matching Src IP");
Saurav Das3d038262015-04-23 12:36:58 -0700279 fail(fwd, ObjectiveError.UNSUPPORTED);
280 return Collections.emptySet();
281 }
282 if (ipDst != null) {
283 log.error("Driver handles Dst IP matching as specific forwarding "
284 + "objective, not versatile");
285 fail(fwd, ObjectiveError.UNSUPPORTED);
286 return Collections.emptySet();
287 }
288 if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) {
289 log.warn("Driver automatically punts all packets reaching the "
290 + "LOCAL table to the controller");
291 pass(fwd);
292 return Collections.emptySet();
293 }
294 }
295
296 log.warn("Driver does not support given versatile forwarding objective");
alshabib2a441c62015-04-13 18:39:38 -0700297 fail(fwd, ObjectiveError.UNSUPPORTED);
298 return Collections.emptySet();
299 }
300
301 private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
Saurav Das3d038262015-04-23 12:36:58 -0700302 log.debug("Processing specific forwarding objective");
alshabib2a441c62015-04-13 18:39:38 -0700303 TrafficSelector selector = fwd.selector();
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700304 EthTypeCriterion ethType =
305 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
alshabib2a441c62015-04-13 18:39:38 -0700306 if (ethType == null || ethType.ethType() != Ethernet.TYPE_IPV4) {
307 fail(fwd, ObjectiveError.UNSUPPORTED);
308 return Collections.emptySet();
309 }
310
311 TrafficSelector filteredSelector =
312 DefaultTrafficSelector.builder()
313 .matchEthType(Ethernet.TYPE_IPV4)
314 .matchIPDst(
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700315 ((IPCriterion)
alshabib2a441c62015-04-13 18:39:38 -0700316 selector.getCriterion(Criterion.Type.IPV4_DST)).ip())
317 .build();
318
sanghodde53d12015-04-30 10:34:41 -0700319 TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
alshabib2a441c62015-04-13 18:39:38 -0700320
sanghodde53d12015-04-30 10:34:41 -0700321 if (fwd.nextId() != null) {
322 NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
323 GroupKey key = appKryo.deserialize(next.data());
324 Group group = groupService.getGroup(deviceId, key);
325 if (group == null) {
326 log.warn("The group left!");
327 fail(fwd, ObjectiveError.GROUPMISSING);
328 return Collections.emptySet();
329 }
330 tb.group(group.id());
alshabib2a441c62015-04-13 18:39:38 -0700331 }
332
alshabibd17abc22015-04-21 18:26:35 -0700333 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
334 .fromApp(fwd.appId())
335 .withPriority(fwd.priority())
336 .forDevice(deviceId)
337 .withSelector(filteredSelector)
sanghodde53d12015-04-30 10:34:41 -0700338 .withTreatment(tb.build());
alshabibd17abc22015-04-21 18:26:35 -0700339
340 if (fwd.permanent()) {
341 ruleBuilder.makePermanent();
342 } else {
343 ruleBuilder.makeTemporary(fwd.timeout());
344 }
345
346 ruleBuilder.forTable(FIB_TABLE);
347
348
349 return Collections.singletonList(ruleBuilder.build());
alshabib2a441c62015-04-13 18:39:38 -0700350
351 }
352
353 private void processFilter(FilteringObjective filt, boolean install,
alshabib910aff12015-04-09 16:55:57 -0700354 ApplicationId applicationId) {
Saurav Dascfd63d22015-04-13 16:08:24 -0700355 // This driver only processes filtering criteria defined with switch
356 // ports as the key
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700357 PortCriterion p;
Saurav Dascfd63d22015-04-13 16:08:24 -0700358 if (!filt.key().equals(Criteria.dummy()) &&
359 filt.key().type() == Criterion.Type.IN_PORT) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700360 p = (PortCriterion) filt.key();
Saurav Dascfd63d22015-04-13 16:08:24 -0700361 } else {
362 log.warn("No key defined in filtering objective from app: {}. Not"
363 + "processing filtering objective", applicationId);
alshabib2a441c62015-04-13 18:39:38 -0700364 fail(filt, ObjectiveError.UNKNOWN);
365 return;
alshabib910aff12015-04-09 16:55:57 -0700366 }
Saurav Dascfd63d22015-04-13 16:08:24 -0700367 // convert filtering conditions for switch-intfs into flowrules
368 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
369 for (Criterion c : filt.conditions()) {
370 if (c.type() == Criterion.Type.ETH_DST) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700371 EthCriterion e = (EthCriterion) c;
Saurav Dascfd63d22015-04-13 16:08:24 -0700372 log.debug("adding rule for MAC: {}", e.mac());
373 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
374 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
375 selector.matchEthDst(e.mac());
alshabibd17abc22015-04-21 18:26:35 -0700376 treatment.transition(VLAN_MPLS_TABLE);
377 FlowRule rule = DefaultFlowRule.builder()
378 .forDevice(deviceId)
379 .withSelector(selector.build())
380 .withTreatment(treatment.build())
381 .withPriority(CONTROLLER_PRIORITY)
382 .fromApp(applicationId)
383 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700384 .forTable(MAC_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700385 ops = install ? ops.add(rule) : ops.remove(rule);
386 } else if (c.type() == Criterion.Type.VLAN_VID) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700387 VlanIdCriterion v = (VlanIdCriterion) c;
Saurav Dascfd63d22015-04-13 16:08:24 -0700388 log.debug("adding rule for VLAN: {}", v.vlanId());
389 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
390 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
391 selector.matchVlanId(v.vlanId());
392 selector.matchInPort(p.port());
alshabibd17abc22015-04-21 18:26:35 -0700393 treatment.transition(ETHER_TABLE);
Saurav Dascfd63d22015-04-13 16:08:24 -0700394 treatment.deferred().popVlan();
alshabibd17abc22015-04-21 18:26:35 -0700395 FlowRule rule = DefaultFlowRule.builder()
396 .forDevice(deviceId)
397 .withSelector(selector.build())
398 .withTreatment(treatment.build())
399 .withPriority(CONTROLLER_PRIORITY)
400 .fromApp(applicationId)
401 .makePermanent()
402 .forTable(VLAN_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700403 ops = install ? ops.add(rule) : ops.remove(rule);
404 } else if (c.type() == Criterion.Type.IPV4_DST) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700405 IPCriterion ip = (IPCriterion) c;
Saurav Dascfd63d22015-04-13 16:08:24 -0700406 log.debug("adding rule for IP: {}", ip.ip());
407 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
408 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
409 selector.matchEthType(Ethernet.TYPE_IPV4);
410 selector.matchIPDst(ip.ip());
alshabibd17abc22015-04-21 18:26:35 -0700411 treatment.transition(LOCAL_TABLE);
412 FlowRule rule = DefaultFlowRule.builder()
413 .forDevice(deviceId)
414 .withSelector(selector.build())
415 .withTreatment(treatment.build())
416 .withPriority(HIGHEST_PRIORITY)
417 .fromApp(applicationId)
418 .makePermanent()
419 .forTable(FIB_TABLE).build();
420
Saurav Dascfd63d22015-04-13 16:08:24 -0700421 ops = install ? ops.add(rule) : ops.remove(rule);
422 } else {
423 log.warn("Driver does not currently process filtering condition"
424 + " of type: {}", c.type());
alshabib2a441c62015-04-13 18:39:38 -0700425 fail(filt, ObjectiveError.UNSUPPORTED);
Saurav Dascfd63d22015-04-13 16:08:24 -0700426 }
427 }
428 // apply filtering flow rules
429 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
430 @Override
431 public void onSuccess(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700432 pass(filt);
Saurav Das3ea46622015-04-22 14:01:34 -0700433 log.info("Applied filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700434 }
435
436 @Override
437 public void onError(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700438 fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
Saurav Das3ea46622015-04-22 14:01:34 -0700439 log.info("Failed to apply filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700440 }
441 }));
alshabibaebe7752015-04-07 17:45:42 -0700442 }
443
alshabib2a441c62015-04-13 18:39:38 -0700444 private void pass(Objective obj) {
445 if (obj.context().isPresent()) {
446 obj.context().get().onSuccess(obj);
447 }
alshabibaebe7752015-04-07 17:45:42 -0700448 }
449
alshabib2a441c62015-04-13 18:39:38 -0700450 private void fail(Objective obj, ObjectiveError error) {
451 if (obj.context().isPresent()) {
452 obj.context().get().onError(obj, error);
453 }
alshabibaebe7752015-04-07 17:45:42 -0700454 }
455
Saurav Das100e3b82015-04-30 11:12:10 -0700456 private void initializePipeline() {
Saurav Das3ea46622015-04-22 14:01:34 -0700457 processMacTable(true);
458 processVlanMplsTable(true);
459 processVlanTable(true);
460 processEtherTable(true);
461 processCosTable(true);
462 processFibTable(true);
463 processLocalTable(true);
alshabibaebe7752015-04-07 17:45:42 -0700464 }
465
Saurav Das3ea46622015-04-22 14:01:34 -0700466 private void processMacTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700467 TrafficSelector.Builder selector;
468 TrafficTreatment.Builder treatment;
469
470 // Bcast rule
471 selector = DefaultTrafficSelector.builder();
472 treatment = DefaultTrafficTreatment.builder();
473
474 selector.matchEthDst(MacAddress.BROADCAST);
alshabibd17abc22015-04-21 18:26:35 -0700475 treatment.transition(VLAN_MPLS_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700476
alshabibd17abc22015-04-21 18:26:35 -0700477 FlowRule rule = DefaultFlowRule.builder()
478 .forDevice(deviceId)
479 .withSelector(selector.build())
480 .withTreatment(treatment.build())
481 .withPriority(CONTROLLER_PRIORITY)
482 .fromApp(appId)
483 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700484 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700485
alshabibaebe7752015-04-07 17:45:42 -0700486
487 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
488
489 ops = install ? ops.add(rule) : ops.remove(rule);
490
491
alshabibaebe7752015-04-07 17:45:42 -0700492 //Drop rule
493 selector = DefaultTrafficSelector.builder();
494 treatment = DefaultTrafficTreatment.builder();
495
496 treatment.drop();
497
alshabibd17abc22015-04-21 18:26:35 -0700498 rule = DefaultFlowRule.builder()
499 .forDevice(deviceId)
500 .withSelector(selector.build())
501 .withTreatment(treatment.build())
502 .withPriority(DROP_PRIORITY)
503 .fromApp(appId)
504 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700505 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700506
alshabibaebe7752015-04-07 17:45:42 -0700507
508 ops = install ? ops.add(rule) : ops.remove(rule);
509
510 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
511 @Override
512 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700513 log.info("Provisioned mac table");
alshabibaebe7752015-04-07 17:45:42 -0700514 }
515
516 @Override
517 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700518 log.info("Failed to provision mac table");
alshabibaebe7752015-04-07 17:45:42 -0700519 }
520 }));
521
522 }
523
Saurav Dasd8b97002015-05-14 23:42:49 -0700524 protected void processVlanMplsTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700525 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
526 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
527 .builder();
528 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
529 FlowRule rule;
530
531 selector.matchVlanId(VlanId.ANY);
alshabibd17abc22015-04-21 18:26:35 -0700532 treatment.transition(VLAN_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700533
alshabibd17abc22015-04-21 18:26:35 -0700534 rule = DefaultFlowRule.builder()
535 .forDevice(deviceId)
536 .withSelector(selector.build())
537 .withTreatment(treatment.build())
538 .withPriority(CONTROLLER_PRIORITY)
539 .fromApp(appId)
540 .makePermanent()
541 .forTable(VLAN_MPLS_TABLE).build();
542
alshabibaebe7752015-04-07 17:45:42 -0700543
544 ops = install ? ops.add(rule) : ops.remove(rule);
545
546 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
547 @Override
548 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700549 log.info("Provisioned vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700550 }
551
552 @Override
553 public void onError(FlowRuleOperations ops) {
554 log.info(
Saurav Das3ea46622015-04-22 14:01:34 -0700555 "Failed to provision vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700556 }
557 }));
558
559 }
560
Saurav Das3ea46622015-04-22 14:01:34 -0700561 private void processVlanTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700562 TrafficSelector.Builder selector;
563 TrafficTreatment.Builder treatment;
564 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
565 FlowRule rule;
566
567
alshabibaebe7752015-04-07 17:45:42 -0700568 //Drop rule
569 selector = DefaultTrafficSelector.builder();
570 treatment = DefaultTrafficTreatment.builder();
571
572 treatment.drop();
573
alshabibd17abc22015-04-21 18:26:35 -0700574 rule = DefaultFlowRule.builder()
575 .forDevice(deviceId)
576 .withSelector(selector.build())
577 .withTreatment(treatment.build())
578 .withPriority(DROP_PRIORITY)
579 .fromApp(appId)
580 .makePermanent()
581 .forTable(VLAN_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700582
583 ops = install ? ops.add(rule) : ops.remove(rule);
584
585 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
586 @Override
587 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700588 log.info("Provisioned vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700589 }
590
591 @Override
592 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700593 log.info("Failed to provision vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700594 }
595 }));
596 }
597
Saurav Das3ea46622015-04-22 14:01:34 -0700598 private void processEtherTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700599 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
600 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
601 .builder();
602 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
603 FlowRule rule;
604
605 selector.matchEthType(Ethernet.TYPE_ARP);
606 treatment.punt();
607
alshabibd17abc22015-04-21 18:26:35 -0700608 rule = DefaultFlowRule.builder()
609 .forDevice(deviceId)
610 .withSelector(selector.build())
611 .withTreatment(treatment.build())
612 .withPriority(CONTROLLER_PRIORITY)
613 .fromApp(appId)
614 .makePermanent()
615 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700616
617 ops = install ? ops.add(rule) : ops.remove(rule);
618
619 selector = DefaultTrafficSelector.builder();
620 treatment = DefaultTrafficTreatment.builder();
621
622 selector.matchEthType(Ethernet.TYPE_IPV4);
alshabibd17abc22015-04-21 18:26:35 -0700623 treatment.transition(COS_MAP_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700624
alshabibd17abc22015-04-21 18:26:35 -0700625 rule = DefaultFlowRule.builder()
626 .forDevice(deviceId)
627 .withPriority(CONTROLLER_PRIORITY)
628 .withSelector(selector.build())
629 .withTreatment(treatment.build())
630 .fromApp(appId)
631 .makePermanent()
632 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700633
634 ops = install ? ops.add(rule) : ops.remove(rule);
635
636 //Drop rule
637 selector = DefaultTrafficSelector.builder();
638 treatment = DefaultTrafficTreatment.builder();
639
640 treatment.drop();
641
alshabibd17abc22015-04-21 18:26:35 -0700642 rule = DefaultFlowRule.builder()
643 .forDevice(deviceId)
644 .withSelector(selector.build())
645 .withTreatment(treatment.build())
646 .withPriority(DROP_PRIORITY)
647 .fromApp(appId)
648 .makePermanent()
649 .forTable(ETHER_TABLE).build();
650
alshabibaebe7752015-04-07 17:45:42 -0700651
652 ops = install ? ops.add(rule) : ops.remove(rule);
653
654 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
655 @Override
656 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700657 log.info("Provisioned ether table");
alshabibaebe7752015-04-07 17:45:42 -0700658 }
659
660 @Override
661 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700662 log.info("Failed to provision ether table");
alshabibaebe7752015-04-07 17:45:42 -0700663 }
664 }));
665
666 }
667
Saurav Das3ea46622015-04-22 14:01:34 -0700668 private void processCosTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700669 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
670 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
671 .builder();
672 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
673 FlowRule rule;
674
alshabibd17abc22015-04-21 18:26:35 -0700675 treatment.transition(FIB_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700676
alshabibd17abc22015-04-21 18:26:35 -0700677 rule = DefaultFlowRule.builder()
678 .forDevice(deviceId)
679 .withSelector(selector.build())
680 .withTreatment(treatment.build())
681 .withPriority(DROP_PRIORITY)
682 .fromApp(appId)
683 .makePermanent()
684 .forTable(COS_MAP_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700685
686 ops = install ? ops.add(rule) : ops.remove(rule);
687
688 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
689 @Override
690 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700691 log.info("Provisioned cos table");
alshabibaebe7752015-04-07 17:45:42 -0700692 }
693
694 @Override
695 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700696 log.info("Failed to provision cos table");
alshabibaebe7752015-04-07 17:45:42 -0700697 }
698 }));
699
700 }
701
Saurav Das3ea46622015-04-22 14:01:34 -0700702 private void processFibTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700703 TrafficSelector.Builder selector;
704 TrafficTreatment.Builder treatment;
705 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
706 FlowRule rule;
707
708 //Drop rule
709 selector = DefaultTrafficSelector.builder();
710 treatment = DefaultTrafficTreatment.builder();
711
712 treatment.drop();
713
alshabibd17abc22015-04-21 18:26:35 -0700714 rule = DefaultFlowRule.builder()
715 .forDevice(deviceId)
716 .withSelector(selector.build())
717 .withTreatment(treatment.build())
718 .withPriority(DROP_PRIORITY)
719 .fromApp(appId)
720 .makePermanent()
721 .forTable(FIB_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700722
723 ops = install ? ops.add(rule) : ops.remove(rule);
724
725 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
726 @Override
727 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700728 log.info("Provisioned FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700729 }
730
731 @Override
732 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700733 log.info("Failed to provision FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700734 }
735 }));
736 }
737
Saurav Das3ea46622015-04-22 14:01:34 -0700738 private void processLocalTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700739 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
740 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
741 .builder();
742 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
743 FlowRule rule;
744
745 treatment.punt();
746
alshabibd17abc22015-04-21 18:26:35 -0700747 rule = DefaultFlowRule.builder()
748 .forDevice(deviceId)
749 .withSelector(selector.build())
750 .withTreatment(treatment.build())
751 .withPriority(CONTROLLER_PRIORITY)
752 .fromApp(appId)
753 .makePermanent()
754 .forTable(LOCAL_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700755
756 ops = install ? ops.add(rule) : ops.remove(rule);
757
758 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
759 @Override
760 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700761 log.info("Provisioned Local table");
alshabibaebe7752015-04-07 17:45:42 -0700762 }
763
764 @Override
765 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700766 log.info("Failed to provision Local table");
alshabibaebe7752015-04-07 17:45:42 -0700767 }
768 }));
769 }
770
alshabib2a441c62015-04-13 18:39:38 -0700771 private class InnerGroupListener implements GroupListener {
772 @Override
773 public void event(GroupEvent event) {
774 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
775 GroupKey key = event.subject().appCookie();
776
777 NextObjective obj = pendingGroups.getIfPresent(key);
778 if (obj != null) {
779 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
780 pass(obj);
781 pendingGroups.invalidate(key);
782 }
783 }
784 }
785 }
786
787
788 private class GroupChecker implements Runnable {
789
790 @Override
791 public void run() {
792 Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
793 .filter(key -> groupService.getGroup(deviceId, key) != null)
794 .collect(Collectors.toSet());
795
796 keys.stream().forEach(key -> {
797 NextObjective obj = pendingGroups.getIfPresent(key);
798 if (obj == null) {
799 return;
800 }
801 pass(obj);
802 pendingGroups.invalidate(key);
Saurav Dasbd7f7422015-04-23 16:31:47 -0700803 log.info("Heard back from group service for group {}. "
804 + "Applying pending forwarding objectives", obj.id());
alshabib2a441c62015-04-13 18:39:38 -0700805 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
806 });
807 }
808 }
809
810 private class CorsaGroup implements NextGroup {
811
812 private final GroupKey key;
813
814 public CorsaGroup(GroupKey key) {
815 this.key = key;
816 }
817
Saurav Dase3274c82015-05-24 17:21:56 -0700818 @SuppressWarnings("unused")
alshabib2a441c62015-04-13 18:39:38 -0700819 public GroupKey key() {
820 return key;
821 }
822
823 @Override
824 public byte[] data() {
825 return appKryo.serialize(key);
826 }
827
828 }
alshabibaebe7752015-04-07 17:45:42 -0700829}