blob: 1a57ffb02244b6c49f7db23a2e28b6cf54f37b6e [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:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700146 setupPipelineHandler(event.subject());
alshabib77b88482015-04-07 15:47:50 -0700147 break;
148 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700149 break;
alshabib77b88482015-04-07 15:47:50 -0700150 }
151 }
alshabibaebe7752015-04-07 17:45:42 -0700152 }
alshabib77b88482015-04-07 15:47:50 -0700153
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700154 // Triggers driver setup when a device is (re)detected.
alshabibaebe7752015-04-07 17:45:42 -0700155 private class InnerDeviceListener implements DeviceListener {
156 @Override
157 public void event(DeviceEvent event) {
158 switch (event.type()) {
159 case DEVICE_ADDED:
160 case DEVICE_AVAILABILITY_CHANGED:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700161 setupPipelineHandler(event.subject().id());
alshabibaebe7752015-04-07 17:45:42 -0700162 break;
163 default:
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700164 break;
alshabibaebe7752015-04-07 17:45:42 -0700165 }
alshabib77b88482015-04-07 15:47:50 -0700166 }
167 }
alshabibaebe7752015-04-07 17:45:42 -0700168
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700169 private void setupPipelineHandler(DeviceId deviceId) {
170 if (localNode.equals(mastershipService.getMasterFor(deviceId))) {
171 // Attempt to lookup the handler in the cache
172 DriverHandler handler = driverHandlers.get(deviceId);
173 if (handler == null) {
174 try {
175 // Otherwise create it and if it has pipeline behaviour, cache it
176 handler = driverService.createHandler(deviceId);
177 if (!handler.driver().hasBehaviour(Pipeliner.class)) {
178 log.warn("Pipeline behaviour not supported for device {}",
179 deviceId);
180 return;
181 }
182 } catch (ItemNotFoundException e) {
183 log.warn("No applicable driver for device {}", deviceId);
184 return;
185 }
alshabibaebe7752015-04-07 17:45:42 -0700186 driverHandlers.put(deviceId, handler);
alshabibaebe7752015-04-07 17:45:42 -0700187 }
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700188
189 // Always (re)initialize the pipeline behaviour
190 handler.behaviour(Pipeliner.class).init(deviceId, context);
191 log.info("Driver {} bound to device {}", handler.driver().name(), deviceId);
alshabibaebe7752015-04-07 17:45:42 -0700192 }
193 }
194
Thomas Vachuskaca88bb72015-04-08 19:38:02 -0700195 // Processing context for initializing pipeline driver behaviours.
196 private class InnerPipelineContext implements PipelinerContext {
197 @Override
198 public ServiceDirectory directory() {
199 return serviceDirectory;
alshabibaebe7752015-04-07 17:45:42 -0700200 }
alshabibaebe7752015-04-07 17:45:42 -0700201 }
alshabib77b88482015-04-07 15:47:50 -0700202}