Thomas Vachuska

Cleaning up and enhancing driver subsystem and the flow objective subsystem.

Change-Id: Ica600ef1aaa46d19e764cd7a197454a4e0f85a08
Showing 22 changed files with 361 additions and 130 deletions
...@@ -50,6 +50,11 @@ public final class AnnotationKeys { ...@@ -50,6 +50,11 @@ public final class AnnotationKeys {
50 public static final String PROTOCOL = "protocol"; 50 public static final String PROTOCOL = "protocol";
51 51
52 /** 52 /**
53 + * Annotation key for the device driver name.
54 + */
55 + public static final String DRIVER = "driver";
56 +
57 + /**
53 * Annotation key for durable links. 58 * Annotation key for durable links.
54 */ 59 */
55 public static final String DURABLE = "durable"; 60 public static final String DURABLE = "durable";
......
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
15 */ 15 */
16 package org.onosproject.net.behaviour; 16 package org.onosproject.net.behaviour;
17 17
18 -import org.onlab.osgi.ServiceDirectory;
19 import org.onosproject.net.DeviceId; 18 import org.onosproject.net.DeviceId;
20 import org.onosproject.net.driver.HandlerBehaviour; 19 import org.onosproject.net.driver.HandlerBehaviour;
21 import org.onosproject.net.flowobjective.FilteringObjective; 20 import org.onosproject.net.flowobjective.FilteringObjective;
...@@ -31,20 +30,20 @@ import java.util.concurrent.Future; ...@@ -31,20 +30,20 @@ import java.util.concurrent.Future;
31 public interface Pipeliner extends HandlerBehaviour { 30 public interface Pipeliner extends HandlerBehaviour {
32 31
33 /** 32 /**
34 - * Injecting the service directory into the driver. 33 + * Initializes the driver with context required for its operation.
35 * 34 *
36 * @param deviceId the deviceId 35 * @param deviceId the deviceId
37 - * @param serviceDirectory the service directory. 36 + * @param context processing context
38 */ 37 */
39 - void init(DeviceId deviceId, ServiceDirectory serviceDirectory); 38 + void init(DeviceId deviceId, PipelinerContext context);
40 39
41 /** 40 /**
42 * Installs the filtering rules onto the device. 41 * Installs the filtering rules onto the device.
43 * 42 *
44 - * @param filteringObjectives the collection of filters 43 + * @param filterObjectives the collection of filters
45 * @return a future indicating the success of the operation 44 * @return a future indicating the success of the operation
46 */ 45 */
47 - Future<Boolean> filter(Collection<FilteringObjective> filteringObjectives); 46 + Future<Boolean> filter(Collection<FilteringObjective> filterObjectives);
48 47
49 /** 48 /**
50 * Installs the forwarding rules onto the device. 49 * Installs the forwarding rules onto the device.
......
1 +/*
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 + */
16 +package org.onosproject.net.behaviour;
17 +
18 +import org.onlab.osgi.ServiceDirectory;
19 +
20 +/**
21 + * Processing context and supporting services for the pipeline behaviour.
22 + */
23 +public interface PipelinerContext {
24 +
25 + /**
26 + * Returns the service directory which can be used to obtain references
27 + * to various supporting services.
28 + *
29 + * @return service directory
30 + */
31 + ServiceDirectory directory();
32 +
33 + // TODO: add means to store and access shared state
34 +}
...@@ -29,27 +29,27 @@ import static com.google.common.base.MoreObjects.toStringHelper; ...@@ -29,27 +29,27 @@ import static com.google.common.base.MoreObjects.toStringHelper;
29 */ 29 */
30 public class DefaultDriverData implements DriverData { 30 public class DefaultDriverData implements DriverData {
31 31
32 - private final Driver type; 32 + private final Driver driver;
33 private final Map<String, String> properties; 33 private final Map<String, String> properties;
34 34
35 /** 35 /**
36 * Creates new driver data. 36 * Creates new driver data.
37 * 37 *
38 - * @param type parent driver type 38 + * @param driver parent driver type
39 */ 39 */
40 - public DefaultDriverData(Driver type) { 40 + public DefaultDriverData(Driver driver) {
41 - this.type = type; 41 + this.driver = driver;
42 this.properties = new HashMap<>(); 42 this.properties = new HashMap<>();
43 } 43 }
44 44
45 @Override 45 @Override
46 - public Driver type() { 46 + public Driver driver() {
47 - return type; 47 + return driver;
48 } 48 }
49 49
50 @Override 50 @Override
51 public <T extends Behaviour> T behaviour(Class<T> behaviourClass) { 51 public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
52 - return type.createBehaviour(this, behaviourClass, false); 52 + return driver.createBehaviour(this, behaviourClass, false);
53 } 53 }
54 54
55 @Override 55 @Override
...@@ -83,7 +83,7 @@ public class DefaultDriverData implements DriverData { ...@@ -83,7 +83,7 @@ public class DefaultDriverData implements DriverData {
83 @Override 83 @Override
84 public String toString() { 84 public String toString() {
85 return toStringHelper(this) 85 return toStringHelper(this)
86 - .add("type", type) 86 + .add("type", driver)
87 .add("properties", properties) 87 .add("properties", properties)
88 .toString(); 88 .toString();
89 } 89 }
......
...@@ -34,13 +34,18 @@ public class DefaultDriverHandler implements DriverHandler { ...@@ -34,13 +34,18 @@ public class DefaultDriverHandler implements DriverHandler {
34 } 34 }
35 35
36 @Override 36 @Override
37 + public Driver driver() {
38 + return data.driver();
39 + }
40 +
41 + @Override
37 public DriverData data() { 42 public DriverData data() {
38 return data; 43 return data;
39 } 44 }
40 45
41 @Override 46 @Override
42 public <T extends Behaviour> T behaviour(Class<T> behaviourClass) { 47 public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
43 - return data.type().createBehaviour(this.data, behaviourClass, true); 48 + return data.driver().createBehaviour(this.data, behaviourClass, true);
44 } 49 }
45 50
46 @Override 51 @Override
......
...@@ -28,7 +28,7 @@ public interface DriverData extends MutableAnnotations { ...@@ -28,7 +28,7 @@ public interface DriverData extends MutableAnnotations {
28 * 28 *
29 * @return device driver 29 * @return device driver
30 */ 30 */
31 - Driver type(); 31 + Driver driver();
32 32
33 /** 33 /**
34 * Returns the specified facet of behaviour to access the device data. 34 * Returns the specified facet of behaviour to access the device data.
......
...@@ -21,6 +21,13 @@ package org.onosproject.net.driver; ...@@ -21,6 +21,13 @@ package org.onosproject.net.driver;
21 public interface DriverHandler { 21 public interface DriverHandler {
22 22
23 /** 23 /**
24 + * Returns the parent device driver.
25 + *
26 + * @return device driver
27 + */
28 + Driver driver();
29 +
30 + /**
24 * Returns the device driver data. 31 * Returns the device driver data.
25 * 32 *
26 * @return device driver data 33 * @return device driver data
......
...@@ -38,6 +38,8 @@ public interface DriverService { ...@@ -38,6 +38,8 @@ public interface DriverService {
38 * 38 *
39 * @param driverName driver name 39 * @param driverName driver name
40 * @return driver 40 * @return driver
41 + * @throws org.onlab.util.ItemNotFoundException if driver with the given
42 + * name is not found
41 */ 43 */
42 Driver getDriver(String driverName); 44 Driver getDriver(String driverName);
43 45
...@@ -53,25 +55,33 @@ public interface DriverService { ...@@ -53,25 +55,33 @@ public interface DriverService {
53 Driver getDriver(String mfr, String hw, String sw); 55 Driver getDriver(String mfr, String hw, String sw);
54 56
55 /** 57 /**
56 - * Creates a new driver handler for the specified driver. 58 + * Returns the driver for the specified device. If the device carries
59 + * {@code driver} annotation, its value is used to look-up the driver.
60 + * Otherwise, the device manufacturer, hardware and software version
61 + * attributes are used to look-up the driver. First using their literal
62 + * values and if no driver is found, using ERE matching against the
63 + * driver manufacturer, hardware and software version fields.
57 * 64 *
58 - * @param driverName driver name 65 + * @param deviceId device identifier
59 - * @param deviceId device identifier 66 + * @return driver or null of no matching one is found
60 - * @param credentials optional login credentials in string form 67 + * @throws org.onlab.util.ItemNotFoundException if device or driver for it
61 - * @return driver handler 68 + * are not found
62 */ 69 */
63 - DriverHandler createHandler(String driverName, DeviceId deviceId, 70 + Driver getDriver(DeviceId deviceId);
64 - String... credentials);
65 71
66 /** 72 /**
67 - * Creates a new driver handler for the specified driver data. 73 + * Creates a new driver handler for interacting with the specified device.
74 + * The driver is looked-up using the same semantics as
75 + * {@link #getDriver(DeviceId)} method.
68 * 76 *
69 - * @param data driver data
70 * @param deviceId device identifier 77 * @param deviceId device identifier
71 * @param credentials optional login credentials in string form 78 * @param credentials optional login credentials in string form
72 * @return driver handler 79 * @return driver handler
80 + * @throws org.onlab.util.ItemNotFoundException if device or driver for it
81 + * are not found
73 */ 82 */
74 - DriverHandler createHandler(DriverData data, DeviceId deviceId, 83 + DriverHandler createHandler(DeviceId deviceId, String... credentials);
75 - String... credentials); 84 +
85 + // TODO: Devise a mechanism for retaining DriverData for devices
76 86
77 } 87 }
......
...@@ -21,14 +21,36 @@ import java.util.Collection; ...@@ -21,14 +21,36 @@ import java.util.Collection;
21 import java.util.concurrent.Future; 21 import java.util.concurrent.Future;
22 22
23 /** 23 /**
24 - * Created by ash on 07/04/15. 24 + * Service for programming data plane flow rules in manner independent of
25 + * specific device table pipeline configuration.
25 */ 26 */
26 public interface FlowObjectiveService { 27 public interface FlowObjectiveService {
27 28
28 - Future<Boolean> filter(DeviceId deviceId, Collection<FilteringObjective> filterObjectives); 29 + /**
30 + * Installs the filtering rules onto the specified device.
31 + *
32 + * @param deviceId device identifier
33 + * @param filteringObjectives the collection of filters
34 + * @return a future indicating the success of the operation
35 + */
36 + Future<Boolean> filter(DeviceId deviceId, Collection<FilteringObjective> filteringObjectives);
29 37
38 + /**
39 + * Installs the forwarding rules onto the specified device.
40 + *
41 + * @param deviceId device identifier
42 + * @param forwardingObjectives the collection of forwarding objectives
43 + * @return a future indicating the success of the operation
44 + */
30 Future<Boolean> forward(DeviceId deviceId, Collection<ForwardingObjective> forwardingObjectives); 45 Future<Boolean> forward(DeviceId deviceId, Collection<ForwardingObjective> forwardingObjectives);
31 46
47 + /**
48 + * Installs the next hop elements into the specified device.
49 + *
50 + * @param deviceId device identifier
51 + * @param nextObjectives the collection of next objectives
52 + * @return a future indicating the success of the operation
53 + */
32 Future<Boolean> next(DeviceId deviceId, Collection<NextObjective> nextObjectives); 54 Future<Boolean> next(DeviceId deviceId, Collection<NextObjective> nextObjectives);
33 55
34 } 56 }
......
1 +/*
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 + */
16 +
17 +/**
18 + * Abstractions for objective-based flow programming of data plane without
19 + * requiring device pipeline structure awareness.
20 + */
21 +package org.onosproject.net.flowobjective;
...\ No newline at end of file ...\ No newline at end of file
...@@ -37,7 +37,7 @@ public class DefaultDriverDataTest { ...@@ -37,7 +37,7 @@ public class DefaultDriverDataTest {
37 37
38 @Test 38 @Test
39 public void basics() { 39 public void basics() {
40 - assertSame("incorrect type", ddc, data.type()); 40 + assertSame("incorrect type", ddc, data.driver());
41 assertTrue("incorrect toString", data.toString().contains("foo.bar")); 41 assertTrue("incorrect toString", data.toString().contains("foo.bar"));
42 } 42 }
43 43
......
...@@ -21,29 +21,45 @@ import com.google.common.collect.Sets; ...@@ -21,29 +21,45 @@ import com.google.common.collect.Sets;
21 import org.apache.felix.scr.annotations.Activate; 21 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 22 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 23 import org.apache.felix.scr.annotations.Deactivate;
24 +import org.apache.felix.scr.annotations.Reference;
25 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 import org.apache.felix.scr.annotations.Service; 26 import org.apache.felix.scr.annotations.Service;
27 +import org.onosproject.net.Device;
25 import org.onosproject.net.DeviceId; 28 import org.onosproject.net.DeviceId;
29 +import org.onosproject.net.device.DeviceService;
26 import org.onosproject.net.driver.Behaviour; 30 import org.onosproject.net.driver.Behaviour;
27 import org.onosproject.net.driver.DefaultDriverData; 31 import org.onosproject.net.driver.DefaultDriverData;
28 import org.onosproject.net.driver.DefaultDriverHandler; 32 import org.onosproject.net.driver.DefaultDriverHandler;
29 import org.onosproject.net.driver.Driver; 33 import org.onosproject.net.driver.Driver;
30 import org.onosproject.net.driver.DriverAdminService; 34 import org.onosproject.net.driver.DriverAdminService;
31 -import org.onosproject.net.driver.DriverData;
32 import org.onosproject.net.driver.DriverHandler; 35 import org.onosproject.net.driver.DriverHandler;
33 import org.onosproject.net.driver.DriverProvider; 36 import org.onosproject.net.driver.DriverProvider;
34 import org.slf4j.Logger; 37 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory; 38 import org.slf4j.LoggerFactory;
36 39
37 import java.util.Map; 40 import java.util.Map;
41 +import java.util.Optional;
38 import java.util.Set; 42 import java.util.Set;
39 43
44 +import static org.onlab.util.Tools.nullIsNotFound;
45 +import static org.onosproject.net.AnnotationKeys.DRIVER;
40 46
47 +/**
48 + * Manages inventory of device drivers.
49 + */
41 @Component(immediate = true) 50 @Component(immediate = true)
42 @Service 51 @Service
43 public class DriverManager implements DriverAdminService { 52 public class DriverManager implements DriverAdminService {
44 53
45 private final Logger log = LoggerFactory.getLogger(getClass()); 54 private final Logger log = LoggerFactory.getLogger(getClass());
46 55
56 + private static final String NO_DRIVER = "Driver not found";
57 + private static final String NO_DEVICE = "Device not found";
58 + private static final String DEFAULT = "default";
59 +
60 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
61 + protected DeviceService deviceService;
62 +
47 private Set<DriverProvider> providers = Sets.newConcurrentHashSet(); 63 private Set<DriverProvider> providers = Sets.newConcurrentHashSet();
48 private Map<String, Driver> driverByName = Maps.newConcurrentMap(); 64 private Map<String, Driver> driverByName = Maps.newConcurrentMap();
49 private Map<String, Driver> driverByKey = Maps.newConcurrentMap(); 65 private Map<String, Driver> driverByKey = Maps.newConcurrentMap();
...@@ -88,30 +104,63 @@ public class DriverManager implements DriverAdminService { ...@@ -88,30 +104,63 @@ public class DriverManager implements DriverAdminService {
88 104
89 @Override 105 @Override
90 public Set<Driver> getDrivers(Class<? extends Behaviour>... withBehaviours) { 106 public Set<Driver> getDrivers(Class<? extends Behaviour>... withBehaviours) {
91 - //TODO 107 + ImmutableSet.Builder<Driver> builder = ImmutableSet.builder();
92 - return null; 108 + for (Class<? extends Behaviour> behaviour : withBehaviours) {
109 + driverByName.forEach((name, driver) -> {
110 + if (driver.hasBehaviour(behaviour)) {
111 + builder.add(driver);
112 + }
113 + });
114 + }
115 + return builder.build();
93 } 116 }
94 117
95 @Override 118 @Override
96 public Driver getDriver(String driverName) { 119 public Driver getDriver(String driverName) {
97 - //TODO: replace with fallback driver. 120 + return nullIsNotFound(driverByName.get(driverName), NO_DRIVER);
98 - return driverByName.getOrDefault(driverName, driverByName.get("default"));
99 } 121 }
100 122
101 @Override 123 @Override
102 public Driver getDriver(String mfr, String hw, String sw) { 124 public Driver getDriver(String mfr, String hw, String sw) {
103 - return driverByKey.getOrDefault(key(mfr, hw, sw), driverByName.get("default")); 125 + // First attempt a literal search.
126 + Driver driver = driverByKey.get(key(mfr, hw, sw));
127 + if (driver != null) {
128 + return driver;
129 + }
130 +
131 + // Otherwise, sweep through the key space and attempt to match using
132 + // regular expression matching.
133 + Optional<Driver> optional = driverByKey.values().stream()
134 + .filter(d -> matches(d, mfr, hw, sw)).findFirst();
135 +
136 + // If no matching driver is found, return default.
137 + return optional.isPresent() ? optional.get() : driverByName.get(DEFAULT);
138 + }
139 +
140 + // Matches the given driver using ERE matching against the given criteria.
141 + private boolean matches(Driver d, String mfr, String hw, String sw) {
142 + // TODO: consider pre-compiling the expressions in the future
143 + return mfr.matches(d.manufacturer()) &&
144 + hw.matches(d.hwVersion()) &&
145 + sw.matches(d.swVersion());
104 } 146 }
105 147
106 @Override 148 @Override
107 - public DriverHandler createHandler(String driverName, DeviceId deviceId, String... credentials) { 149 + public Driver getDriver(DeviceId deviceId) {
108 - Driver driver = driverByName.get(driverName); 150 + Device device = nullIsNotFound(deviceService.getDevice(deviceId), NO_DEVICE);
109 - return new DefaultDriverHandler(new DefaultDriverData(driver)); 151 + String driverName = device.annotations().value(DRIVER);
152 + if (driverName != null) {
153 + return getDriver(driverName);
154 + }
155 + return nullIsNotFound(getDriver(device.manufacturer(),
156 + device.hwVersion(), device.swVersion()),
157 + NO_DRIVER);
110 } 158 }
111 159
112 @Override 160 @Override
113 - public DriverHandler createHandler(DriverData data, DeviceId deviceId, String... credentials) { 161 + public DriverHandler createHandler(DeviceId deviceId, String... credentials) {
114 - return null; 162 + Driver driver = getDriver(deviceId);
163 + return new DefaultDriverHandler(new DefaultDriverData(driver));
115 } 164 }
116 165
117 private String key(String mfr, String hw, String sw) { 166 private String key(String mfr, String hw, String sw) {
......
1 +/*
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 + */
16 +
17 +/**
18 + * Implementation of the device driver management subsystem.
19 + */
20 +package org.onosproject.net.driver.impl;
...\ No newline at end of file ...\ No newline at end of file
...@@ -24,23 +24,26 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -24,23 +24,26 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
24 import org.apache.felix.scr.annotations.Service; 24 import org.apache.felix.scr.annotations.Service;
25 import org.onlab.osgi.DefaultServiceDirectory; 25 import org.onlab.osgi.DefaultServiceDirectory;
26 import org.onlab.osgi.ServiceDirectory; 26 import org.onlab.osgi.ServiceDirectory;
27 +import org.onlab.util.ItemNotFoundException;
27 import org.onosproject.cluster.ClusterService; 28 import org.onosproject.cluster.ClusterService;
29 +import org.onosproject.cluster.NodeId;
28 import org.onosproject.mastership.MastershipEvent; 30 import org.onosproject.mastership.MastershipEvent;
29 import org.onosproject.mastership.MastershipListener; 31 import org.onosproject.mastership.MastershipListener;
30 import org.onosproject.mastership.MastershipService; 32 import org.onosproject.mastership.MastershipService;
31 -import org.onosproject.net.Device;
32 import org.onosproject.net.DeviceId; 33 import org.onosproject.net.DeviceId;
33 import org.onosproject.net.behaviour.Pipeliner; 34 import org.onosproject.net.behaviour.Pipeliner;
35 +import org.onosproject.net.behaviour.PipelinerContext;
34 import org.onosproject.net.device.DeviceEvent; 36 import org.onosproject.net.device.DeviceEvent;
35 import org.onosproject.net.device.DeviceListener; 37 import org.onosproject.net.device.DeviceListener;
36 import org.onosproject.net.device.DeviceService; 38 import org.onosproject.net.device.DeviceService;
37 -import org.onosproject.net.driver.Driver;
38 import org.onosproject.net.driver.DriverHandler; 39 import org.onosproject.net.driver.DriverHandler;
39 import org.onosproject.net.driver.DriverService; 40 import org.onosproject.net.driver.DriverService;
41 +import org.onosproject.net.flow.FlowRuleService;
40 import org.onosproject.net.flowobjective.FilteringObjective; 42 import org.onosproject.net.flowobjective.FilteringObjective;
41 import org.onosproject.net.flowobjective.FlowObjectiveService; 43 import org.onosproject.net.flowobjective.FlowObjectiveService;
42 import org.onosproject.net.flowobjective.ForwardingObjective; 44 import org.onosproject.net.flowobjective.ForwardingObjective;
43 import org.onosproject.net.flowobjective.NextObjective; 45 import org.onosproject.net.flowobjective.NextObjective;
46 +import org.onosproject.net.group.GroupService;
44 import org.slf4j.Logger; 47 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory; 48 import org.slf4j.LoggerFactory;
46 49
...@@ -51,7 +54,7 @@ import java.util.concurrent.Future; ...@@ -51,7 +54,7 @@ import java.util.concurrent.Future;
51 import static com.google.common.base.Preconditions.checkState; 54 import static com.google.common.base.Preconditions.checkState;
52 55
53 /** 56 /**
54 - * Created by ash on 07/04/15. 57 + * Provides implementation of the flow objective programming service.
55 */ 58 */
56 @Component(immediate = true) 59 @Component(immediate = true)
57 @Service 60 @Service
...@@ -59,6 +62,8 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -59,6 +62,8 @@ public class FlowObjectiveManager implements FlowObjectiveService {
59 62
60 private final Logger log = LoggerFactory.getLogger(getClass()); 63 private final Logger log = LoggerFactory.getLogger(getClass());
61 64
65 + public static final String NOT_INITIALIZED = "Driver not initialized";
66 +
62 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 67 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 protected DriverService driverService; 68 protected DriverService driverService;
64 69
...@@ -71,20 +76,31 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -71,20 +76,31 @@ public class FlowObjectiveManager implements FlowObjectiveService {
71 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 76 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
72 protected ClusterService clusterService; 77 protected ClusterService clusterService;
73 78
74 - protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory(); 79 + // 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;
75 87
76 - private MastershipListener mastershipListener = new InnerMastershipListener();
77 88
78 - private DeviceListener deviceListener = new InnerDeviceListener(); 89 + private final Map<DeviceId, DriverHandler> driverHandlers = Maps.newConcurrentMap();
79 90
80 - private Map<DeviceId, DriverHandler> driverHandlers = 91 + private final PipelinerContext context = new InnerPipelineContext();
81 - Maps.newConcurrentMap(); 92 + private final MastershipListener mastershipListener = new InnerMastershipListener();
93 + private final DeviceListener deviceListener = new InnerDeviceListener();
94 +
95 + protected ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
96 + private NodeId localNode;
82 97
83 @Activate 98 @Activate
84 protected void activate() { 99 protected void activate() {
100 + localNode = clusterService.getLocalNode().id();
85 mastershipService.addListener(mastershipListener); 101 mastershipService.addListener(mastershipListener);
86 deviceService.addListener(deviceListener); 102 deviceService.addListener(deviceListener);
87 - deviceService.getDevices().forEach(device -> setupDriver(device.id())); 103 + deviceService.getDevices().forEach(device -> setupPipelineHandler(device.id()));
88 log.info("Started"); 104 log.info("Started");
89 } 105 }
90 106
...@@ -97,113 +113,90 @@ public class FlowObjectiveManager implements FlowObjectiveService { ...@@ -97,113 +113,90 @@ public class FlowObjectiveManager implements FlowObjectiveService {
97 113
98 @Override 114 @Override
99 public Future<Boolean> filter(DeviceId deviceId, 115 public Future<Boolean> filter(DeviceId deviceId,
100 - Collection<FilteringObjective> filterObjectives) { 116 + Collection<FilteringObjective> filteringObjectives) {
101 - DriverHandler handler = driverHandlers.get(deviceId); 117 + return getDevicePipeliner(deviceId).filter(filteringObjectives);
102 - checkState(handler != null, "Driver not initialized");
103 -
104 - Pipeliner pipe = handler.behaviour(Pipeliner.class);
105 -
106 - return pipe.filter(filterObjectives);
107 } 118 }
108 119
109 @Override 120 @Override
110 public Future<Boolean> forward(DeviceId deviceId, 121 public Future<Boolean> forward(DeviceId deviceId,
111 Collection<ForwardingObjective> forwardingObjectives) { 122 Collection<ForwardingObjective> forwardingObjectives) {
112 - DriverHandler handler = driverHandlers.get(deviceId); 123 + return getDevicePipeliner(deviceId).forward(forwardingObjectives);
113 - checkState(handler != null, "Driver not initialized");
114 -
115 - Pipeliner pipe = handler.behaviour(Pipeliner.class);
116 -
117 - return pipe.forward(forwardingObjectives);
118 } 124 }
119 125
120 @Override 126 @Override
121 public Future<Boolean> next(DeviceId deviceId, 127 public Future<Boolean> next(DeviceId deviceId,
122 Collection<NextObjective> nextObjectives) { 128 Collection<NextObjective> nextObjectives) {
123 - DriverHandler handler = driverHandlers.get(deviceId); 129 + return getDevicePipeliner(deviceId).next(nextObjectives);
124 - checkState(handler != null, "Driver not initialized");
125 -
126 - Pipeliner pipe = handler.behaviour(Pipeliner.class);
127 -
128 - return pipe.next(nextObjectives);
129 } 130 }
130 131
132 + // Retrieves the device handler pipeline behaviour from the cache.
133 + private Pipeliner getDevicePipeliner(DeviceId deviceId) {
134 + DriverHandler handler = driverHandlers.get(deviceId);
135 + checkState(handler != null, NOT_INITIALIZED);
136 + return handler != null ? handler.behaviour(Pipeliner.class) : null;
137 + }
131 138
132 139
140 + // Triggers driver setup when the local node becomes a device master.
133 private class InnerMastershipListener implements MastershipListener { 141 private class InnerMastershipListener implements MastershipListener {
134 @Override 142 @Override
135 public void event(MastershipEvent event) { 143 public void event(MastershipEvent event) {
136 switch (event.type()) { 144 switch (event.type()) {
137 -
138 case MASTER_CHANGED: 145 case MASTER_CHANGED:
139 - setupDriver(event.subject()); 146 + setupPipelineHandler(event.subject());
140 -
141 - break;
142 - case BACKUPS_CHANGED:
143 break; 147 break;
144 default: 148 default:
145 - log.warn("Unknown mastership type {}", event.type()); 149 + break;
146 } 150 }
147 } 151 }
148 -
149 -
150 } 152 }
151 153
154 + // Triggers driver setup when a device is (re)detected.
152 private class InnerDeviceListener implements DeviceListener { 155 private class InnerDeviceListener implements DeviceListener {
153 @Override 156 @Override
154 public void event(DeviceEvent event) { 157 public void event(DeviceEvent event) {
155 switch (event.type()) { 158 switch (event.type()) {
156 case DEVICE_ADDED: 159 case DEVICE_ADDED:
157 case DEVICE_AVAILABILITY_CHANGED: 160 case DEVICE_AVAILABILITY_CHANGED:
158 - setupDriver(event.subject().id()); 161 + setupPipelineHandler(event.subject().id());
159 - break;
160 - case DEVICE_UPDATED:
161 - break;
162 - case DEVICE_REMOVED:
163 - break;
164 - case DEVICE_SUSPENDED:
165 - break;
166 - case PORT_ADDED:
167 - break;
168 - case PORT_UPDATED:
169 - break;
170 - case PORT_REMOVED:
171 break; 162 break;
172 default: 163 default:
173 - log.warn("Unknown event type {}", event.type()); 164 + break;
174 } 165 }
175 } 166 }
176 } 167 }
177 168
178 - private void setupDriver(DeviceId deviceId) { 169 + private void setupPipelineHandler(DeviceId deviceId) {
179 - //TODO: Refactor this to make it nicer and use a cache. 170 + if (localNode.equals(mastershipService.getMasterFor(deviceId))) {
180 - if (mastershipService.getMasterFor( 171 + // Attempt to lookup the handler in the cache
181 - deviceId).equals(clusterService.getLocalNode().id())) { 172 + DriverHandler handler = driverHandlers.get(deviceId);
182 - 173 + if (handler == null) {
183 - DriverHandler handler = lookupDriver(deviceId); 174 + try {
184 - if (handler != null) { 175 + // Otherwise create it and if it has pipeline behaviour, cache it
185 - Pipeliner pipe = handler.behaviour(Pipeliner.class); 176 + handler = driverService.createHandler(deviceId);
186 - pipe.init(deviceId, serviceDirectory); 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 + }
187 driverHandlers.put(deviceId, handler); 186 driverHandlers.put(deviceId, handler);
188 - log.info("Driver {} bound to device {}",
189 - handler.data().type().name(), deviceId);
190 - } else {
191 - log.error("No driver for device {}", deviceId);
192 } 187 }
188 +
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);
193 } 192 }
194 } 193 }
195 194
196 - 195 + // Processing context for initializing pipeline driver behaviours.
197 - private DriverHandler lookupDriver(DeviceId deviceId) { 196 + private class InnerPipelineContext implements PipelinerContext {
198 - Device device = deviceService.getDevice(deviceId); 197 + @Override
199 - if (device == null) { 198 + public ServiceDirectory directory() {
200 - log.warn("Device is null!"); 199 + return serviceDirectory;
201 - return null;
202 } 200 }
203 - Driver driver = driverService.getDriver(device.manufacturer(),
204 - device.hwVersion(), device.swVersion());
205 -
206 - return driverService.createHandler(driver.name(), deviceId);
207 } 201 }
208 -
209 } 202 }
......
1 +/*
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 + */
16 +
17 +/**
18 + * Implementations of the flow objective programming subsystem.
19 + */
20 +package org.onosproject.net.flowobjective.impl;
...\ No newline at end of file ...\ No newline at end of file
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
61 <group> 61 <group>
62 <title>Core Subsystems</title> 62 <title>Core Subsystems</title>
63 <packages> 63 <packages>
64 - org.onosproject.impl:org.onosproject.core.impl:org.onosproject.cluster.impl:org.onosproject.net.device.impl:org.onosproject.net.link.impl:org.onosproject.net.host.impl:org.onosproject.net.topology.impl:org.onosproject.net.packet.impl:org.onosproject.net.flow.impl:org.onosproject.net.*.impl:org.onosproject.event.impl:org.onosproject.net.intent.impl*:org.onosproject.net.proxyarp.impl:org.onosproject.mastership.impl:org.onosproject.net.resource.impl:org.onosproject.json:org.onosproject.json.*:org.onosproject.provider.host.impl:org.onosproject.provider.lldp.impl:org.onosproject.net.statistic.impl:org.onosproject.app.impl:org.onosproject.common.*:org.onosproject.net.group.impl:org.onosproject.cfg.impl 64 + org.onosproject.impl:org.onosproject.core.impl:org.onosproject.cluster.impl:org.onosproject.net.device.impl:org.onosproject.net.link.impl:org.onosproject.net.host.impl:org.onosproject.net.topology.impl:org.onosproject.net.packet.impl:org.onosproject.net.flow.impl:org.onosproject.net.*.impl:org.onosproject.event.impl:org.onosproject.net.intent.impl*:org.onosproject.net.proxyarp.impl:org.onosproject.mastership.impl:org.onosproject.net.resource.impl:org.onosproject.json:org.onosproject.json.*:org.onosproject.provider.host.impl:org.onosproject.provider.lldp.impl:org.onosproject.net.statistic.impl:org.onosproject.app.impl:org.onosproject.common.*:org.onosproject.net.group.impl:org.onosproject.cfg.impl:org.onosproject.net.driver.impl:org.onosproject.net.flowobjective.impl:org.onosproject.net.flowext.impl
65 </packages> 65 </packages>
66 </group> 66 </group>
67 <group> 67 <group>
...@@ -83,6 +83,12 @@ ...@@ -83,6 +83,12 @@
83 </packages> 83 </packages>
84 </group> 84 </group>
85 <group> 85 <group>
86 + <title>Built-in Device Drivers</title>
87 + <packages>
88 + org.onosproject.driver.*
89 + </packages>
90 + </group>
91 + <group>
86 <title>Utilities</title> 92 <title>Utilities</title>
87 <packages> 93 <packages>
88 org.onlab.* 94 org.onlab.*
......
...@@ -27,6 +27,7 @@ import org.slf4j.Logger; ...@@ -27,6 +27,7 @@ import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory; 27 import org.slf4j.LoggerFactory;
28 28
29 import java.io.IOException; 29 import java.io.IOException;
30 +import java.io.InputStream;
30 31
31 /** 32 /**
32 * Bootstrap for built in drivers. 33 * Bootstrap for built in drivers.
...@@ -36,6 +37,8 @@ public class DefaultDrivers { ...@@ -36,6 +37,8 @@ public class DefaultDrivers {
36 37
37 private final Logger log = LoggerFactory.getLogger(getClass()); 38 private final Logger log = LoggerFactory.getLogger(getClass());
38 39
40 + private static final String DRIVERS_XML = "/onos-drivers.xml";
41 +
39 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 42 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
40 protected DriverAdminService driverService; 43 protected DriverAdminService driverService;
41 44
...@@ -43,25 +46,23 @@ public class DefaultDrivers { ...@@ -43,25 +46,23 @@ public class DefaultDrivers {
43 46
44 @Activate 47 @Activate
45 protected void activate() { 48 protected void activate() {
46 - XmlDriverLoader xmlDriverLoader = 49 + ClassLoader classLoader = getClass().getClassLoader();
47 - new XmlDriverLoader(getClass().getClassLoader());
48 try { 50 try {
49 - provider = xmlDriverLoader.loadDrivers( 51 + InputStream stream = classLoader.getResourceAsStream(DRIVERS_XML);
50 - getClass().getResourceAsStream("/default.xml")); 52 + provider = new XmlDriverLoader(classLoader).loadDrivers(stream);
51 - driverService.registerProvider( 53 + driverService.registerProvider(provider);
52 - provider);
53 } catch (IOException e) { 54 } catch (IOException e) {
54 - log.warn("Unable to load drivers"); 55 + log.error("Unable to load default drivers", e);
55 } 56 }
56 -
57 log.info("Started"); 57 log.info("Started");
58 } 58 }
59 59
60 @Deactivate 60 @Deactivate
61 protected void deactivate() { 61 protected void deactivate() {
62 - driverService.unregisterProvider(provider); 62 + if (provider != null) {
63 + driverService.unregisterProvider(provider);
64 + }
63 log.info("Stopped"); 65 log.info("Stopped");
64 } 66 }
65 67
66 -
67 } 68 }
......
...@@ -20,6 +20,7 @@ import org.onlab.osgi.ServiceDirectory; ...@@ -20,6 +20,7 @@ import org.onlab.osgi.ServiceDirectory;
20 import org.onosproject.core.DefaultGroupId; 20 import org.onosproject.core.DefaultGroupId;
21 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
22 import org.onosproject.net.behaviour.Pipeliner; 22 import org.onosproject.net.behaviour.Pipeliner;
23 +import org.onosproject.net.behaviour.PipelinerContext;
23 import org.onosproject.net.driver.DriverData; 24 import org.onosproject.net.driver.DriverData;
24 import org.onosproject.net.flow.DefaultFlowRule; 25 import org.onosproject.net.flow.DefaultFlowRule;
25 import org.onosproject.net.flow.FlowRule; 26 import org.onosproject.net.flow.FlowRule;
...@@ -49,8 +50,8 @@ public class DefaultSingleTablePipeline implements Pipeliner { ...@@ -49,8 +50,8 @@ public class DefaultSingleTablePipeline implements Pipeliner {
49 private DeviceId deviceId; 50 private DeviceId deviceId;
50 51
51 @Override 52 @Override
52 - public void init(DeviceId deviceId, ServiceDirectory serviceDirectory) { 53 + public void init(DeviceId deviceId, PipelinerContext context) {
53 - this.serviceDirectory = serviceDirectory; 54 + this.serviceDirectory = context.directory();
54 this.deviceId = deviceId; 55 this.deviceId = deviceId;
55 56
56 flowRuleService = serviceDirectory.get(FlowRuleService.class); 57 flowRuleService = serviceDirectory.get(FlowRuleService.class);
......
...@@ -23,6 +23,7 @@ import org.onosproject.core.ApplicationId; ...@@ -23,6 +23,7 @@ import org.onosproject.core.ApplicationId;
23 import org.onosproject.core.CoreService; 23 import org.onosproject.core.CoreService;
24 import org.onosproject.net.DeviceId; 24 import org.onosproject.net.DeviceId;
25 import org.onosproject.net.behaviour.Pipeliner; 25 import org.onosproject.net.behaviour.Pipeliner;
26 +import org.onosproject.net.behaviour.PipelinerContext;
26 import org.onosproject.net.driver.DriverData; 27 import org.onosproject.net.driver.DriverData;
27 import org.onosproject.net.flow.DefaultFlowRule; 28 import org.onosproject.net.flow.DefaultFlowRule;
28 import org.onosproject.net.flow.DefaultTrafficSelector; 29 import org.onosproject.net.flow.DefaultTrafficSelector;
...@@ -61,8 +62,8 @@ public class OVSCorsaPipeline implements Pipeliner { ...@@ -61,8 +62,8 @@ public class OVSCorsaPipeline implements Pipeliner {
61 private ApplicationId appId; 62 private ApplicationId appId;
62 63
63 @Override 64 @Override
64 - public void init(DeviceId deviceId, ServiceDirectory serviceDirectory) { 65 + public void init(DeviceId deviceId, PipelinerContext context) {
65 - this.serviceDirectory = serviceDirectory; 66 + this.serviceDirectory = context.directory();
66 this.deviceId = deviceId; 67 this.deviceId = deviceId;
67 68
68 69
......
1 +/*
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 + */
16 +
17 +/**
18 + * Implementations of the pipeline driver behaviours.
19 + */
20 +package org.onosproject.driver.pipeline;
...\ No newline at end of file ...\ No newline at end of file
...@@ -112,6 +112,23 @@ public abstract class Tools { ...@@ -112,6 +112,23 @@ public abstract class Tools {
112 } 112 }
113 113
114 /** 114 /**
115 + * Returns the specified item if that items is null; otherwise throws
116 + * not found exception.
117 + *
118 + * @param item item to check
119 + * @param message not found message
120 + * @param <T> item type
121 + * @return item if not null
122 + * @throws org.onlab.util.ItemNotFoundException if item is null
123 + */
124 + public static <T> T nullIsNotFound(T item, String message) {
125 + if (item == null) {
126 + throw new ItemNotFoundException(message);
127 + }
128 + return item;
129 + }
130 +
131 + /**
115 * Converts a string from hex to long. 132 * Converts a string from hex to long.
116 * 133 *
117 * @param string hex number in string form; sans 0x 134 * @param string hex number in string form; sans 0x
......