blob: 95707cf1e67b3937fdbddbb0611b1cca891bed92 [file] [log] [blame]
alshabibaebe7752015-04-07 17:45:42 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
alshabibaebe7752015-04-07 17:45:42 -07003 *
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;
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -050070import org.onosproject.net.meter.MeterService;
alshabibaebe7752015-04-07 17:45:42 -070071import org.slf4j.Logger;
72
73import java.util.Collection;
alshabib2a441c62015-04-13 18:39:38 -070074import java.util.Collections;
Saurav Das24431192016-03-07 19:13:00 -080075import java.util.List;
Sho SHIMIZU45906042016-01-13 23:05:54 -080076import java.util.Objects;
alshabib2a441c62015-04-13 18:39:38 -070077import java.util.Set;
78import java.util.concurrent.Executors;
79import java.util.concurrent.ScheduledExecutorService;
80import java.util.concurrent.TimeUnit;
81import java.util.stream.Collectors;
alshabibaebe7752015-04-07 17:45:42 -070082
alshabib2a441c62015-04-13 18:39:38 -070083import static org.onlab.util.Tools.groupedThreads;
alshabibaebe7752015-04-07 17:45:42 -070084import static org.slf4j.LoggerFactory.getLogger;
85
86/**
alshabib2a441c62015-04-13 18:39:38 -070087 * OpenvSwitch emulation of the Corsa pipeline handler.
alshabibaebe7752015-04-07 17:45:42 -070088 */
Thomas Vachuskafacc3f52015-04-10 08:58:36 -070089public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner {
alshabibaebe7752015-04-07 17:45:42 -070090
Saurav Das3ea46622015-04-22 14:01:34 -070091 protected static final int MAC_TABLE = 0;
alshabibd17abc22015-04-21 18:26:35 -070092 protected static final int VLAN_MPLS_TABLE = 1;
93 protected static final int VLAN_TABLE = 2;
94 //protected static final int MPLS_TABLE = 3;
95 protected static final int ETHER_TABLE = 4;
96 protected static final int COS_MAP_TABLE = 5;
97 protected static final int FIB_TABLE = 6;
98 protected static final int LOCAL_TABLE = 9;
99
100
Saurav Dasd8b97002015-05-14 23:42:49 -0700101 protected static final int CONTROLLER_PRIORITY = 255;
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500102 protected static final int DROP_PRIORITY = 0;
103 protected static final int HIGHEST_PRIORITY = 0xffff;
alshabibaebe7752015-04-07 17:45:42 -0700104
105 private final Logger log = getLogger(getClass());
106
107 private ServiceDirectory serviceDirectory;
Saurav Dasd8b97002015-05-14 23:42:49 -0700108 protected FlowRuleService flowRuleService;
alshabibaebe7752015-04-07 17:45:42 -0700109 private CoreService coreService;
alshabib2a441c62015-04-13 18:39:38 -0700110 private GroupService groupService;
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500111 protected MeterService meterService;
alshabib2a441c62015-04-13 18:39:38 -0700112 private FlowObjectiveStore flowObjectiveStore;
Saurav Dasd8b97002015-05-14 23:42:49 -0700113 protected DeviceId deviceId;
114 protected ApplicationId appId;
alshabibaebe7752015-04-07 17:45:42 -0700115
alshabib2a441c62015-04-13 18:39:38 -0700116 private KryoNamespace appKryo = new KryoNamespace.Builder()
117 .register(GroupKey.class)
118 .register(DefaultGroupKey.class)
119 .register(CorsaGroup.class)
120 .register(byte[].class)
121 .build();
122
123 private Cache<GroupKey, NextObjective> pendingGroups;
124
125 private ScheduledExecutorService groupChecker =
126 Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
HIGUCHI Yutad9e01052016-04-14 09:31:42 -0700127 "ovs-corsa-%d",
128 log));
alshabib2a441c62015-04-13 18:39:38 -0700129
alshabibaebe7752015-04-07 17:45:42 -0700130 @Override
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700131 public void init(DeviceId deviceId, PipelinerContext context) {
132 this.serviceDirectory = context.directory();
alshabibaebe7752015-04-07 17:45:42 -0700133 this.deviceId = deviceId;
134
alshabib2a441c62015-04-13 18:39:38 -0700135 pendingGroups = CacheBuilder.newBuilder()
136 .expireAfterWrite(20, TimeUnit.SECONDS)
137 .removalListener((RemovalNotification<GroupKey, NextObjective> notification) -> {
138 if (notification.getCause() == RemovalCause.EXPIRED) {
139 fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED);
140 }
141 }).build();
142
143 groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS);
alshabibaebe7752015-04-07 17:45:42 -0700144
145 coreService = serviceDirectory.get(CoreService.class);
146 flowRuleService = serviceDirectory.get(FlowRuleService.class);
alshabib2a441c62015-04-13 18:39:38 -0700147 groupService = serviceDirectory.get(GroupService.class);
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500148 meterService = serviceDirectory.get(MeterService.class);
alshabib2a441c62015-04-13 18:39:38 -0700149 flowObjectiveStore = context.store();
150
151 groupService.addListener(new InnerGroupListener());
alshabibaebe7752015-04-07 17:45:42 -0700152
153 appId = coreService.registerApplication(
154 "org.onosproject.driver.OVSCorsaPipeline");
155
Saurav Das100e3b82015-04-30 11:12:10 -0700156 initializePipeline();
alshabibaebe7752015-04-07 17:45:42 -0700157 }
158
159 @Override
alshabib2a441c62015-04-13 18:39:38 -0700160 public void filter(FilteringObjective filteringObjective) {
161 if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
162 processFilter(filteringObjective,
163 filteringObjective.op() == Objective.Operation.ADD,
164 filteringObjective.appId());
165 } else {
166 fail(filteringObjective, ObjectiveError.UNSUPPORTED);
167 }
168 }
alshabib910aff12015-04-09 16:55:57 -0700169
alshabib2a441c62015-04-13 18:39:38 -0700170 @Override
171 public void forward(ForwardingObjective fwd) {
172 Collection<FlowRule> rules;
173 FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder();
174
175 rules = processForward(fwd);
176 switch (fwd.op()) {
177 case ADD:
178 rules.stream()
Sho SHIMIZU45906042016-01-13 23:05:54 -0800179 .filter(Objects::nonNull)
alshabib2a441c62015-04-13 18:39:38 -0700180 .forEach(flowBuilder::add);
181 break;
182 case REMOVE:
183 rules.stream()
Sho SHIMIZU45906042016-01-13 23:05:54 -0800184 .filter(Objects::nonNull)
alshabib2a441c62015-04-13 18:39:38 -0700185 .forEach(flowBuilder::remove);
186 break;
187 default:
188 fail(fwd, ObjectiveError.UNKNOWN);
189 log.warn("Unknown forwarding type {}", fwd.op());
190 }
191
192
193 flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() {
194 @Override
195 public void onSuccess(FlowRuleOperations ops) {
196 pass(fwd);
197 }
198
199 @Override
200 public void onError(FlowRuleOperations ops) {
201 fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
202 }
203 }));
alshabib910aff12015-04-09 16:55:57 -0700204
205 }
206
alshabib2a441c62015-04-13 18:39:38 -0700207 @Override
208 public void next(NextObjective nextObjective) {
209 switch (nextObjective.type()) {
210 case SIMPLE:
211 Collection<TrafficTreatment> treatments = nextObjective.next();
212 if (treatments.size() == 1) {
213 TrafficTreatment treatment = treatments.iterator().next();
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500214 treatment = processNextTreatment(treatment);
alshabib2a441c62015-04-13 18:39:38 -0700215 GroupBucket bucket =
216 DefaultGroupBucket.createIndirectGroupBucket(treatment);
217 final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id()));
218 GroupDescription groupDescription
219 = new DefaultGroupDescription(deviceId,
220 GroupDescription.Type.INDIRECT,
221 new GroupBuckets(Collections
222 .singletonList(bucket)),
223 key,
Saurav Das100e3b82015-04-30 11:12:10 -0700224 null, // let group service determine group id
alshabib2a441c62015-04-13 18:39:38 -0700225 nextObjective.appId());
226 groupService.addGroup(groupDescription);
227 pendingGroups.put(key, nextObjective);
228 }
229 break;
230 case HASHED:
231 case BROADCAST:
232 case FAILOVER:
233 fail(nextObjective, ObjectiveError.UNSUPPORTED);
234 log.warn("Unsupported next objective type {}", nextObjective.type());
235 break;
236 default:
237 fail(nextObjective, ObjectiveError.UNKNOWN);
238 log.warn("Unknown next objective type {}", nextObjective.type());
239 }
240
241 }
242
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500243 /* Hook for altering the NextObjective treatment */
244 protected TrafficTreatment processNextTreatment(TrafficTreatment treatment) {
245 return treatment; /* Keep treatment as is for OVSCorsaPipeline */
246 }
247
alshabib2a441c62015-04-13 18:39:38 -0700248 private Collection<FlowRule> processForward(ForwardingObjective fwd) {
249 switch (fwd.flag()) {
250 case SPECIFIC:
251 return processSpecific(fwd);
252 case VERSATILE:
253 return processVersatile(fwd);
254 default:
255 fail(fwd, ObjectiveError.UNKNOWN);
256 log.warn("Unknown forwarding flag {}", fwd.flag());
257 }
258 return Collections.emptySet();
259 }
260
261 private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
Saurav Das3d038262015-04-23 12:36:58 -0700262 log.debug("Processing versatile forwarding objective");
263 TrafficSelector selector = fwd.selector();
264
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700265 EthTypeCriterion ethType =
266 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
Saurav Das3d038262015-04-23 12:36:58 -0700267 if (ethType == null) {
268 log.error("Versatile forwarding objective must include ethType");
269 fail(fwd, ObjectiveError.UNKNOWN);
270 return Collections.emptySet();
271 }
alshabibcaf1ca22015-06-25 15:18:16 -0700272 if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) {
Saurav Das3d038262015-04-23 12:36:58 -0700273 log.warn("Driver automatically handles ARP packets by punting to controller "
274 + " from ETHER table");
275 pass(fwd);
276 return Collections.emptySet();
alshabibcaf1ca22015-06-25 15:18:16 -0700277 } else if (ethType.ethType().toShort() == Ethernet.TYPE_LLDP ||
278 ethType.ethType().toShort() == Ethernet.TYPE_BSN) {
Saurav Das3d038262015-04-23 12:36:58 -0700279 log.warn("Driver currently does not currently handle LLDP packets");
280 fail(fwd, ObjectiveError.UNSUPPORTED);
281 return Collections.emptySet();
alshabibcaf1ca22015-06-25 15:18:16 -0700282 } else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700283 IPCriterion ipSrc = (IPCriterion) selector
Saurav Das3d038262015-04-23 12:36:58 -0700284 .getCriterion(Criterion.Type.IPV4_SRC);
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700285 IPCriterion ipDst = (IPCriterion) selector
Saurav Das3d038262015-04-23 12:36:58 -0700286 .getCriterion(Criterion.Type.IPV4_DST);
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700287 IPProtocolCriterion ipProto = (IPProtocolCriterion) selector
Saurav Das3d038262015-04-23 12:36:58 -0700288 .getCriterion(Criterion.Type.IP_PROTO);
289 if (ipSrc != null) {
Saurav Dasbd7f7422015-04-23 16:31:47 -0700290 log.warn("Driver does not currently handle matching Src IP");
Saurav Das3d038262015-04-23 12:36:58 -0700291 fail(fwd, ObjectiveError.UNSUPPORTED);
292 return Collections.emptySet();
293 }
294 if (ipDst != null) {
295 log.error("Driver handles Dst IP matching as specific forwarding "
296 + "objective, not versatile");
297 fail(fwd, ObjectiveError.UNSUPPORTED);
298 return Collections.emptySet();
299 }
300 if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) {
301 log.warn("Driver automatically punts all packets reaching the "
302 + "LOCAL table to the controller");
303 pass(fwd);
304 return Collections.emptySet();
305 }
306 }
307
308 log.warn("Driver does not support given versatile forwarding objective");
alshabib2a441c62015-04-13 18:39:38 -0700309 fail(fwd, ObjectiveError.UNSUPPORTED);
310 return Collections.emptySet();
311 }
312
313 private Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
Saurav Das3d038262015-04-23 12:36:58 -0700314 log.debug("Processing specific forwarding objective");
alshabib2a441c62015-04-13 18:39:38 -0700315 TrafficSelector selector = fwd.selector();
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500316
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700317 EthTypeCriterion ethType =
318 (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500319 if (ethType != null) {
320 short et = ethType.ethType().toShort();
321 if (et == Ethernet.TYPE_IPV4) {
322 return processSpecificRoute(fwd);
323 } else if (et == Ethernet.TYPE_VLAN) {
324 /* The ForwardingObjective must specify VLAN ethtype in order to use the Transit Circuit */
325 return processSpecificSwitch(fwd);
326 }
alshabib2a441c62015-04-13 18:39:38 -0700327 }
328
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500329 fail(fwd, ObjectiveError.UNSUPPORTED);
330 return Collections.emptySet();
331 }
332
333 private Collection<FlowRule> processSpecificRoute(ForwardingObjective fwd) {
alshabib2a441c62015-04-13 18:39:38 -0700334 TrafficSelector filteredSelector =
335 DefaultTrafficSelector.builder()
336 .matchEthType(Ethernet.TYPE_IPV4)
337 .matchIPDst(
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500338 ((IPCriterion) fwd.selector().getCriterion(Criterion.Type.IPV4_DST)).ip())
alshabib2a441c62015-04-13 18:39:38 -0700339 .build();
340
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500341 TrafficTreatment.Builder tb = processSpecificRoutingTreatment();
alshabib2a441c62015-04-13 18:39:38 -0700342
sanghodde53d12015-04-30 10:34:41 -0700343 if (fwd.nextId() != null) {
344 NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
345 GroupKey key = appKryo.deserialize(next.data());
346 Group group = groupService.getGroup(deviceId, key);
347 if (group == null) {
348 log.warn("The group left!");
349 fail(fwd, ObjectiveError.GROUPMISSING);
350 return Collections.emptySet();
351 }
352 tb.group(group.id());
alshabib2a441c62015-04-13 18:39:38 -0700353 }
354
alshabibd17abc22015-04-21 18:26:35 -0700355 FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
356 .fromApp(fwd.appId())
357 .withPriority(fwd.priority())
358 .forDevice(deviceId)
359 .withSelector(filteredSelector)
sanghodde53d12015-04-30 10:34:41 -0700360 .withTreatment(tb.build());
alshabibd17abc22015-04-21 18:26:35 -0700361
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500362 ruleBuilder = processSpecificRoutingRule(ruleBuilder);
363
alshabibd17abc22015-04-21 18:26:35 -0700364 if (fwd.permanent()) {
365 ruleBuilder.makePermanent();
366 } else {
367 ruleBuilder.makeTemporary(fwd.timeout());
368 }
369
alshabibd17abc22015-04-21 18:26:35 -0700370 return Collections.singletonList(ruleBuilder.build());
alshabib2a441c62015-04-13 18:39:38 -0700371 }
372
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500373 /* Hook for modifying Route traffic treatment */
374 protected TrafficTreatment.Builder processSpecificRoutingTreatment() {
375 return DefaultTrafficTreatment.builder();
376 }
377
378 /* Hook for modifying Route flow rule */
379 protected FlowRule.Builder processSpecificRoutingRule(FlowRule.Builder rb) {
380 return rb.forTable(FIB_TABLE);
381 }
382
383 protected Collection<FlowRule> processSpecificSwitch(ForwardingObjective fwd) {
384 /* Not supported by until CorsaPipelineV3 */
385 log.warn("Vlan switching not supported in ovs-corsa driver");
386 fail(fwd, ObjectiveError.UNSUPPORTED);
387 return Collections.emptySet();
388 }
389
390 protected void processFilter(FilteringObjective filt, boolean install,
alshabib910aff12015-04-09 16:55:57 -0700391 ApplicationId applicationId) {
Saurav Dascfd63d22015-04-13 16:08:24 -0700392 // This driver only processes filtering criteria defined with switch
393 // ports as the key
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700394 PortCriterion p;
Saurav Dascfd63d22015-04-13 16:08:24 -0700395 if (!filt.key().equals(Criteria.dummy()) &&
396 filt.key().type() == Criterion.Type.IN_PORT) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700397 p = (PortCriterion) filt.key();
Saurav Dascfd63d22015-04-13 16:08:24 -0700398 } else {
399 log.warn("No key defined in filtering objective from app: {}. Not"
400 + "processing filtering objective", applicationId);
alshabib2a441c62015-04-13 18:39:38 -0700401 fail(filt, ObjectiveError.UNKNOWN);
402 return;
alshabib910aff12015-04-09 16:55:57 -0700403 }
Saurav Dascfd63d22015-04-13 16:08:24 -0700404 // convert filtering conditions for switch-intfs into flowrules
405 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
406 for (Criterion c : filt.conditions()) {
407 if (c.type() == Criterion.Type.ETH_DST) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700408 EthCriterion e = (EthCriterion) c;
Saurav Dascfd63d22015-04-13 16:08:24 -0700409 log.debug("adding rule for MAC: {}", e.mac());
410 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
411 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
412 selector.matchEthDst(e.mac());
alshabibd17abc22015-04-21 18:26:35 -0700413 treatment.transition(VLAN_MPLS_TABLE);
414 FlowRule rule = DefaultFlowRule.builder()
415 .forDevice(deviceId)
416 .withSelector(selector.build())
417 .withTreatment(treatment.build())
418 .withPriority(CONTROLLER_PRIORITY)
419 .fromApp(applicationId)
420 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700421 .forTable(MAC_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700422 ops = install ? ops.add(rule) : ops.remove(rule);
423 } else if (c.type() == Criterion.Type.VLAN_VID) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700424 VlanIdCriterion v = (VlanIdCriterion) c;
Saurav Dascfd63d22015-04-13 16:08:24 -0700425 log.debug("adding rule for VLAN: {}", v.vlanId());
426 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
427 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
428 selector.matchVlanId(v.vlanId());
429 selector.matchInPort(p.port());
alshabibd17abc22015-04-21 18:26:35 -0700430 treatment.transition(ETHER_TABLE);
Saurav Dascfd63d22015-04-13 16:08:24 -0700431 treatment.deferred().popVlan();
alshabibd17abc22015-04-21 18:26:35 -0700432 FlowRule rule = DefaultFlowRule.builder()
433 .forDevice(deviceId)
434 .withSelector(selector.build())
435 .withTreatment(treatment.build())
436 .withPriority(CONTROLLER_PRIORITY)
437 .fromApp(applicationId)
438 .makePermanent()
439 .forTable(VLAN_TABLE).build();
Saurav Dascfd63d22015-04-13 16:08:24 -0700440 ops = install ? ops.add(rule) : ops.remove(rule);
441 } else if (c.type() == Criterion.Type.IPV4_DST) {
Sho SHIMIZUfbc80e52015-04-28 10:41:58 -0700442 IPCriterion ip = (IPCriterion) c;
Saurav Dascfd63d22015-04-13 16:08:24 -0700443 log.debug("adding rule for IP: {}", ip.ip());
444 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
445 TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
446 selector.matchEthType(Ethernet.TYPE_IPV4);
447 selector.matchIPDst(ip.ip());
alshabibd17abc22015-04-21 18:26:35 -0700448 treatment.transition(LOCAL_TABLE);
449 FlowRule rule = DefaultFlowRule.builder()
450 .forDevice(deviceId)
451 .withSelector(selector.build())
452 .withTreatment(treatment.build())
453 .withPriority(HIGHEST_PRIORITY)
454 .fromApp(applicationId)
455 .makePermanent()
456 .forTable(FIB_TABLE).build();
457
Saurav Dascfd63d22015-04-13 16:08:24 -0700458 ops = install ? ops.add(rule) : ops.remove(rule);
459 } else {
460 log.warn("Driver does not currently process filtering condition"
461 + " of type: {}", c.type());
alshabib2a441c62015-04-13 18:39:38 -0700462 fail(filt, ObjectiveError.UNSUPPORTED);
Saurav Dascfd63d22015-04-13 16:08:24 -0700463 }
464 }
465 // apply filtering flow rules
466 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
467 @Override
468 public void onSuccess(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700469 pass(filt);
Saurav Das3ea46622015-04-22 14:01:34 -0700470 log.info("Applied filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700471 }
472
473 @Override
474 public void onError(FlowRuleOperations ops) {
alshabib2a441c62015-04-13 18:39:38 -0700475 fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
Saurav Das3ea46622015-04-22 14:01:34 -0700476 log.info("Failed to apply filtering rules");
Saurav Dascfd63d22015-04-13 16:08:24 -0700477 }
478 }));
alshabibaebe7752015-04-07 17:45:42 -0700479 }
480
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500481 protected void pass(Objective obj) {
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800482 obj.context().ifPresent(context -> context.onSuccess(obj));
alshabibaebe7752015-04-07 17:45:42 -0700483 }
484
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500485 protected void fail(Objective obj, ObjectiveError error) {
Sho SHIMIZUef7e2902016-02-12 18:38:29 -0800486 obj.context().ifPresent(context -> context.onError(obj, error));
alshabibaebe7752015-04-07 17:45:42 -0700487 }
488
Jonathan Gravel8c9f7bc2015-12-03 15:46:20 -0500489 protected void initializePipeline() {
Saurav Das3ea46622015-04-22 14:01:34 -0700490 processMacTable(true);
491 processVlanMplsTable(true);
492 processVlanTable(true);
493 processEtherTable(true);
494 processCosTable(true);
495 processFibTable(true);
496 processLocalTable(true);
alshabibaebe7752015-04-07 17:45:42 -0700497 }
498
Saurav Das3ea46622015-04-22 14:01:34 -0700499 private void processMacTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700500 TrafficSelector.Builder selector;
501 TrafficTreatment.Builder treatment;
502
503 // Bcast rule
504 selector = DefaultTrafficSelector.builder();
505 treatment = DefaultTrafficTreatment.builder();
506
507 selector.matchEthDst(MacAddress.BROADCAST);
alshabibd17abc22015-04-21 18:26:35 -0700508 treatment.transition(VLAN_MPLS_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700509
alshabibd17abc22015-04-21 18:26:35 -0700510 FlowRule rule = DefaultFlowRule.builder()
511 .forDevice(deviceId)
512 .withSelector(selector.build())
513 .withTreatment(treatment.build())
514 .withPriority(CONTROLLER_PRIORITY)
515 .fromApp(appId)
516 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700517 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700518
alshabibaebe7752015-04-07 17:45:42 -0700519
520 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
521
522 ops = install ? ops.add(rule) : ops.remove(rule);
523
524
alshabibaebe7752015-04-07 17:45:42 -0700525 //Drop rule
526 selector = DefaultTrafficSelector.builder();
527 treatment = DefaultTrafficTreatment.builder();
528
529 treatment.drop();
530
alshabibd17abc22015-04-21 18:26:35 -0700531 rule = DefaultFlowRule.builder()
532 .forDevice(deviceId)
533 .withSelector(selector.build())
534 .withTreatment(treatment.build())
535 .withPriority(DROP_PRIORITY)
536 .fromApp(appId)
537 .makePermanent()
Saurav Das3ea46622015-04-22 14:01:34 -0700538 .forTable(MAC_TABLE).build();
alshabibd17abc22015-04-21 18:26:35 -0700539
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 mac table");
alshabibaebe7752015-04-07 17:45:42 -0700547 }
548
549 @Override
550 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700551 log.info("Failed to provision mac table");
alshabibaebe7752015-04-07 17:45:42 -0700552 }
553 }));
554
555 }
556
Saurav Dasd8b97002015-05-14 23:42:49 -0700557 protected void processVlanMplsTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700558 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
559 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
560 .builder();
561 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
562 FlowRule rule;
563
564 selector.matchVlanId(VlanId.ANY);
alshabibd17abc22015-04-21 18:26:35 -0700565 treatment.transition(VLAN_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700566
alshabibd17abc22015-04-21 18:26:35 -0700567 rule = DefaultFlowRule.builder()
568 .forDevice(deviceId)
569 .withSelector(selector.build())
570 .withTreatment(treatment.build())
571 .withPriority(CONTROLLER_PRIORITY)
572 .fromApp(appId)
573 .makePermanent()
574 .forTable(VLAN_MPLS_TABLE).build();
575
alshabibaebe7752015-04-07 17:45:42 -0700576
577 ops = install ? ops.add(rule) : ops.remove(rule);
578
579 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
580 @Override
581 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700582 log.info("Provisioned vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700583 }
584
585 @Override
586 public void onError(FlowRuleOperations ops) {
587 log.info(
Saurav Das3ea46622015-04-22 14:01:34 -0700588 "Failed to provision vlan/mpls table");
alshabibaebe7752015-04-07 17:45:42 -0700589 }
590 }));
591
592 }
593
Saurav Das3ea46622015-04-22 14:01:34 -0700594 private void processVlanTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700595 TrafficSelector.Builder selector;
596 TrafficTreatment.Builder treatment;
597 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
598 FlowRule rule;
599
600
alshabibaebe7752015-04-07 17:45:42 -0700601 //Drop rule
602 selector = DefaultTrafficSelector.builder();
603 treatment = DefaultTrafficTreatment.builder();
604
605 treatment.drop();
606
alshabibd17abc22015-04-21 18:26:35 -0700607 rule = DefaultFlowRule.builder()
608 .forDevice(deviceId)
609 .withSelector(selector.build())
610 .withTreatment(treatment.build())
611 .withPriority(DROP_PRIORITY)
612 .fromApp(appId)
613 .makePermanent()
614 .forTable(VLAN_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700615
616 ops = install ? ops.add(rule) : ops.remove(rule);
617
618 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
619 @Override
620 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700621 log.info("Provisioned vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700622 }
623
624 @Override
625 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700626 log.info("Failed to provision vlan table");
alshabibaebe7752015-04-07 17:45:42 -0700627 }
628 }));
629 }
630
Saurav Das3ea46622015-04-22 14:01:34 -0700631 private void processEtherTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700632 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
633 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
634 .builder();
635 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
636 FlowRule rule;
637
638 selector.matchEthType(Ethernet.TYPE_ARP);
639 treatment.punt();
640
alshabibd17abc22015-04-21 18:26:35 -0700641 rule = DefaultFlowRule.builder()
642 .forDevice(deviceId)
643 .withSelector(selector.build())
644 .withTreatment(treatment.build())
645 .withPriority(CONTROLLER_PRIORITY)
646 .fromApp(appId)
647 .makePermanent()
648 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700649
650 ops = install ? ops.add(rule) : ops.remove(rule);
651
652 selector = DefaultTrafficSelector.builder();
653 treatment = DefaultTrafficTreatment.builder();
654
655 selector.matchEthType(Ethernet.TYPE_IPV4);
alshabibd17abc22015-04-21 18:26:35 -0700656 treatment.transition(COS_MAP_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700657
alshabibd17abc22015-04-21 18:26:35 -0700658 rule = DefaultFlowRule.builder()
659 .forDevice(deviceId)
660 .withPriority(CONTROLLER_PRIORITY)
661 .withSelector(selector.build())
662 .withTreatment(treatment.build())
663 .fromApp(appId)
664 .makePermanent()
665 .forTable(ETHER_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700666
667 ops = install ? ops.add(rule) : ops.remove(rule);
668
669 //Drop rule
670 selector = DefaultTrafficSelector.builder();
671 treatment = DefaultTrafficTreatment.builder();
672
673 treatment.drop();
674
alshabibd17abc22015-04-21 18:26:35 -0700675 rule = DefaultFlowRule.builder()
676 .forDevice(deviceId)
677 .withSelector(selector.build())
678 .withTreatment(treatment.build())
679 .withPriority(DROP_PRIORITY)
680 .fromApp(appId)
681 .makePermanent()
682 .forTable(ETHER_TABLE).build();
683
alshabibaebe7752015-04-07 17:45:42 -0700684
685 ops = install ? ops.add(rule) : ops.remove(rule);
686
687 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
688 @Override
689 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700690 log.info("Provisioned ether table");
alshabibaebe7752015-04-07 17:45:42 -0700691 }
692
693 @Override
694 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700695 log.info("Failed to provision ether table");
alshabibaebe7752015-04-07 17:45:42 -0700696 }
697 }));
698
699 }
700
Saurav Das3ea46622015-04-22 14:01:34 -0700701 private void processCosTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700702 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
703 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
704 .builder();
705 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
706 FlowRule rule;
707
alshabibd17abc22015-04-21 18:26:35 -0700708 treatment.transition(FIB_TABLE);
alshabibaebe7752015-04-07 17:45:42 -0700709
alshabibd17abc22015-04-21 18:26:35 -0700710 rule = DefaultFlowRule.builder()
711 .forDevice(deviceId)
712 .withSelector(selector.build())
713 .withTreatment(treatment.build())
714 .withPriority(DROP_PRIORITY)
715 .fromApp(appId)
716 .makePermanent()
717 .forTable(COS_MAP_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700718
719 ops = install ? ops.add(rule) : ops.remove(rule);
720
721 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
722 @Override
723 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700724 log.info("Provisioned cos table");
alshabibaebe7752015-04-07 17:45:42 -0700725 }
726
727 @Override
728 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700729 log.info("Failed to provision cos table");
alshabibaebe7752015-04-07 17:45:42 -0700730 }
731 }));
732
733 }
734
Saurav Das3ea46622015-04-22 14:01:34 -0700735 private void processFibTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700736 TrafficSelector.Builder selector;
737 TrafficTreatment.Builder treatment;
738 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
739 FlowRule rule;
740
741 //Drop rule
742 selector = DefaultTrafficSelector.builder();
743 treatment = DefaultTrafficTreatment.builder();
744
745 treatment.drop();
746
alshabibd17abc22015-04-21 18:26:35 -0700747 rule = DefaultFlowRule.builder()
748 .forDevice(deviceId)
749 .withSelector(selector.build())
750 .withTreatment(treatment.build())
751 .withPriority(DROP_PRIORITY)
752 .fromApp(appId)
753 .makePermanent()
754 .forTable(FIB_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 FIB 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 FIB table");
alshabibaebe7752015-04-07 17:45:42 -0700767 }
768 }));
769 }
770
Saurav Das3ea46622015-04-22 14:01:34 -0700771 private void processLocalTable(boolean install) {
alshabibaebe7752015-04-07 17:45:42 -0700772 TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
773 TrafficTreatment.Builder treatment = DefaultTrafficTreatment
774 .builder();
775 FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
776 FlowRule rule;
777
778 treatment.punt();
779
alshabibd17abc22015-04-21 18:26:35 -0700780 rule = DefaultFlowRule.builder()
781 .forDevice(deviceId)
782 .withSelector(selector.build())
783 .withTreatment(treatment.build())
784 .withPriority(CONTROLLER_PRIORITY)
785 .fromApp(appId)
786 .makePermanent()
787 .forTable(LOCAL_TABLE).build();
alshabibaebe7752015-04-07 17:45:42 -0700788
789 ops = install ? ops.add(rule) : ops.remove(rule);
790
791 flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
792 @Override
793 public void onSuccess(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700794 log.info("Provisioned Local table");
alshabibaebe7752015-04-07 17:45:42 -0700795 }
796
797 @Override
798 public void onError(FlowRuleOperations ops) {
Saurav Das3ea46622015-04-22 14:01:34 -0700799 log.info("Failed to provision Local table");
alshabibaebe7752015-04-07 17:45:42 -0700800 }
801 }));
802 }
803
alshabib2a441c62015-04-13 18:39:38 -0700804 private class InnerGroupListener implements GroupListener {
805 @Override
806 public void event(GroupEvent event) {
807 if (event.type() == GroupEvent.Type.GROUP_ADDED) {
808 GroupKey key = event.subject().appCookie();
809
810 NextObjective obj = pendingGroups.getIfPresent(key);
811 if (obj != null) {
812 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
813 pass(obj);
814 pendingGroups.invalidate(key);
815 }
816 }
817 }
818 }
819
820
821 private class GroupChecker implements Runnable {
822
823 @Override
824 public void run() {
825 Set<GroupKey> keys = pendingGroups.asMap().keySet().stream()
826 .filter(key -> groupService.getGroup(deviceId, key) != null)
827 .collect(Collectors.toSet());
828
829 keys.stream().forEach(key -> {
830 NextObjective obj = pendingGroups.getIfPresent(key);
831 if (obj == null) {
832 return;
833 }
834 pass(obj);
835 pendingGroups.invalidate(key);
Saurav Dasbd7f7422015-04-23 16:31:47 -0700836 log.info("Heard back from group service for group {}. "
837 + "Applying pending forwarding objectives", obj.id());
alshabib2a441c62015-04-13 18:39:38 -0700838 flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key));
839 });
840 }
841 }
842
843 private class CorsaGroup implements NextGroup {
844
845 private final GroupKey key;
846
847 public CorsaGroup(GroupKey key) {
848 this.key = key;
849 }
850
Saurav Dase3274c82015-05-24 17:21:56 -0700851 @SuppressWarnings("unused")
alshabib2a441c62015-04-13 18:39:38 -0700852 public GroupKey key() {
853 return key;
854 }
855
856 @Override
857 public byte[] data() {
858 return appKryo.serialize(key);
859 }
860
861 }
Saurav Das24431192016-03-07 19:13:00 -0800862
863 @Override
864 public List<String> getNextMappings(NextGroup nextGroup) {
865 // TODO Implementation deferred to vendor
866 return null;
867 }
alshabibaebe7752015-04-07 17:45:42 -0700868}