Thomas Vachuska

Fixed a defect that allowed ancillary device providers to overwrite primary provider's data.

...@@ -290,12 +290,17 @@ public class GossipDeviceStore ...@@ -290,12 +290,17 @@ public class GossipDeviceStore
290 private DeviceEvent updateDevice(ProviderId providerId, 290 private DeviceEvent updateDevice(ProviderId providerId,
291 Device oldDevice, 291 Device oldDevice,
292 Device newDevice, Timestamp newTimestamp) { 292 Device newDevice, Timestamp newTimestamp) {
293 -
294 // We allow only certain attributes to trigger update 293 // We allow only certain attributes to trigger update
295 - if (!Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || 294 + boolean propertiesChanged =
296 - !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()) || 295 + !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) ||
297 - !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations())) { 296 + !Objects.equals(oldDevice.swVersion(), newDevice.swVersion());
298 - 297 + boolean annotationsChanged =
298 + !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations());
299 +
300 + // Primary providers can respond to all changes, but ancillary ones
301 + // should respond only to annotation changes.
302 + if ((providerId.isAncillary() && annotationsChanged) ||
303 + (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) {
299 boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); 304 boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice);
300 if (!replaced) { 305 if (!replaced) {
301 verify(replaced, 306 verify(replaced,
......
...@@ -70,15 +70,16 @@ public class SimpleDeviceStore ...@@ -70,15 +70,16 @@ public class SimpleDeviceStore
70 70
71 public static final String DEVICE_NOT_FOUND = "Device with ID %s not found"; 71 public static final String DEVICE_NOT_FOUND = "Device with ID %s not found";
72 72
73 - // collection of Description given from various providers 73 + // Collection of Description given from various providers
74 private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>> 74 private final ConcurrentMap<DeviceId, Map<ProviderId, DeviceDescriptions>>
75 deviceDescs = Maps.newConcurrentMap(); 75 deviceDescs = Maps.newConcurrentMap();
76 76
77 - // cache of Device and Ports generated by compositing descriptions from providers 77 + // Cache of Device and Ports generated by compositing descriptions from providers
78 private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap(); 78 private final ConcurrentMap<DeviceId, Device> devices = Maps.newConcurrentMap();
79 - private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>> devicePorts = Maps.newConcurrentMap(); 79 + private final ConcurrentMap<DeviceId, ConcurrentMap<PortNumber, Port>>
80 + devicePorts = Maps.newConcurrentMap();
80 81
81 - // available(=UP) devices 82 + // Available (=UP) devices
82 private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet(); 83 private final Set<DeviceId> availableDevices = Sets.newConcurrentHashSet();
83 84
84 85
...@@ -115,13 +116,11 @@ public class SimpleDeviceStore ...@@ -115,13 +116,11 @@ public class SimpleDeviceStore
115 public DeviceEvent createOrUpdateDevice(ProviderId providerId, 116 public DeviceEvent createOrUpdateDevice(ProviderId providerId,
116 DeviceId deviceId, 117 DeviceId deviceId,
117 DeviceDescription deviceDescription) { 118 DeviceDescription deviceDescription) {
118 -
119 Map<ProviderId, DeviceDescriptions> providerDescs 119 Map<ProviderId, DeviceDescriptions> providerDescs
120 = getOrCreateDeviceDescriptions(deviceId); 120 = getOrCreateDeviceDescriptions(deviceId);
121 121
122 synchronized (providerDescs) { 122 synchronized (providerDescs) {
123 // locking per device 123 // locking per device
124 -
125 DeviceDescriptions descs 124 DeviceDescriptions descs
126 = getOrCreateProviderDeviceDescriptions(providerDescs, 125 = getOrCreateProviderDeviceDescriptions(providerDescs,
127 providerId, 126 providerId,
...@@ -145,7 +144,6 @@ public class SimpleDeviceStore ...@@ -145,7 +144,6 @@ public class SimpleDeviceStore
145 // Creates the device and returns the appropriate event if necessary. 144 // Creates the device and returns the appropriate event if necessary.
146 // Guarded by deviceDescs value (=Device lock) 145 // Guarded by deviceDescs value (=Device lock)
147 private DeviceEvent createDevice(ProviderId providerId, Device newDevice) { 146 private DeviceEvent createDevice(ProviderId providerId, Device newDevice) {
148 -
149 // update composed device cache 147 // update composed device cache
150 Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice); 148 Device oldDevice = devices.putIfAbsent(newDevice.id(), newDevice);
151 verify(oldDevice == null, 149 verify(oldDevice == null,
...@@ -162,14 +160,21 @@ public class SimpleDeviceStore ...@@ -162,14 +160,21 @@ public class SimpleDeviceStore
162 // Updates the device and returns the appropriate event if necessary. 160 // Updates the device and returns the appropriate event if necessary.
163 // Guarded by deviceDescs value (=Device lock) 161 // Guarded by deviceDescs value (=Device lock)
164 private DeviceEvent updateDevice(ProviderId providerId, Device oldDevice, Device newDevice) { 162 private DeviceEvent updateDevice(ProviderId providerId, Device oldDevice, Device newDevice) {
165 -
166 // We allow only certain attributes to trigger update 163 // We allow only certain attributes to trigger update
167 - if (!Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) || 164 + boolean propertiesChanged =
168 - !Objects.equals(oldDevice.swVersion(), newDevice.swVersion()) || 165 + !Objects.equals(oldDevice.hwVersion(), newDevice.hwVersion()) ||
169 - !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations())) { 166 + !Objects.equals(oldDevice.swVersion(), newDevice.swVersion());
167 + boolean annotationsChanged =
168 + !AnnotationsUtil.isEqual(oldDevice.annotations(), newDevice.annotations());
169 +
170 + // Primary providers can respond to all changes, but ancillary ones
171 + // should respond only to annotation changes.
172 + if ((providerId.isAncillary() && annotationsChanged) ||
173 + (!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) {
170 174
171 boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice); 175 boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice);
172 if (!replaced) { 176 if (!replaced) {
177 + // FIXME: Is the enclosing if required here?
173 verify(replaced, 178 verify(replaced,
174 "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]", 179 "Replacing devices cache failed. PID:%s [expected:%s, found:%s, new=%s]",
175 providerId, oldDevice, devices.get(newDevice.id()) 180 providerId, oldDevice, devices.get(newDevice.id())
...@@ -214,7 +219,6 @@ public class SimpleDeviceStore ...@@ -214,7 +219,6 @@ public class SimpleDeviceStore
214 public List<DeviceEvent> updatePorts(ProviderId providerId, 219 public List<DeviceEvent> updatePorts(ProviderId providerId,
215 DeviceId deviceId, 220 DeviceId deviceId,
216 List<PortDescription> portDescriptions) { 221 List<PortDescription> portDescriptions) {
217 -
218 Device device = devices.get(deviceId); 222 Device device = devices.get(deviceId);
219 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId); 223 checkArgument(device != null, DEVICE_NOT_FOUND, deviceId);
220 224
...@@ -327,7 +331,6 @@ public class SimpleDeviceStore ...@@ -327,7 +331,6 @@ public class SimpleDeviceStore
327 private DeviceDescriptions getOrCreateProviderDeviceDescriptions( 331 private DeviceDescriptions getOrCreateProviderDeviceDescriptions(
328 Map<ProviderId, DeviceDescriptions> device, 332 Map<ProviderId, DeviceDescriptions> device,
329 ProviderId providerId, DeviceDescription deltaDesc) { 333 ProviderId providerId, DeviceDescription deltaDesc) {
330 -
331 synchronized (device) { 334 synchronized (device) {
332 DeviceDescriptions r = device.get(providerId); 335 DeviceDescriptions r = device.get(providerId);
333 if (r == null) { 336 if (r == null) {
...@@ -447,7 +450,7 @@ public class SimpleDeviceStore ...@@ -447,7 +450,7 @@ public class SimpleDeviceStore
447 annotations = merge(annotations, e.getValue().getDeviceDesc().annotations()); 450 annotations = merge(annotations, e.getValue().getDeviceDesc().annotations());
448 } 451 }
449 452
450 - return new DefaultDevice(primary, deviceId , type, manufacturer, 453 + return new DefaultDevice(primary, deviceId, type, manufacturer,
451 hwVersion, swVersion, serialNumber, 454 hwVersion, swVersion, serialNumber,
452 chassisId, annotations); 455 chassisId, annotations);
453 } 456 }
......