Jonathan Hart

Implemented adding and removing address bindings in the store, along with unit tests.

1 package org.onlab.onos.net.host; 1 package org.onlab.onos.net.host;
2 2
3 +import java.util.Collections;
3 import java.util.HashSet; 4 import java.util.HashSet;
5 +import java.util.Objects;
4 import java.util.Set; 6 import java.util.Set;
5 7
6 import org.onlab.onos.net.ConnectPoint; 8 import org.onlab.onos.net.ConnectPoint;
...@@ -29,7 +31,7 @@ public class PortAddresses { ...@@ -29,7 +31,7 @@ public class PortAddresses {
29 public PortAddresses(ConnectPoint connectPoint, 31 public PortAddresses(ConnectPoint connectPoint,
30 Set<IpPrefix> ips, MacAddress mac) { 32 Set<IpPrefix> ips, MacAddress mac) {
31 this.connectPoint = connectPoint; 33 this.connectPoint = connectPoint;
32 - this.ipAddresses = (ips == null) ? null : new HashSet<>(ips); 34 + this.ipAddresses = (ips == null) ? Collections.<IpPrefix>emptySet() : new HashSet<>(ips);
33 this.macAddress = mac; 35 this.macAddress = mac;
34 } 36 }
35 37
...@@ -60,4 +62,25 @@ public class PortAddresses { ...@@ -60,4 +62,25 @@ public class PortAddresses {
60 return macAddress; 62 return macAddress;
61 } 63 }
62 64
65 + @Override
66 + public boolean equals(Object other) {
67 + if (this == other) {
68 + return true;
69 + }
70 +
71 + if (!(other instanceof PortAddresses)) {
72 + return false;
73 + }
74 +
75 + PortAddresses otherPa = (PortAddresses) other;
76 +
77 + return Objects.equals(this.connectPoint, otherPa.connectPoint)
78 + && Objects.equals(this.ipAddresses, otherPa.ipAddresses)
79 + && Objects.equals(this.macAddress, otherPa.macAddress);
80 + }
81 +
82 + @Override
83 + public int hashCode() {
84 + return Objects.hash(connectPoint, ipAddresses, macAddress);
85 + }
63 } 86 }
......
...@@ -2,9 +2,13 @@ package org.onlab.onos.net.host.impl; ...@@ -2,9 +2,13 @@ package org.onlab.onos.net.host.impl;
2 2
3 import static org.junit.Assert.assertEquals; 3 import static org.junit.Assert.assertEquals;
4 import static org.junit.Assert.assertFalse; 4 import static org.junit.Assert.assertFalse;
5 -import static org.junit.Assert.assertNull;
6 import static org.junit.Assert.assertNotNull; 5 import static org.junit.Assert.assertNotNull;
6 +import static org.junit.Assert.assertNull;
7 import static org.junit.Assert.assertTrue; 7 import static org.junit.Assert.assertTrue;
8 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_ADDED;
9 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_MOVED;
10 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_REMOVED;
11 +import static org.onlab.onos.net.host.HostEvent.Type.HOST_UPDATED;
8 12
9 import java.util.List; 13 import java.util.List;
10 import java.util.Set; 14 import java.util.Set;
...@@ -14,6 +18,7 @@ import org.junit.Before; ...@@ -14,6 +18,7 @@ import org.junit.Before;
14 import org.junit.Test; 18 import org.junit.Test;
15 import org.onlab.onos.event.Event; 19 import org.onlab.onos.event.Event;
16 import org.onlab.onos.event.impl.TestEventDispatcher; 20 import org.onlab.onos.event.impl.TestEventDispatcher;
21 +import org.onlab.onos.net.ConnectPoint;
17 import org.onlab.onos.net.DeviceId; 22 import org.onlab.onos.net.DeviceId;
18 import org.onlab.onos.net.Host; 23 import org.onlab.onos.net.Host;
19 import org.onlab.onos.net.HostId; 24 import org.onlab.onos.net.HostId;
...@@ -26,6 +31,7 @@ import org.onlab.onos.net.host.HostListener; ...@@ -26,6 +31,7 @@ import org.onlab.onos.net.host.HostListener;
26 import org.onlab.onos.net.host.HostProvider; 31 import org.onlab.onos.net.host.HostProvider;
27 import org.onlab.onos.net.host.HostProviderRegistry; 32 import org.onlab.onos.net.host.HostProviderRegistry;
28 import org.onlab.onos.net.host.HostProviderService; 33 import org.onlab.onos.net.host.HostProviderService;
34 +import org.onlab.onos.net.host.PortAddresses;
29 import org.onlab.onos.net.provider.AbstractProvider; 35 import org.onlab.onos.net.provider.AbstractProvider;
30 import org.onlab.onos.net.provider.ProviderId; 36 import org.onlab.onos.net.provider.ProviderId;
31 import org.onlab.onos.net.trivial.impl.SimpleHostStore; 37 import org.onlab.onos.net.trivial.impl.SimpleHostStore;
...@@ -36,8 +42,6 @@ import org.onlab.packet.VlanId; ...@@ -36,8 +42,6 @@ import org.onlab.packet.VlanId;
36 import com.google.common.collect.Lists; 42 import com.google.common.collect.Lists;
37 import com.google.common.collect.Sets; 43 import com.google.common.collect.Sets;
38 44
39 -import static org.onlab.onos.net.host.HostEvent.Type.*;
40 -
41 /** 45 /**
42 * Test codifying the host service & host provider service contracts. 46 * Test codifying the host service & host provider service contracts.
43 */ 47 */
...@@ -63,6 +67,12 @@ public class HostManagerTest { ...@@ -63,6 +67,12 @@ public class HostManagerTest {
63 private static final PortNumber P2 = PortNumber.portNumber(200); 67 private static final PortNumber P2 = PortNumber.portNumber(200);
64 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L); 68 private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
65 private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L); 69 private static final HostLocation LOC2 = new HostLocation(DID1, P2, 123L);
70 + private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
71 + private static final ConnectPoint CP2 = new ConnectPoint(DID2, P2);
72 +
73 + private static final IpPrefix PREFIX1 = IpPrefix.valueOf("10.0.1.0/24");
74 + private static final IpPrefix PREFIX2 = IpPrefix.valueOf("10.1.0.0/16");
75 + private static final IpPrefix PREFIX3 = IpPrefix.valueOf("5.8.2.0/23");
66 76
67 private HostManager mgr; 77 private HostManager mgr;
68 78
...@@ -196,4 +206,130 @@ public class HostManagerTest { ...@@ -196,4 +206,130 @@ public class HostManagerTest {
196 } 206 }
197 207
198 } 208 }
209 +
210 + @Test
211 + public void bindAddressesToPort() {
212 + PortAddresses add1 = new PortAddresses(CP1,
213 + Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
214 +
215 + mgr.bindAddressesToPort(add1);
216 + PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
217 +
218 + assertTrue(add1.ips().equals(storedAddresses.ips()));
219 + assertTrue(add1.mac().equals(storedAddresses.mac()));
220 +
221 + // Add some more addresses and check that they're added correctly
222 + PortAddresses add2 = new PortAddresses(CP1, Sets.newHashSet(PREFIX3), null);
223 +
224 + mgr.bindAddressesToPort(add2);
225 + storedAddresses = mgr.getAddressBindingsForPort(CP1);
226 +
227 + assertTrue(storedAddresses.ips().equals(
228 + Sets.newHashSet(PREFIX1, PREFIX2, PREFIX3)));
229 + assertTrue(storedAddresses.mac().equals(MAC1));
230 +
231 + PortAddresses add3 = new PortAddresses(CP1, null, MAC2);
232 +
233 + mgr.bindAddressesToPort(add3);
234 + storedAddresses = mgr.getAddressBindingsForPort(CP1);
235 +
236 + assertTrue(storedAddresses.ips().equals(
237 + Sets.newHashSet(PREFIX1, PREFIX2, PREFIX3)));
238 + assertTrue(storedAddresses.mac().equals(MAC2));
239 + }
240 +
241 + @Test
242 + public void unbindAddressesFromPort() {
243 + PortAddresses add1 = new PortAddresses(CP1,
244 + Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
245 +
246 + mgr.bindAddressesToPort(add1);
247 + PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
248 +
249 + assertTrue(storedAddresses.ips().size() == 2);
250 + assertNotNull(storedAddresses.mac());
251 +
252 + PortAddresses rem1 = new PortAddresses(CP1,
253 + Sets.newHashSet(PREFIX1), null);
254 +
255 + mgr.unbindAddressesFromPort(rem1);
256 + storedAddresses = mgr.getAddressBindingsForPort(CP1);
257 +
258 + assertTrue(storedAddresses.ips().equals(Sets.newHashSet(PREFIX2)));
259 + assertTrue(storedAddresses.mac().equals(MAC1));
260 +
261 + PortAddresses rem2 = new PortAddresses(CP1, null, MAC1);
262 +
263 + mgr.unbindAddressesFromPort(rem2);
264 + storedAddresses = mgr.getAddressBindingsForPort(CP1);
265 +
266 + assertTrue(storedAddresses.ips().equals(Sets.newHashSet(PREFIX2)));
267 + assertNull(storedAddresses.mac());
268 +
269 + PortAddresses rem3 = new PortAddresses(CP1,
270 + Sets.newHashSet(PREFIX2), MAC1);
271 +
272 + mgr.unbindAddressesFromPort(rem3);
273 + storedAddresses = mgr.getAddressBindingsForPort(CP1);
274 +
275 + assertTrue(storedAddresses.ips().isEmpty());
276 + assertNull(storedAddresses.mac());
277 + }
278 +
279 + @Test
280 + public void clearAddresses() {
281 + PortAddresses add1 = new PortAddresses(CP1,
282 + Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
283 +
284 + mgr.bindAddressesToPort(add1);
285 + PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
286 +
287 + assertTrue(storedAddresses.ips().size() == 2);
288 + assertNotNull(storedAddresses.mac());
289 +
290 + mgr.clearAddresses(CP1);
291 + storedAddresses = mgr.getAddressBindingsForPort(CP1);
292 +
293 + assertTrue(storedAddresses.ips().isEmpty());
294 + assertNull(storedAddresses.mac());
295 + }
296 +
297 + @Test
298 + public void getAddressBindingsForPort() {
299 + PortAddresses add1 = new PortAddresses(CP1,
300 + Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
301 +
302 + mgr.bindAddressesToPort(add1);
303 + PortAddresses storedAddresses = mgr.getAddressBindingsForPort(CP1);
304 +
305 + assertTrue(storedAddresses.connectPoint().equals(CP1));
306 + assertTrue(storedAddresses.ips().equals(Sets.newHashSet(PREFIX1, PREFIX2)));
307 + assertTrue(storedAddresses.mac().equals(MAC1));
308 + }
309 +
310 + @Test
311 + public void getAddressBindings() {
312 + Set<PortAddresses> storedAddresses = mgr.getAddressBindings();
313 +
314 + assertTrue(storedAddresses.isEmpty());
315 +
316 + PortAddresses add1 = new PortAddresses(CP1,
317 + Sets.newHashSet(PREFIX1, PREFIX2), MAC1);
318 +
319 + mgr.bindAddressesToPort(add1);
320 +
321 + storedAddresses = mgr.getAddressBindings();
322 +
323 + assertTrue(storedAddresses.size() == 1);
324 +
325 + PortAddresses add2 = new PortAddresses(CP2,
326 + Sets.newHashSet(PREFIX3), MAC2);
327 +
328 + mgr.bindAddressesToPort(add2);
329 +
330 + storedAddresses = mgr.getAddressBindings();
331 +
332 + assertTrue(storedAddresses.size() == 2);
333 + assertTrue(storedAddresses.equals(Sets.newHashSet(add1, add2)));
334 + }
199 } 335 }
......
...@@ -36,6 +36,7 @@ import org.slf4j.Logger; ...@@ -36,6 +36,7 @@ import org.slf4j.Logger;
36 import com.google.common.collect.HashMultimap; 36 import com.google.common.collect.HashMultimap;
37 import com.google.common.collect.ImmutableSet; 37 import com.google.common.collect.ImmutableSet;
38 import com.google.common.collect.Multimap; 38 import com.google.common.collect.Multimap;
39 +import com.google.common.collect.Sets;
39 40
40 /** 41 /**
41 * Manages inventory of end-station hosts using trivial in-memory 42 * Manages inventory of end-station hosts using trivial in-memory
...@@ -202,29 +203,75 @@ public class SimpleHostStore ...@@ -202,29 +203,75 @@ public class SimpleHostStore
202 203
203 @Override 204 @Override
204 public void updateAddressBindings(PortAddresses addresses) { 205 public void updateAddressBindings(PortAddresses addresses) {
205 - // TODO portAddresses.put(addresses.connectPoint(), addresses); 206 + synchronized (portAddresses) {
207 + PortAddresses existing = portAddresses.get(addresses.connectPoint());
208 + if (existing == null) {
209 + portAddresses.put(addresses.connectPoint(), addresses);
210 + } else {
211 + Set<IpPrefix> union = Sets.union(existing.ips(), addresses.ips())
212 + .immutableCopy();
213 +
214 + MacAddress newMac = (addresses.mac() == null) ? existing.mac()
215 + : addresses.mac();
216 +
217 + PortAddresses newAddresses =
218 + new PortAddresses(addresses.connectPoint(), union, newMac);
219 +
220 + portAddresses.put(newAddresses.connectPoint(), newAddresses);
221 + }
222 + }
206 } 223 }
207 224
208 @Override 225 @Override
209 public void removeAddressBindings(PortAddresses addresses) { 226 public void removeAddressBindings(PortAddresses addresses) {
210 - // TODO Auto-generated method stub 227 + synchronized (portAddresses) {
228 + PortAddresses existing = portAddresses.get(addresses.connectPoint());
229 + if (existing != null) {
230 + Set<IpPrefix> difference =
231 + Sets.difference(existing.ips(), addresses.ips()).immutableCopy();
211 232
233 + // If they removed the existing mac, set the new mac to null.
234 + // Otherwise, keep the existing mac.
235 + MacAddress newMac = existing.mac();
236 + if (addresses.mac() != null && addresses.mac().equals(existing.mac())) {
237 + newMac = null;
238 + }
239 +
240 + PortAddresses newAddresses =
241 + new PortAddresses(addresses.connectPoint(), difference, newMac);
242 +
243 + portAddresses.put(newAddresses.connectPoint(), newAddresses);
244 + }
245 + }
212 } 246 }
213 247
214 @Override 248 @Override
215 public void clearAddressBindings(ConnectPoint connectPoint) { 249 public void clearAddressBindings(ConnectPoint connectPoint) {
216 - // TODO Auto-generated method stub 250 + synchronized (portAddresses) {
217 - 251 + portAddresses.remove(connectPoint);
252 + }
218 } 253 }
219 254
220 @Override 255 @Override
221 public Set<PortAddresses> getAddressBindings() { 256 public Set<PortAddresses> getAddressBindings() {
257 + synchronized (portAddresses) {
222 return new HashSet<>(portAddresses.values()); 258 return new HashSet<>(portAddresses.values());
223 } 259 }
260 + }
224 261
225 @Override 262 @Override
226 public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) { 263 public PortAddresses getAddressBindingsForPort(ConnectPoint connectPoint) {
227 - return portAddresses.get(connectPoint); 264 + PortAddresses addresses;
265 +
266 + synchronized (portAddresses) {
267 + addresses = portAddresses.get(connectPoint);
268 + }
269 +
270 + if (addresses == null) {
271 + addresses = new PortAddresses(connectPoint, null, null);
272 + }
273 +
274 + return addresses;
228 } 275 }
229 276
230 } 277 }
......