Jonathan Hart
Committed by Gerrit Code Review

Added events for the Interface subsytem

Change-Id: I9adcc2caa2a98625173c9b9c6d15bbd1a0706eaa
...@@ -31,6 +31,9 @@ import org.onosproject.net.host.InterfaceIpAddress; ...@@ -31,6 +31,9 @@ import org.onosproject.net.host.InterfaceIpAddress;
31 import java.util.Iterator; 31 import java.util.Iterator;
32 import java.util.Set; 32 import java.util.Set;
33 33
34 +import static com.google.common.base.Preconditions.checkArgument;
35 +import static com.google.common.base.Preconditions.checkNotNull;
36 +
34 /** 37 /**
35 * Configuration for interfaces. 38 * Configuration for interfaces.
36 */ 39 */
...@@ -41,7 +44,9 @@ public class InterfaceConfig extends Config<ConnectPoint> { ...@@ -41,7 +44,9 @@ public class InterfaceConfig extends Config<ConnectPoint> {
41 public static final String MAC = "mac"; 44 public static final String MAC = "mac";
42 public static final String VLAN = "vlan"; 45 public static final String VLAN = "vlan";
43 46
44 - public static final String CONFIG_VALUE_ERROR = "Error parsing config value"; 47 + private static final String CONFIG_VALUE_ERROR = "Error parsing config value";
48 + private static final String INTF_NULL_ERROR = "Interface cannot be null";
49 + private static final String INTF_NAME_ERROR = "Interface must have a valid name";
45 50
46 /** 51 /**
47 * Retrieves all interfaces configured on this port. 52 * Retrieves all interfaces configured on this port.
...@@ -78,6 +83,12 @@ public class InterfaceConfig extends Config<ConnectPoint> { ...@@ -78,6 +83,12 @@ public class InterfaceConfig extends Config<ConnectPoint> {
78 * @param intf interface to add 83 * @param intf interface to add
79 */ 84 */
80 public void addInterface(Interface intf) { 85 public void addInterface(Interface intf) {
86 + checkNotNull(intf, INTF_NULL_ERROR);
87 + checkArgument(!intf.name().equals(Interface.NO_INTERFACE_NAME), INTF_NAME_ERROR);
88 +
89 + // Remove old interface with this name if it exists
90 + removeInterface(intf.name());
91 +
81 ObjectNode intfNode = array.addObject(); 92 ObjectNode intfNode = array.addObject();
82 93
83 intfNode.put(NAME, intf.name()); 94 intfNode.put(NAME, intf.name());
...@@ -101,6 +112,9 @@ public class InterfaceConfig extends Config<ConnectPoint> { ...@@ -101,6 +112,9 @@ public class InterfaceConfig extends Config<ConnectPoint> {
101 * @param name name of the interface to remove 112 * @param name name of the interface to remove
102 */ 113 */
103 public void removeInterface(String name) { 114 public void removeInterface(String name) {
115 + checkNotNull(name, INTF_NULL_ERROR);
116 + checkArgument(!name.equals(Interface.NO_INTERFACE_NAME), INTF_NAME_ERROR);
117 +
104 Iterator<JsonNode> it = array.iterator(); 118 Iterator<JsonNode> it = array.iterator();
105 while (it.hasNext()) { 119 while (it.hasNext()) {
106 JsonNode node = it.next(); 120 JsonNode node = it.next();
......
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 +package org.onosproject.incubator.net.intf;
18 +
19 +import org.onosproject.event.AbstractEvent;
20 +
21 +/**
22 + * Describes an interface event.
23 + */
24 +public class InterfaceEvent extends AbstractEvent<InterfaceEvent.Type, Interface> {
25 +
26 + public enum Type {
27 + /**
28 + * Indicates a new interface has been added.
29 + */
30 + INTERFACE_ADDED,
31 +
32 + /**
33 + * Indicates an interface has been updated.
34 + */
35 + INTERFACE_UPDATED,
36 +
37 + /**
38 + * Indicates an interface has been removed.
39 + */
40 + INTERFACE_REMOVED
41 + }
42 +
43 + /**
44 + * Creates an interface event with type and subject.
45 + *
46 + * @param type event type
47 + * @param subject subject interface
48 + */
49 + public InterfaceEvent(Type type, Interface subject) {
50 + super(type, subject);
51 + }
52 +
53 + /**
54 + * Creates an interface event with type, subject and time.
55 + *
56 + * @param type event type
57 + * @param subject subject interface
58 + * @param time time of event
59 + */
60 + public InterfaceEvent(Type type, Interface subject, long time) {
61 + super(type, subject, time);
62 + }
63 +
64 +}
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 +package org.onosproject.incubator.net.intf;
18 +
19 +import org.onosproject.event.EventListener;
20 +
21 +/**
22 + * Listener for interface events.
23 + */
24 +public interface InterfaceListener extends EventListener<InterfaceEvent> {
25 +}
...@@ -19,6 +19,7 @@ package org.onosproject.incubator.net.intf; ...@@ -19,6 +19,7 @@ package org.onosproject.incubator.net.intf;
19 import com.google.common.annotations.Beta; 19 import com.google.common.annotations.Beta;
20 import org.onlab.packet.IpAddress; 20 import org.onlab.packet.IpAddress;
21 import org.onlab.packet.VlanId; 21 import org.onlab.packet.VlanId;
22 +import org.onosproject.event.ListenerService;
22 import org.onosproject.net.ConnectPoint; 23 import org.onosproject.net.ConnectPoint;
23 24
24 import java.util.Set; 25 import java.util.Set;
...@@ -27,7 +28,8 @@ import java.util.Set; ...@@ -27,7 +28,8 @@ import java.util.Set;
27 * Service for interacting with interfaces. 28 * Service for interacting with interfaces.
28 */ 29 */
29 @Beta 30 @Beta
30 -public interface InterfaceService { 31 +public interface InterfaceService
32 + extends ListenerService<InterfaceEvent, InterfaceListener> {
31 33
32 /** 34 /**
33 * Returns the set of all interfaces in the system. 35 * Returns the set of all interfaces in the system.
......
...@@ -27,10 +27,13 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; ...@@ -27,10 +27,13 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
27 import org.apache.felix.scr.annotations.Service; 27 import org.apache.felix.scr.annotations.Service;
28 import org.onlab.packet.IpAddress; 28 import org.onlab.packet.IpAddress;
29 import org.onlab.packet.VlanId; 29 import org.onlab.packet.VlanId;
30 +import org.onosproject.event.ListenerRegistry;
30 import org.onosproject.incubator.net.config.basics.ConfigException; 31 import org.onosproject.incubator.net.config.basics.ConfigException;
31 import org.onosproject.incubator.net.config.basics.InterfaceConfig; 32 import org.onosproject.incubator.net.config.basics.InterfaceConfig;
32 import org.onosproject.incubator.net.intf.Interface; 33 import org.onosproject.incubator.net.intf.Interface;
33 import org.onosproject.incubator.net.intf.InterfaceAdminService; 34 import org.onosproject.incubator.net.intf.InterfaceAdminService;
35 +import org.onosproject.incubator.net.intf.InterfaceEvent;
36 +import org.onosproject.incubator.net.intf.InterfaceListener;
34 import org.onosproject.incubator.net.intf.InterfaceService; 37 import org.onosproject.incubator.net.intf.InterfaceService;
35 import org.onosproject.net.ConnectPoint; 38 import org.onosproject.net.ConnectPoint;
36 import org.onosproject.net.config.NetworkConfigEvent; 39 import org.onosproject.net.config.NetworkConfigEvent;
...@@ -40,11 +43,9 @@ import org.slf4j.Logger; ...@@ -40,11 +43,9 @@ import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory; 43 import org.slf4j.LoggerFactory;
41 44
42 import java.util.Collections; 45 import java.util.Collections;
43 -import java.util.Iterator;
44 import java.util.Map; 46 import java.util.Map;
45 import java.util.Optional; 47 import java.util.Optional;
46 import java.util.Set; 48 import java.util.Set;
47 -import java.util.concurrent.atomic.AtomicBoolean;
48 49
49 import static java.util.stream.Collectors.collectingAndThen; 50 import static java.util.stream.Collectors.collectingAndThen;
50 import static java.util.stream.Collectors.toSet; 51 import static java.util.stream.Collectors.toSet;
...@@ -54,8 +55,8 @@ import static java.util.stream.Collectors.toSet; ...@@ -54,8 +55,8 @@ import static java.util.stream.Collectors.toSet;
54 */ 55 */
55 @Service 56 @Service
56 @Component(immediate = true) 57 @Component(immediate = true)
57 -public class InterfaceManager implements InterfaceService, 58 +public class InterfaceManager extends ListenerRegistry<InterfaceEvent, InterfaceListener>
58 - InterfaceAdminService { 59 + implements InterfaceService, InterfaceAdminService {
59 60
60 private final Logger log = LoggerFactory.getLogger(getClass()); 61 private final Logger log = LoggerFactory.getLogger(getClass());
61 62
...@@ -148,20 +149,53 @@ public class InterfaceManager implements InterfaceService, ...@@ -148,20 +149,53 @@ public class InterfaceManager implements InterfaceService,
148 149
149 private void updateInterfaces(InterfaceConfig intfConfig) { 150 private void updateInterfaces(InterfaceConfig intfConfig) {
150 try { 151 try {
151 - interfaces.put(intfConfig.subject(), Sets.newHashSet(intfConfig.getInterfaces())); 152 + Set<Interface> old = interfaces.put(intfConfig.subject(),
153 + Sets.newHashSet(intfConfig.getInterfaces()));
154 +
155 + if (old == null) {
156 + old = Collections.emptySet();
157 + }
158 +
159 + for (Interface intf : intfConfig.getInterfaces()) {
160 + if (intf.name().equals(Interface.NO_INTERFACE_NAME)) {
161 + process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
162 + } else {
163 + Optional<Interface> oldIntf = findInterface(intf, old);
164 + if (oldIntf.isPresent()) {
165 + old.remove(oldIntf.get());
166 + if (!oldIntf.get().equals(intf)) {
167 + process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_UPDATED, intf));
168 + }
169 + } else {
170 + process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_ADDED, intf));
171 + }
172 + }
173 + }
174 +
175 + for (Interface intf : old) {
176 + if (!intf.name().equals(Interface.NO_INTERFACE_NAME)) {
177 + process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, intf));
178 + }
179 + }
152 } catch (ConfigException e) { 180 } catch (ConfigException e) {
153 log.error("Error in interface config", e); 181 log.error("Error in interface config", e);
154 } 182 }
155 } 183 }
156 184
185 + private Optional<Interface> findInterface(Interface intf, Set<Interface> set) {
186 + return set.stream().filter(i -> i.name().equals(intf.name())).findAny();
187 + }
188 +
157 private void removeInterfaces(ConnectPoint port) { 189 private void removeInterfaces(ConnectPoint port) {
158 - interfaces.remove(port); 190 + Set<Interface> old = interfaces.remove(port);
191 +
192 + old.stream()
193 + .filter(i -> !i.name().equals(Interface.NO_INTERFACE_NAME))
194 + .forEach(i -> process(new InterfaceEvent(InterfaceEvent.Type.INTERFACE_REMOVED, i)));
159 } 195 }
160 196
161 @Override 197 @Override
162 public void add(Interface intf) { 198 public void add(Interface intf) {
163 - addInternal(intf);
164 -
165 InterfaceConfig config = 199 InterfaceConfig config =
166 configService.addConfig(intf.connectPoint(), CONFIG_CLASS); 200 configService.addConfig(intf.connectPoint(), CONFIG_CLASS);
167 201
...@@ -170,30 +204,8 @@ public class InterfaceManager implements InterfaceService, ...@@ -170,30 +204,8 @@ public class InterfaceManager implements InterfaceService,
170 configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node()); 204 configService.applyConfig(intf.connectPoint(), CONFIG_CLASS, config.node());
171 } 205 }
172 206
173 - private void addInternal(Interface intf) {
174 - interfaces.compute(intf.connectPoint(), (cp, current) -> {
175 - if (current == null) {
176 - return Sets.newHashSet(intf);
177 - }
178 -
179 - Iterator<Interface> it = current.iterator();
180 - while (it.hasNext()) {
181 - Interface i = it.next();
182 - if (i.name().equals(intf.name())) {
183 - it.remove();
184 - break;
185 - }
186 - }
187 -
188 - current.add(intf);
189 - return current;
190 - });
191 - }
192 -
193 @Override 207 @Override
194 public boolean remove(ConnectPoint connectPoint, String name) { 208 public boolean remove(ConnectPoint connectPoint, String name) {
195 - boolean success = removeInternal(name, connectPoint);
196 -
197 InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS); 209 InterfaceConfig config = configService.addConfig(connectPoint, CONFIG_CLASS);
198 config.removeInterface(name); 210 config.removeInterface(name);
199 211
...@@ -205,37 +217,10 @@ public class InterfaceManager implements InterfaceService, ...@@ -205,37 +217,10 @@ public class InterfaceManager implements InterfaceService,
205 } 217 }
206 } catch (ConfigException e) { 218 } catch (ConfigException e) {
207 log.error("Error reading interfaces JSON", e); 219 log.error("Error reading interfaces JSON", e);
220 + return false;
208 } 221 }
209 222
210 - return success; 223 + return true;
211 - }
212 -
213 - public boolean removeInternal(String name, ConnectPoint connectPoint) {
214 - AtomicBoolean removed = new AtomicBoolean(false);
215 -
216 - interfaces.compute(connectPoint, (cp, current) -> {
217 - if (current == null) {
218 - return null;
219 - }
220 -
221 - Iterator<Interface> it = current.iterator();
222 - while (it.hasNext()) {
223 - Interface i = it.next();
224 - if (i.name().equals(name)) {
225 - it.remove();
226 - removed.set(true);
227 - break;
228 - }
229 - }
230 -
231 - if (current.isEmpty()) {
232 - return null;
233 - } else {
234 - return current;
235 - }
236 - });
237 -
238 - return removed.get();
239 } 224 }
240 225
241 /** 226 /**
...@@ -245,19 +230,16 @@ public class InterfaceManager implements InterfaceService, ...@@ -245,19 +230,16 @@ public class InterfaceManager implements InterfaceService,
245 230
246 @Override 231 @Override
247 public void event(NetworkConfigEvent event) { 232 public void event(NetworkConfigEvent event) {
233 + if (event.configClass() == CONFIG_CLASS) {
248 switch (event.type()) { 234 switch (event.type()) {
249 case CONFIG_ADDED: 235 case CONFIG_ADDED:
250 case CONFIG_UPDATED: 236 case CONFIG_UPDATED:
251 - if (event.configClass() == InterfaceConfig.class) {
252 InterfaceConfig config = 237 InterfaceConfig config =
253 configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class); 238 configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
254 updateInterfaces(config); 239 updateInterfaces(config);
255 - }
256 break; 240 break;
257 case CONFIG_REMOVED: 241 case CONFIG_REMOVED:
258 - if (event.configClass() == InterfaceConfig.class) {
259 removeInterfaces((ConnectPoint) event.subject()); 242 removeInterfaces((ConnectPoint) event.subject());
260 - }
261 break; 243 break;
262 case CONFIG_REGISTERED: 244 case CONFIG_REGISTERED:
263 case CONFIG_UNREGISTERED: 245 case CONFIG_UNREGISTERED:
...@@ -266,4 +248,5 @@ public class InterfaceManager implements InterfaceService, ...@@ -266,4 +248,5 @@ public class InterfaceManager implements InterfaceService,
266 } 248 }
267 } 249 }
268 } 250 }
251 + }
269 } 252 }
......