blob: 3c1ec35c6ee792233b0ce3d0f5364ebb313d4bad [file] [log] [blame]
alshabib77b88482015-04-07 15:47:50 -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.net.flowobjective.impl;
17
18import com.google.common.collect.Maps;
19import org.apache.felix.scr.annotations.Activate;
20import org.apache.felix.scr.annotations.Component;
21import org.apache.felix.scr.annotations.Deactivate;
22import org.apache.felix.scr.annotations.Reference;
23import org.apache.felix.scr.annotations.ReferenceCardinality;
24import org.apache.felix.scr.annotations.Service;
25import org.onlab.osgi.DefaultServiceDirectory;
26import org.onlab.osgi.ServiceDirectory;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070027import org.onlab.util.ItemNotFoundException;
alshabib77b88482015-04-07 15:47:50 -070028import org.onosproject.cluster.ClusterService;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070029import org.onosproject.cluster.NodeId;
alshabib77b88482015-04-07 15:47:50 -070030import org.onosproject.mastership.MastershipEvent;
31import org.onosproject.mastership.MastershipListener;
32import org.onosproject.mastership.MastershipService;
alshabib77b88482015-04-07 15:47:50 -070033import org.onosproject.net.DeviceId;
34import org.onosproject.net.behaviour.Pipeliner;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070035import org.onosproject.net.behaviour.PipelinerContext;
alshabibaebe7752015-04-07 17:45:42 -070036import org.onosproject.net.device.DeviceEvent;
37import org.onosproject.net.device.DeviceListener;
alshabib77b88482015-04-07 15:47:50 -070038import org.onosproject.net.device.DeviceService;
alshabib77b88482015-04-07 15:47:50 -070039import org.onosproject.net.driver.DriverHandler;
40import org.onosproject.net.driver.DriverService;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070041import org.onosproject.net.flow.FlowRuleService;
alshabib77b88482015-04-07 15:47:50 -070042import org.onosproject.net.flowobjective.FilteringObjective;
43import org.onosproject.net.flowobjective.FlowObjectiveService;
44import org.onosproject.net.flowobjective.ForwardingObjective;
45import org.onosproject.net.flowobjective.NextObjective;
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070046import org.onosproject.net.group.GroupService;
alshabib77b88482015-04-07 15:47:50 -070047import org.slf4j.Logger;
48import org.slf4j.LoggerFactory;
49
50import java.util.Collection;
51import java.util.Map;
52import java.util.concurrent.Future;
53
54import static com.google.common.base.Preconditions.checkState;
55
56/**
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070057 * Provides implementation of the flow objective programming service.
alshabib77b88482015-04-07 15:47:50 -070058 */
59@Component(immediate = true)
60@Service
61public class FlowObjectiveManager implements FlowObjectiveService {
62
63 private final Logger log = LoggerFactory.getLogger(getClass());
64
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070065 public static final String NOT_INITIALIZED = "Driver not initialized";
66
alshabib77b88482015-04-07 15:47:50 -070067 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
68 protected DriverService driverService;
69
70 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
71 protected DeviceService deviceService;
72
73 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
74 protected MastershipService mastershipService;
75
76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
77 protected ClusterService clusterService;
78
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070079 // Note: The following dependencies are added on behalf of the pipeline
80 // driver behaviours to assure these services are available for their
81 // initialization.
82 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
83 protected FlowRuleService flowRuleService;
84
85 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
86 protected GroupService groupService;
87
88
89 private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
90
91 private final PipelinerContext context = new InnerPipelineContext();
92 private final MastershipListener mastershipListener = new InnerMastershipListener();
93 private final DeviceListener deviceListener = new InnerDeviceListener();
94
alshabib77b88482015-04-07 15:47:50 -070095 protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
Thomas Vachuskaca88bb72015-04-08 19:38:02 -070096 private NodeId localNode;
alshabib77b88482015-04-07 15:47:50 -070097
98 @Activate
99 protected void activate() {
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700100 localNode = clusterService.getLocalNode().id();
alshabib77b88482015-04-07 15:47:50 -0700101 mastershipService.addListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700102 deviceService.addListener(deviceListener);
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700103 deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id()));
alshabib77b88482015-04-07 15:47:50 -0700104 log.info("Started");
105 }
106
107 @Deactivate
108 protected void deactivate() {
109 mastershipService.removeListener(mastershipListener);
alshabibaebe7752015-04-07 17:45:42 -0700110 deviceService.removeListener(deviceListener);
alshabib77b88482015-04-07 15:47:50 -0700111 log.info("Stopped");
112 }
113
114 @Override
115 public Future<Boolean> filter(DeviceId deviceId,
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700116 Collection<FilteringObjective> filteringObjectives) {
117 return getDevicePipeliner(deviceId).filter(filteringObjectives);
alshabib77b88482015-04-07 15:47:50 -0700118 }
119
120 @Override
121 public Future<Boolean> forward(DeviceId deviceId,
122 Collection<ForwardingObjective> forwardingObjectives) {
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700123 return getDevicePipeliner(deviceId).forward(forwardingObjectives);
alshabib77b88482015-04-07 15:47:50 -0700124 }
125
126 @Override
127 public Future<Boolean> next(DeviceId deviceId,
128 Collection<NextObjective> nextObjectives) {
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700129 return getDevicePipeliner(deviceId).next(nextObjectives);
130 }
131
132 // Retrieves the device handler pipeline behaviour from the cache.
133 private Pipeliner getDevicePipeliner(DeviceId deviceId) {
alshabib77b88482015-04-07 15:47:50 -0700134 DriverHandler handler = driverHandlers.get(deviceId);
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700135 checkState(handler != null, NOT_INITIALIZED);
136 return handler != null ? handler.behaviour(Pipeliner.class) : null;
alshabib77b88482015-04-07 15:47:50 -0700137 }
138
alshabibaebe7752015-04-07 17:45:42 -0700139
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700140 // Triggers driver setup when the local node becomes a device master.
alshabib77b88482015-04-07 15:47:50 -0700141 private class InnerMastershipListener implements MastershipListener {
142 @Override
143 public void event(MastershipEvent event) {
144 switch (event.type()) {
alshabib77b88482015-04-07 15:47:50 -0700145 case MASTER_CHANGED:
alshabib4313d102015-04-08 18:55:08 -0700146 if (event.roleInfo().master() != null) {
147 setupPipelineHandler(event.subject());
148 }
149 break;
150 case BACKUPS_CHANGED:
alshabib77b88482015-04-07 15:47:50 -0700151 break;
152 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700153 break;
alshabib77b88482015-04-07 15:47:50 -0700154 }
155 }
alshabibaebe7752015-04-07 17:45:42 -0700156 }
alshabib77b88482015-04-07 15:47:50 -0700157
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700158 // Triggers driver setup when a device is (re)detected.
alshabibaebe7752015-04-07 17:45:42 -0700159 private class InnerDeviceListener implements DeviceListener {
160 @Override
161 public void event(DeviceEvent event) {
162 switch (event.type()) {
163 case DEVICE_ADDED:
164 case DEVICE_AVAILABILITY_CHANGED:
alshabib4313d102015-04-08 18:55:08 -0700165 if (deviceService.isAvailable(event.subject().id())) {
166 setupPipelineHandler(event.subject().id());
167 }
168 break;
169 case DEVICE_UPDATED:
170 break;
171 case DEVICE_REMOVED:
172 break;
173 case DEVICE_SUSPENDED:
174 break;
175 case PORT_ADDED:
176 break;
177 case PORT_UPDATED:
178 break;
179 case PORT_REMOVED:
alshabibaebe7752015-04-07 17:45:42 -0700180 break;
181 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700182 break;
alshabibaebe7752015-04-07 17:45:42 -0700183 }
alshabib77b88482015-04-07 15:47:50 -0700184 }
185 }
alshabibaebe7752015-04-07 17:45:42 -0700186
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700187 private void setupPipelineHandler(DeviceId deviceId) {
188 if (localNode.equals(mastershipService.getMasterFor(deviceId))) {
189 // Attempt to lookup the handler in the cache
190 DriverHandler handler = driverHandlers.get(deviceId);
191 if (handler == null) {
192 try {
193 // Otherwise create it and if it has pipeline behaviour, cache it
194 handler = driverService.createHandler(deviceId);
195 if (!handler.driver().hasBehaviour(Pipeliner.class)) {
196 log.warn("Pipeline behaviour not supported for device {}",
197 deviceId);
198 return;
199 }
200 } catch (ItemNotFoundException e) {
201 log.warn("No applicable driver for device {}", deviceId);
202 return;
203 }
alshabibaebe7752015-04-07 17:45:42 -0700204 driverHandlers.put(deviceId, handler);
alshabibaebe7752015-04-07 17:45:42 -0700205 }
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700206
207 // Always (re)initialize the pipeline behaviour
208 handler.behaviour(Pipeliner.class).init(deviceId, context);
209 log.info("Driver {} bound to device {}", handler.driver().name(), deviceId);
alshabibaebe7752015-04-07 17:45:42 -0700210 }
211 }
212
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700213 // Processing context for initializing pipeline driver behaviours.
214 private class InnerPipelineContext implements PipelinerContext {
215 @Override
216 public ServiceDirectory directory() {
217 return serviceDirectory;
alshabibaebe7752015-04-07 17:45:42 -0700218 }
alshabibaebe7752015-04-07 17:45:42 -0700219 }
alshabib77b88482015-04-07 15:47:50 -0700220}