Praseed Balakrishnan

Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next

Showing 31 changed files with 2590 additions and 264 deletions
...@@ -45,6 +45,12 @@ ...@@ -45,6 +45,12 @@
45 45
46 <dependency> 46 <dependency>
47 <groupId>org.onlab.onos</groupId> 47 <groupId>org.onlab.onos</groupId>
48 + <artifactId>onlab-junit</artifactId>
49 + <scope>test</scope>
50 + </dependency>
51 +
52 + <dependency>
53 + <groupId>org.onlab.onos</groupId>
48 <artifactId>onos-cli</artifactId> 54 <artifactId>onos-cli</artifactId>
49 <version>${project.version}</version> 55 <version>${project.version}</version>
50 </dependency> 56 </dependency>
......
1 package org.onlab.onos.sdnip; 1 package org.onlab.onos.sdnip;
2 2
3 +import java.util.List;
4 +
3 import org.onlab.onos.ApplicationId; 5 import org.onlab.onos.ApplicationId;
4 import org.onlab.onos.net.ConnectPoint; 6 import org.onlab.onos.net.ConnectPoint;
5 import org.onlab.onos.net.flow.DefaultTrafficSelector; 7 import org.onlab.onos.net.flow.DefaultTrafficSelector;
...@@ -8,6 +10,7 @@ import org.onlab.onos.net.flow.TrafficSelector; ...@@ -8,6 +10,7 @@ import org.onlab.onos.net.flow.TrafficSelector;
8 import org.onlab.onos.net.flow.TrafficTreatment; 10 import org.onlab.onos.net.flow.TrafficTreatment;
9 import org.onlab.onos.net.intent.IntentService; 11 import org.onlab.onos.net.intent.IntentService;
10 import org.onlab.onos.net.intent.PointToPointIntent; 12 import org.onlab.onos.net.intent.PointToPointIntent;
13 +import org.onlab.onos.sdnip.bgp.BgpConstants;
11 import org.onlab.onos.sdnip.config.BgpPeer; 14 import org.onlab.onos.sdnip.config.BgpPeer;
12 import org.onlab.onos.sdnip.config.BgpSpeaker; 15 import org.onlab.onos.sdnip.config.BgpSpeaker;
13 import org.onlab.onos.sdnip.config.Interface; 16 import org.onlab.onos.sdnip.config.Interface;
...@@ -20,8 +23,6 @@ import org.onlab.packet.IpPrefix; ...@@ -20,8 +23,6 @@ import org.onlab.packet.IpPrefix;
20 import org.slf4j.Logger; 23 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory; 24 import org.slf4j.LoggerFactory;
22 25
23 -import java.util.List;
24 -
25 /** 26 /**
26 * Manages the connectivity requirements between peers. 27 * Manages the connectivity requirements between peers.
27 */ 28 */
...@@ -30,37 +31,44 @@ public class PeerConnectivityManager { ...@@ -30,37 +31,44 @@ public class PeerConnectivityManager {
30 private static final Logger log = LoggerFactory.getLogger( 31 private static final Logger log = LoggerFactory.getLogger(
31 PeerConnectivityManager.class); 32 PeerConnectivityManager.class);
32 33
33 - // TODO these shouldn't be defined here 34 + private final SdnIpConfigService configService;
34 - private static final short BGP_PORT = 179;
35 - private static final int IPV4_BIT_LENGTH = 32;
36 -
37 - private final SdnIpConfigService configInfoService;
38 private final InterfaceService interfaceService; 35 private final InterfaceService interfaceService;
39 private final IntentService intentService; 36 private final IntentService intentService;
40 37
41 private final ApplicationId appId; 38 private final ApplicationId appId;
42 39
40 + /**
41 + * Creates a new PeerConnectivityManager.
42 + *
43 + * @param appId the application ID
44 + * @param configService the SDN-IP config service
45 + * @param interfaceService the interface service
46 + * @param intentService the intent service
47 + */
43 public PeerConnectivityManager(ApplicationId appId, 48 public PeerConnectivityManager(ApplicationId appId,
44 - SdnIpConfigService configInfoService, 49 + SdnIpConfigService configService,
45 InterfaceService interfaceService, 50 InterfaceService interfaceService,
46 IntentService intentService) { 51 IntentService intentService) {
47 this.appId = appId; 52 this.appId = appId;
48 - this.configInfoService = configInfoService; 53 + this.configService = configService;
49 this.interfaceService = interfaceService; 54 this.interfaceService = interfaceService;
50 this.intentService = intentService; 55 this.intentService = intentService;
51 } 56 }
52 57
58 + /**
59 + * Starts the peer connectivity manager.
60 + */
53 public void start() { 61 public void start() {
54 // TODO are any of these errors? 62 // TODO are any of these errors?
55 if (interfaceService.getInterfaces().isEmpty()) { 63 if (interfaceService.getInterfaces().isEmpty()) {
56 64
57 log.warn("The interface in configuration file is empty. " 65 log.warn("The interface in configuration file is empty. "
58 + "Thus, the SDN-IP application can not be started."); 66 + "Thus, the SDN-IP application can not be started.");
59 - } else if (configInfoService.getBgpPeers().isEmpty()) { 67 + } else if (configService.getBgpPeers().isEmpty()) {
60 68
61 log.warn("The BGP peer in configuration file is empty." 69 log.warn("The BGP peer in configuration file is empty."
62 + "Thus, the SDN-IP application can not be started."); 70 + "Thus, the SDN-IP application can not be started.");
63 - } else if (configInfoService.getBgpSpeakers() == null) { 71 + } else if (configService.getBgpSpeakers() == null) {
64 72
65 log.error("The BGP speaker in configuration file is empty. " 73 log.error("The BGP speaker in configuration file is empty. "
66 + "Thus, the SDN-IP application can not be started."); 74 + "Thus, the SDN-IP application can not be started.");
...@@ -79,7 +87,7 @@ public class PeerConnectivityManager { ...@@ -79,7 +87,7 @@ public class PeerConnectivityManager {
79 * for paths from all peers to each BGP speaker. 87 * for paths from all peers to each BGP speaker.
80 */ 88 */
81 private void setupBgpPaths() { 89 private void setupBgpPaths() {
82 - for (BgpSpeaker bgpSpeaker : configInfoService.getBgpSpeakers() 90 + for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
83 .values()) { 91 .values()) {
84 log.debug("Start to set up BGP paths for BGP speaker: {}", 92 log.debug("Start to set up BGP paths for BGP speaker: {}",
85 bgpSpeaker); 93 bgpSpeaker);
...@@ -88,7 +96,7 @@ public class PeerConnectivityManager { ...@@ -88,7 +96,7 @@ public class PeerConnectivityManager {
88 List<InterfaceAddress> interfaceAddresses = 96 List<InterfaceAddress> interfaceAddresses =
89 bgpSpeaker.interfaceAddresses(); 97 bgpSpeaker.interfaceAddresses();
90 98
91 - for (BgpPeer bgpPeer : configInfoService.getBgpPeers().values()) { 99 + for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
92 100
93 log.debug("Start to set up BGP paths between BGP speaker: {} " 101 log.debug("Start to set up BGP paths between BGP speaker: {} "
94 + "to BGP peer: {}", bgpSpeaker, bgpPeer); 102 + "to BGP peer: {}", bgpSpeaker, bgpPeer);
...@@ -121,16 +129,14 @@ public class PeerConnectivityManager { ...@@ -121,16 +129,14 @@ public class PeerConnectivityManager {
121 129
122 // install intent for BGP path from BGPd to BGP peer matching 130 // install intent for BGP path from BGPd to BGP peer matching
123 // destination TCP port 179 131 // destination TCP port 179
124 -
125 - // TODO: The usage of PacketMatchBuilder will be improved, then we
126 - // only need to new the PacketMatchBuilder once.
127 - // By then, the code here will be improved accordingly.
128 TrafficSelector selector = DefaultTrafficSelector.builder() 132 TrafficSelector selector = DefaultTrafficSelector.builder()
129 .matchEthType(Ethernet.TYPE_IPV4) 133 .matchEthType(Ethernet.TYPE_IPV4)
130 .matchIPProtocol(IPv4.PROTOCOL_TCP) 134 .matchIPProtocol(IPv4.PROTOCOL_TCP)
131 - .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH)) 135 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(),
132 - .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH)) 136 + IpAddress.MAX_INET_MASK))
133 - .matchTcpDst(BGP_PORT) 137 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(),
138 + IpAddress.MAX_INET_MASK))
139 + .matchTcpDst((short) BgpConstants.BGP_PORT)
134 .build(); 140 .build();
135 141
136 TrafficTreatment treatment = DefaultTrafficTreatment.builder() 142 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
...@@ -149,9 +155,11 @@ public class PeerConnectivityManager { ...@@ -149,9 +155,11 @@ public class PeerConnectivityManager {
149 selector = DefaultTrafficSelector.builder() 155 selector = DefaultTrafficSelector.builder()
150 .matchEthType(Ethernet.TYPE_IPV4) 156 .matchEthType(Ethernet.TYPE_IPV4)
151 .matchIPProtocol(IPv4.PROTOCOL_TCP) 157 .matchIPProtocol(IPv4.PROTOCOL_TCP)
152 - .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH)) 158 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(),
153 - .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH)) 159 + IpAddress.MAX_INET_MASK))
154 - .matchTcpSrc(BGP_PORT) 160 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(),
161 + IpAddress.MAX_INET_MASK))
162 + .matchTcpSrc((short) BgpConstants.BGP_PORT)
155 .build(); 163 .build();
156 164
157 PointToPointIntent intentMatchSrcTcpPort = 165 PointToPointIntent intentMatchSrcTcpPort =
...@@ -167,9 +175,11 @@ public class PeerConnectivityManager { ...@@ -167,9 +175,11 @@ public class PeerConnectivityManager {
167 selector = DefaultTrafficSelector.builder() 175 selector = DefaultTrafficSelector.builder()
168 .matchEthType(Ethernet.TYPE_IPV4) 176 .matchEthType(Ethernet.TYPE_IPV4)
169 .matchIPProtocol(IPv4.PROTOCOL_TCP) 177 .matchIPProtocol(IPv4.PROTOCOL_TCP)
170 - .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH)) 178 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(),
171 - .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH)) 179 + IpAddress.MAX_INET_MASK))
172 - .matchTcpDst(BGP_PORT) 180 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(),
181 + IpAddress.MAX_INET_MASK))
182 + .matchTcpDst((short) BgpConstants.BGP_PORT)
173 .build(); 183 .build();
174 184
175 PointToPointIntent reversedIntentMatchDstTcpPort = 185 PointToPointIntent reversedIntentMatchDstTcpPort =
...@@ -185,9 +195,11 @@ public class PeerConnectivityManager { ...@@ -185,9 +195,11 @@ public class PeerConnectivityManager {
185 selector = DefaultTrafficSelector.builder() 195 selector = DefaultTrafficSelector.builder()
186 .matchEthType(Ethernet.TYPE_IPV4) 196 .matchEthType(Ethernet.TYPE_IPV4)
187 .matchIPProtocol(IPv4.PROTOCOL_TCP) 197 .matchIPProtocol(IPv4.PROTOCOL_TCP)
188 - .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH)) 198 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(),
189 - .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH)) 199 + IpAddress.MAX_INET_MASK))
190 - .matchTcpSrc(BGP_PORT) 200 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(),
201 + IpAddress.MAX_INET_MASK))
202 + .matchTcpSrc((short) BgpConstants.BGP_PORT)
191 .build(); 203 .build();
192 204
193 PointToPointIntent reversedIntentMatchSrcTcpPort = 205 PointToPointIntent reversedIntentMatchSrcTcpPort =
...@@ -211,7 +223,7 @@ public class PeerConnectivityManager { ...@@ -211,7 +223,7 @@ public class PeerConnectivityManager {
211 * for paths from all peers to each BGP speaker. 223 * for paths from all peers to each BGP speaker.
212 */ 224 */
213 private void setupIcmpPaths() { 225 private void setupIcmpPaths() {
214 - for (BgpSpeaker bgpSpeaker : configInfoService.getBgpSpeakers() 226 + for (BgpSpeaker bgpSpeaker : configService.getBgpSpeakers()
215 .values()) { 227 .values()) {
216 log.debug("Start to set up ICMP paths for BGP speaker: {}", 228 log.debug("Start to set up ICMP paths for BGP speaker: {}",
217 bgpSpeaker); 229 bgpSpeaker);
...@@ -219,7 +231,7 @@ public class PeerConnectivityManager { ...@@ -219,7 +231,7 @@ public class PeerConnectivityManager {
219 List<InterfaceAddress> interfaceAddresses = bgpSpeaker 231 List<InterfaceAddress> interfaceAddresses = bgpSpeaker
220 .interfaceAddresses(); 232 .interfaceAddresses();
221 233
222 - for (BgpPeer bgpPeer : configInfoService.getBgpPeers().values()) { 234 + for (BgpPeer bgpPeer : configService.getBgpPeers().values()) {
223 235
224 Interface peerInterface = interfaceService.getInterface( 236 Interface peerInterface = interfaceService.getInterface(
225 bgpPeer.connectPoint()); 237 bgpPeer.connectPoint());
...@@ -253,8 +265,10 @@ public class PeerConnectivityManager { ...@@ -253,8 +265,10 @@ public class PeerConnectivityManager {
253 TrafficSelector selector = DefaultTrafficSelector.builder() 265 TrafficSelector selector = DefaultTrafficSelector.builder()
254 .matchEthType(Ethernet.TYPE_IPV4) 266 .matchEthType(Ethernet.TYPE_IPV4)
255 .matchIPProtocol(IPv4.PROTOCOL_ICMP) 267 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
256 - .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH)) 268 + .matchIPSrc(IpPrefix.valueOf(bgpdAddress.toInt(),
257 - .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH)) 269 + IpAddress.MAX_INET_MASK))
270 + .matchIPDst(IpPrefix.valueOf(bgpdPeerAddress.toInt(),
271 + IpAddress.MAX_INET_MASK))
258 .build(); 272 .build();
259 273
260 TrafficTreatment treatment = DefaultTrafficTreatment.builder() 274 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
...@@ -271,8 +285,10 @@ public class PeerConnectivityManager { ...@@ -271,8 +285,10 @@ public class PeerConnectivityManager {
271 selector = DefaultTrafficSelector.builder() 285 selector = DefaultTrafficSelector.builder()
272 .matchEthType(Ethernet.TYPE_IPV4) 286 .matchEthType(Ethernet.TYPE_IPV4)
273 .matchIPProtocol(IPv4.PROTOCOL_ICMP) 287 .matchIPProtocol(IPv4.PROTOCOL_ICMP)
274 - .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(), IPV4_BIT_LENGTH)) 288 + .matchIPSrc(IpPrefix.valueOf(bgpdPeerAddress.toInt(),
275 - .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(), IPV4_BIT_LENGTH)) 289 + IpAddress.MAX_INET_MASK))
290 + .matchIPDst(IpPrefix.valueOf(bgpdAddress.toInt(),
291 + IpAddress.MAX_INET_MASK))
276 .build(); 292 .build();
277 293
278 PointToPointIntent reversedIntent = 294 PointToPointIntent reversedIntent =
......
...@@ -55,8 +55,6 @@ import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree; ...@@ -55,8 +55,6 @@ import com.googlecode.concurrenttrees.radixinverted.InvertedRadixTree;
55 /** 55 /**
56 * This class processes BGP route update, translates each update into a intent 56 * This class processes BGP route update, translates each update into a intent
57 * and submits the intent. 57 * and submits the intent.
58 - * <p/>
59 - * TODO: Make it thread-safe.
60 */ 58 */
61 public class Router implements RouteListener { 59 public class Router implements RouteListener {
62 60
...@@ -69,14 +67,13 @@ public class Router implements RouteListener { ...@@ -69,14 +67,13 @@ public class Router implements RouteListener {
69 // Stores all incoming route updates in a queue. 67 // Stores all incoming route updates in a queue.
70 private BlockingQueue<RouteUpdate> routeUpdates; 68 private BlockingQueue<RouteUpdate> routeUpdates;
71 69
72 - // The Ip4Address is the next hop address of each route update. 70 + // The IpAddress is the next hop address of each route update.
73 private SetMultimap<IpAddress, RouteEntry> routesWaitingOnArp; 71 private SetMultimap<IpAddress, RouteEntry> routesWaitingOnArp;
74 private ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent> pushedRouteIntents; 72 private ConcurrentHashMap<IpPrefix, MultiPointToSinglePointIntent> pushedRouteIntents;
75 73
76 private IntentService intentService; 74 private IntentService intentService;
77 - //private IProxyArpService proxyArp;
78 private HostService hostService; 75 private HostService hostService;
79 - private SdnIpConfigService configInfoService; 76 + private SdnIpConfigService configService;
80 private InterfaceService interfaceService; 77 private InterfaceService interfaceService;
81 78
82 private ExecutorService bgpUpdatesExecutor; 79 private ExecutorService bgpUpdatesExecutor;
...@@ -98,18 +95,19 @@ public class Router implements RouteListener { ...@@ -98,18 +95,19 @@ public class Router implements RouteListener {
98 /** 95 /**
99 * Class constructor. 96 * Class constructor.
100 * 97 *
98 + * @param appId the application ID
101 * @param intentService the intent service 99 * @param intentService the intent service
102 * @param hostService the host service 100 * @param hostService the host service
103 - * @param configInfoService the configuration service 101 + * @param configService the configuration service
104 * @param interfaceService the interface service 102 * @param interfaceService the interface service
105 */ 103 */
106 public Router(ApplicationId appId, IntentService intentService, 104 public Router(ApplicationId appId, IntentService intentService,
107 - HostService hostService, SdnIpConfigService configInfoService, 105 + HostService hostService, SdnIpConfigService configService,
108 InterfaceService interfaceService) { 106 InterfaceService interfaceService) {
109 this.appId = appId; 107 this.appId = appId;
110 this.intentService = intentService; 108 this.intentService = intentService;
111 this.hostService = hostService; 109 this.hostService = hostService;
112 - this.configInfoService = configInfoService; 110 + this.configService = configService;
113 this.interfaceService = interfaceService; 111 this.interfaceService = interfaceService;
114 112
115 bgpRoutes = new ConcurrentInvertedRadixTree<>( 113 bgpRoutes = new ConcurrentInvertedRadixTree<>(
...@@ -172,7 +170,7 @@ public class Router implements RouteListener { ...@@ -172,7 +170,7 @@ public class Router implements RouteListener {
172 170
173 @Override 171 @Override
174 public void update(RouteUpdate routeUpdate) { 172 public void update(RouteUpdate routeUpdate) {
175 - log.debug("Received new route Update: {}", routeUpdate); 173 + log.debug("Received new route update: {}", routeUpdate);
176 174
177 try { 175 try {
178 routeUpdates.put(routeUpdate); 176 routeUpdates.put(routeUpdate);
...@@ -498,9 +496,11 @@ public class Router implements RouteListener { ...@@ -498,9 +496,11 @@ public class Router implements RouteListener {
498 private void executeRouteAdd(RouteEntry routeEntry) { 496 private void executeRouteAdd(RouteEntry routeEntry) {
499 log.debug("Executing route add: {}", routeEntry); 497 log.debug("Executing route add: {}", routeEntry);
500 498
499 + // Monitor the IP address so we'll get notified of updates to the MAC
500 + // address.
501 + hostService.startMonitoringIp(routeEntry.nextHop());
502 +
501 // See if we know the MAC address of the next hop 503 // See if we know the MAC address of the next hop
502 - //MacAddress nextHopMacAddress =
503 - //proxyArp.getMacAddress(routeEntry.getNextHop());
504 MacAddress nextHopMacAddress = null; 504 MacAddress nextHopMacAddress = null;
505 Set<Host> hosts = hostService.getHostsByIp( 505 Set<Host> hosts = hostService.getHostsByIp(
506 routeEntry.nextHop().toPrefix()); 506 routeEntry.nextHop().toPrefix());
...@@ -511,9 +511,6 @@ public class Router implements RouteListener { ...@@ -511,9 +511,6 @@ public class Router implements RouteListener {
511 511
512 if (nextHopMacAddress == null) { 512 if (nextHopMacAddress == null) {
513 routesWaitingOnArp.put(routeEntry.nextHop(), routeEntry); 513 routesWaitingOnArp.put(routeEntry.nextHop(), routeEntry);
514 - //proxyArp.sendArpRequest(routeEntry.getNextHop(), this, true);
515 - // TODO maybe just do this for every prefix anyway
516 - hostService.startMonitoringIp(routeEntry.nextHop());
517 return; 514 return;
518 } 515 }
519 516
...@@ -536,11 +533,11 @@ public class Router implements RouteListener { ...@@ -536,11 +533,11 @@ public class Router implements RouteListener {
536 533
537 // Find the attachment point (egress interface) of the next hop 534 // Find the attachment point (egress interface) of the next hop
538 Interface egressInterface; 535 Interface egressInterface;
539 - if (configInfoService.getBgpPeers().containsKey(nextHopIpAddress)) { 536 + if (configService.getBgpPeers().containsKey(nextHopIpAddress)) {
540 // Route to a peer 537 // Route to a peer
541 log.debug("Route to peer {}", nextHopIpAddress); 538 log.debug("Route to peer {}", nextHopIpAddress);
542 BgpPeer peer = 539 BgpPeer peer =
543 - configInfoService.getBgpPeers().get(nextHopIpAddress); 540 + configService.getBgpPeers().get(nextHopIpAddress);
544 egressInterface = 541 egressInterface =
545 interfaceService.getInterface(peer.connectPoint()); 542 interfaceService.getInterface(peer.connectPoint());
546 } else { 543 } else {
...@@ -593,17 +590,12 @@ public class Router implements RouteListener { ...@@ -593,17 +590,12 @@ public class Router implements RouteListener {
593 } 590 }
594 591
595 // Match the destination IP prefix at the first hop 592 // Match the destination IP prefix at the first hop
596 - //PacketMatchBuilder builder = new PacketMatchBuilder();
597 - //builder.setEtherType(Ethernet.TYPE_IPV4).setDstIpNet(prefix);
598 - //PacketMatch packetMatch = builder.build();
599 TrafficSelector selector = DefaultTrafficSelector.builder() 593 TrafficSelector selector = DefaultTrafficSelector.builder()
600 .matchEthType(Ethernet.TYPE_IPV4) 594 .matchEthType(Ethernet.TYPE_IPV4)
601 .matchIPDst(prefix) 595 .matchIPDst(prefix)
602 .build(); 596 .build();
603 597
604 // Rewrite the destination MAC address 598 // Rewrite the destination MAC address
605 - //ModifyDstMacAction modifyDstMacAction =
606 - //new ModifyDstMacAction(nextHopMacAddress);
607 TrafficTreatment treatment = DefaultTrafficTreatment.builder() 599 TrafficTreatment treatment = DefaultTrafficTreatment.builder()
608 .setEthDst(nextHopMacAddress) 600 .setEthDst(nextHopMacAddress)
609 .build(); 601 .build();
...@@ -635,10 +627,6 @@ public class Router implements RouteListener { ...@@ -635,10 +627,6 @@ public class Router implements RouteListener {
635 log.debug("Processing route delete: {}", routeEntry); 627 log.debug("Processing route delete: {}", routeEntry);
636 IpPrefix prefix = routeEntry.prefix(); 628 IpPrefix prefix = routeEntry.prefix();
637 629
638 - // TODO check the change of logic here - remove doesn't check that
639 - // the route entry was what we expected (and we can't do this
640 - // concurrently)
641 -
642 if (bgpRoutes.remove(RouteEntry.createBinaryString(prefix))) { 630 if (bgpRoutes.remove(RouteEntry.createBinaryString(prefix))) {
643 // 631 //
644 // Only delete flows if an entry was actually removed from the 632 // Only delete flows if an entry was actually removed from the
...@@ -680,17 +668,19 @@ public class Router implements RouteListener { ...@@ -680,17 +668,19 @@ public class Router implements RouteListener {
680 } 668 }
681 669
682 /** 670 /**
683 - * This method handles the prefixes which are waiting for ARP replies for 671 + * Signals the Router that the MAC to IP mapping has potentially been
684 - * MAC addresses of next hops. 672 + * updated. This has the effect of updating the MAC address for any
673 + * installed prefixes if it has changed, as well as installing any pending
674 + * prefixes that were waiting for MAC resolution.
685 * 675 *
686 - * @param ipAddress next hop router IP address, for which we sent ARP 676 + * @param ipAddress the IP address that an event was received for
687 - * request out 677 + * @param macAddress the most recently known MAC address for the IP address
688 - * @param macAddress MAC address which is relative to the ipAddress
689 */ 678 */
690 - //@Override 679 + private void updateMac(IpAddress ipAddress, MacAddress macAddress) {
691 - // TODO change name 680 + log.debug("Received updated MAC info: {} => {}", ipAddress, macAddress);
692 - public void arpResponse(IpAddress ipAddress, MacAddress macAddress) { 681 +
693 - log.debug("Received ARP response: {} => {}", ipAddress, macAddress); 682 + // TODO here we should check whether the next hop for any of our
683 + // installed prefixes has changed, not just prefixes pending installation.
694 684
695 // We synchronize on this to prevent changes to the radix tree 685 // We synchronize on this to prevent changes to the radix tree
696 // while we're pushing intents. If the tree changes, the 686 // while we're pushing intents. If the tree changes, the
...@@ -708,8 +698,6 @@ public class Router implements RouteListener { ...@@ -708,8 +698,6 @@ public class Router implements RouteListener {
708 bgpRoutes.getValueForExactKey(binaryString); 698 bgpRoutes.getValueForExactKey(binaryString);
709 if (foundRouteEntry != null && 699 if (foundRouteEntry != null &&
710 foundRouteEntry.nextHop().equals(routeEntry.nextHop())) { 700 foundRouteEntry.nextHop().equals(routeEntry.nextHop())) {
711 - log.debug("Pushing prefix {} next hop {}",
712 - routeEntry.prefix(), routeEntry.nextHop());
713 // We only push prefix flows if the prefix is still in the 701 // We only push prefix flows if the prefix is still in the
714 // radix tree and the next hop is the same as our 702 // radix tree and the next hop is the same as our
715 // update. 703 // update.
...@@ -717,9 +705,8 @@ public class Router implements RouteListener { ...@@ -717,9 +705,8 @@ public class Router implements RouteListener {
717 // for the ARP, or the next hop could have changed. 705 // for the ARP, or the next hop could have changed.
718 addRouteIntentToNextHop(prefix, ipAddress, macAddress); 706 addRouteIntentToNextHop(prefix, ipAddress, macAddress);
719 } else { 707 } else {
720 - log.debug("Received ARP response, but {}/{} is no longer in" 708 + log.debug("{} has been revoked before the MAC was resolved",
721 - + " the radix tree", routeEntry.prefix(), 709 + routeEntry);
722 - routeEntry.nextHop());
723 } 710 }
724 } 711 }
725 } 712 }
...@@ -769,7 +756,7 @@ public class Router implements RouteListener { ...@@ -769,7 +756,7 @@ public class Router implements RouteListener {
769 event.type() == HostEvent.Type.HOST_UPDATED) { 756 event.type() == HostEvent.Type.HOST_UPDATED) {
770 Host host = event.subject(); 757 Host host = event.subject();
771 for (IpPrefix ip : host.ipAddresses()) { 758 for (IpPrefix ip : host.ipAddresses()) {
772 - arpResponse(ip.toIpAddress(), host.mac()); 759 + updateMac(ip.toIpAddress(), host.mac());
773 } 760 }
774 } 761 }
775 } 762 }
......
...@@ -26,7 +26,7 @@ import org.slf4j.Logger; ...@@ -26,7 +26,7 @@ import org.slf4j.Logger;
26 @Service 26 @Service
27 public class SdnIp implements SdnIpService { 27 public class SdnIp implements SdnIpService {
28 28
29 - private static final String SDN_ID_APP = "org.onlab.onos.sdnip"; 29 + private static final String SDN_IP_APP = "org.onlab.onos.sdnip";
30 30
31 private final Logger log = getLogger(getClass()); 31 private final Logger log = getLogger(getClass());
32 32
...@@ -53,8 +53,10 @@ public class SdnIp implements SdnIpService { ...@@ -53,8 +53,10 @@ public class SdnIp implements SdnIpService {
53 53
54 InterfaceService interfaceService = new HostToInterfaceAdaptor(hostService); 54 InterfaceService interfaceService = new HostToInterfaceAdaptor(hostService);
55 55
56 - ApplicationId appId = coreService.registerApplication(SDN_ID_APP); 56 + ApplicationId appId = coreService.registerApplication(SDN_IP_APP);
57 - peerConnectivity = new PeerConnectivityManager(appId, config, interfaceService, intentService); 57 +
58 + peerConnectivity = new PeerConnectivityManager(appId, config,
59 + interfaceService, intentService);
58 peerConnectivity.start(); 60 peerConnectivity.start();
59 61
60 router = new Router(appId, intentService, hostService, config, interfaceService); 62 router = new Router(appId, intentService, hostService, config, interfaceService);
......
1 package org.onlab.onos.sdnip; 1 package org.onlab.onos.sdnip;
2 2
3 +import static org.easymock.EasyMock.anyObject;
3 import static org.easymock.EasyMock.createMock; 4 import static org.easymock.EasyMock.createMock;
4 import static org.easymock.EasyMock.expect; 5 import static org.easymock.EasyMock.expect;
6 +import static org.easymock.EasyMock.expectLastCall;
5 import static org.easymock.EasyMock.replay; 7 import static org.easymock.EasyMock.replay;
6 import static org.easymock.EasyMock.reset; 8 import static org.easymock.EasyMock.reset;
7 import static org.easymock.EasyMock.verify; 9 import static org.easymock.EasyMock.verify;
...@@ -15,6 +17,8 @@ import java.util.Set; ...@@ -15,6 +17,8 @@ import java.util.Set;
15 17
16 import org.junit.Before; 18 import org.junit.Before;
17 import org.junit.Test; 19 import org.junit.Test;
20 +import org.onlab.junit.TestUtils;
21 +import org.onlab.junit.TestUtils.TestUtilsException;
18 import org.onlab.onos.ApplicationId; 22 import org.onlab.onos.ApplicationId;
19 import org.onlab.onos.net.ConnectPoint; 23 import org.onlab.onos.net.ConnectPoint;
20 import org.onlab.onos.net.DefaultHost; 24 import org.onlab.onos.net.DefaultHost;
...@@ -27,6 +31,7 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector; ...@@ -27,6 +31,7 @@ import org.onlab.onos.net.flow.DefaultTrafficSelector;
27 import org.onlab.onos.net.flow.DefaultTrafficTreatment; 31 import org.onlab.onos.net.flow.DefaultTrafficTreatment;
28 import org.onlab.onos.net.flow.TrafficSelector; 32 import org.onlab.onos.net.flow.TrafficSelector;
29 import org.onlab.onos.net.flow.TrafficTreatment; 33 import org.onlab.onos.net.flow.TrafficTreatment;
34 +import org.onlab.onos.net.host.HostListener;
30 import org.onlab.onos.net.host.HostService; 35 import org.onlab.onos.net.host.HostService;
31 import org.onlab.onos.net.intent.IntentService; 36 import org.onlab.onos.net.intent.IntentService;
32 import org.onlab.onos.net.intent.MultiPointToSinglePointIntent; 37 import org.onlab.onos.net.intent.MultiPointToSinglePointIntent;
...@@ -39,8 +44,6 @@ import org.onlab.packet.IpAddress; ...@@ -39,8 +44,6 @@ import org.onlab.packet.IpAddress;
39 import org.onlab.packet.IpPrefix; 44 import org.onlab.packet.IpPrefix;
40 import org.onlab.packet.MacAddress; 45 import org.onlab.packet.MacAddress;
41 import org.onlab.packet.VlanId; 46 import org.onlab.packet.VlanId;
42 -import org.onlab.util.TestUtils;
43 -import org.onlab.util.TestUtils.TestUtilsException;
44 47
45 import com.google.common.collect.Sets; 48 import com.google.common.collect.Sets;
46 49
...@@ -55,10 +58,17 @@ public class RouterTest { ...@@ -55,10 +58,17 @@ public class RouterTest {
55 private IntentService intentService; 58 private IntentService intentService;
56 private HostService hostService; 59 private HostService hostService;
57 60
58 - private Map<IpAddress, BgpPeer> bgpPeers; 61 + private static final ConnectPoint SW1_ETH1 = new ConnectPoint(
59 - private Map<IpAddress, BgpPeer> configuredPeers; 62 + DeviceId.deviceId("of:0000000000000001"),
60 - private Set<Interface> interfaces; 63 + PortNumber.portNumber(1));
61 - private Set<Interface> configuredInterfaces; 64 +
65 + private static final ConnectPoint SW2_ETH1 = new ConnectPoint(
66 + DeviceId.deviceId("of:0000000000000002"),
67 + PortNumber.portNumber(1));
68 +
69 + private static final ConnectPoint SW3_ETH1 = new ConnectPoint(
70 + DeviceId.deviceId("of:0000000000000003"),
71 + PortNumber.portNumber(1));
62 72
63 private static final ApplicationId APPID = new ApplicationId() { 73 private static final ApplicationId APPID = new ApplicationId() {
64 @Override 74 @Override
...@@ -76,55 +86,12 @@ public class RouterTest { ...@@ -76,55 +86,12 @@ public class RouterTest {
76 86
77 @Before 87 @Before
78 public void setUp() throws Exception { 88 public void setUp() throws Exception {
79 - bgpPeers = setUpBgpPeers(); 89 + setUpBgpPeers();
80 - interfaces = setUpInterfaces();
81 - initRouter();
82 - }
83 90
84 - /** 91 + setUpInterfaceService();
85 - * Initializes Router class. 92 + setUpHostService();
86 - */
87 - private void initRouter() {
88 93
89 intentService = createMock(IntentService.class); 94 intentService = createMock(IntentService.class);
90 - hostService = createMock(HostService.class);
91 -
92 - interfaceService = createMock(InterfaceService.class);
93 - expect(interfaceService.getInterfaces()).andReturn(
94 - interfaces).anyTimes();
95 -
96 - Set<IpPrefix> ipAddressesOnSw1Eth1 = new HashSet<IpPrefix>();
97 - ipAddressesOnSw1Eth1.add(IpPrefix.valueOf("192.168.10.0/24"));
98 - Interface expectedInterface =
99 - new Interface(new ConnectPoint(
100 - DeviceId.deviceId("of:0000000000000001"),
101 - PortNumber.portNumber("1")),
102 - ipAddressesOnSw1Eth1,
103 - MacAddress.valueOf("00:00:00:00:00:01"));
104 - ConnectPoint egressPoint = new ConnectPoint(
105 - DeviceId.deviceId("of:0000000000000001"),
106 - PortNumber.portNumber(1));
107 - expect(interfaceService.getInterface(egressPoint)).andReturn(
108 - expectedInterface).anyTimes();
109 -
110 - Set<IpPrefix> ipAddressesOnSw2Eth1 = new HashSet<IpPrefix>();
111 - ipAddressesOnSw2Eth1.add(IpPrefix.valueOf("192.168.20.0/24"));
112 - Interface expectedInterfaceNew =
113 - new Interface(new ConnectPoint(
114 - DeviceId.deviceId("of:0000000000000002"),
115 - PortNumber.portNumber("1")),
116 - ipAddressesOnSw2Eth1,
117 - MacAddress.valueOf("00:00:00:00:00:02"));
118 - ConnectPoint egressPointNew = new ConnectPoint(
119 - DeviceId.deviceId("of:0000000000000002"),
120 - PortNumber.portNumber(1));
121 - expect(interfaceService.getInterface(egressPointNew)).andReturn(
122 - expectedInterfaceNew).anyTimes();
123 - replay(interfaceService);
124 -
125 - sdnIpConfigService = createMock(SdnIpConfigService.class);
126 - expect(sdnIpConfigService.getBgpPeers()).andReturn(bgpPeers).anyTimes();
127 - replay(sdnIpConfigService);
128 95
129 router = new Router(APPID, intentService, 96 router = new Router(APPID, intentService,
130 hostService, sdnIpConfigService, interfaceService); 97 hostService, sdnIpConfigService, interfaceService);
...@@ -132,67 +99,99 @@ public class RouterTest { ...@@ -132,67 +99,99 @@ public class RouterTest {
132 99
133 /** 100 /**
134 * Sets up BGP peers in external networks. 101 * Sets up BGP peers in external networks.
135 - *
136 - * @return configured BGP peers as a Map from peer IP address to BgpPeer
137 */ 102 */
138 - private Map<IpAddress, BgpPeer> setUpBgpPeers() { 103 + private void setUpBgpPeers() {
139 104
140 - configuredPeers = new HashMap<>(); 105 + Map<IpAddress, BgpPeer> peers = new HashMap<>();
141 106
142 String peerSw1Eth1 = "192.168.10.1"; 107 String peerSw1Eth1 = "192.168.10.1";
143 - configuredPeers.put(IpAddress.valueOf(peerSw1Eth1), 108 + peers.put(IpAddress.valueOf(peerSw1Eth1),
144 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1)); 109 new BgpPeer("00:00:00:00:00:00:00:01", 1, peerSw1Eth1));
145 110
146 // Two BGP peers are connected to switch 2 port 1. 111 // Two BGP peers are connected to switch 2 port 1.
147 String peer1Sw2Eth1 = "192.168.20.1"; 112 String peer1Sw2Eth1 = "192.168.20.1";
148 - configuredPeers.put(IpAddress.valueOf(peer1Sw2Eth1), 113 + peers.put(IpAddress.valueOf(peer1Sw2Eth1),
149 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1)); 114 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer1Sw2Eth1));
150 115
151 String peer2Sw2Eth1 = "192.168.20.2"; 116 String peer2Sw2Eth1 = "192.168.20.2";
152 - configuredPeers.put(IpAddress.valueOf(peer2Sw2Eth1), 117 + peers.put(IpAddress.valueOf(peer2Sw2Eth1),
153 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1)); 118 new BgpPeer("00:00:00:00:00:00:00:02", 1, peer2Sw2Eth1));
154 119
155 - return configuredPeers; 120 + sdnIpConfigService = createMock(SdnIpConfigService.class);
121 + expect(sdnIpConfigService.getBgpPeers()).andReturn(peers).anyTimes();
122 + replay(sdnIpConfigService);
123 +
156 } 124 }
157 125
158 /** 126 /**
159 * Sets up logical interfaces, which emulate the configured interfaces 127 * Sets up logical interfaces, which emulate the configured interfaces
160 * in SDN-IP application. 128 * in SDN-IP application.
161 - *
162 - * @return configured interfaces as a Set
163 */ 129 */
164 - private Set<Interface> setUpInterfaces() { 130 + private void setUpInterfaceService() {
165 - 131 + interfaceService = createMock(InterfaceService.class);
166 - configuredInterfaces = Sets.newHashSet(); 132 +
167 - 133 + Set<Interface> interfaces = Sets.newHashSet();
168 - Set<IpPrefix> ipAddressesOnSw1Eth1 = new HashSet<IpPrefix>(); 134 +
169 - ipAddressesOnSw1Eth1.add(IpPrefix.valueOf("192.168.10.0/24")); 135 + Interface sw1Eth1 = new Interface(SW1_ETH1,
170 - configuredInterfaces.add( 136 + Sets.newHashSet(IpPrefix.valueOf("192.168.10.101/24")),
171 - new Interface(new ConnectPoint( 137 + MacAddress.valueOf("00:00:00:00:00:01"));
172 - DeviceId.deviceId("of:0000000000000001"), 138 +
173 - PortNumber.portNumber(1)), 139 + expect(interfaceService.getInterface(SW1_ETH1)).andReturn(sw1Eth1).anyTimes();
174 - ipAddressesOnSw1Eth1, 140 + interfaces.add(sw1Eth1);
175 - MacAddress.valueOf("00:00:00:00:00:01"))); 141 +
176 - 142 + Interface sw2Eth1 = new Interface(SW2_ETH1,
177 - Set<IpPrefix> ipAddressesOnSw2Eth1 = new HashSet<IpPrefix>(); 143 + Sets.newHashSet(IpPrefix.valueOf("192.168.20.101/24")),
178 - ipAddressesOnSw2Eth1.add(IpPrefix.valueOf("192.168.20.0/24")); 144 + MacAddress.valueOf("00:00:00:00:00:02"));
179 - configuredInterfaces.add( 145 +
180 - new Interface(new ConnectPoint( 146 + expect(interfaceService.getInterface(SW2_ETH1)).andReturn(sw2Eth1).anyTimes();
181 - DeviceId.deviceId("of:0000000000000002"), 147 + interfaces.add(sw2Eth1);
182 - PortNumber.portNumber(1)), 148 +
183 - ipAddressesOnSw2Eth1, 149 + Interface sw3Eth1 = new Interface(SW3_ETH1,
184 - MacAddress.valueOf("00:00:00:00:00:02"))); 150 + Sets.newHashSet(IpPrefix.valueOf("192.168.30.101/24")),
185 - 151 + MacAddress.valueOf("00:00:00:00:00:03"));
186 - Set<IpPrefix> ipAddressesOnSw3Eth1 = new HashSet<IpPrefix>(); 152 +
187 - ipAddressesOnSw3Eth1.add(IpPrefix.valueOf("192.168.30.0/24")); 153 + expect(interfaceService.getInterface(SW3_ETH1)).andReturn(sw3Eth1).anyTimes();
188 - configuredInterfaces.add( 154 + interfaces.add(sw3Eth1);
189 - new Interface(new ConnectPoint( 155 +
190 - DeviceId.deviceId("of:0000000000000003"), 156 + expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
191 - PortNumber.portNumber(1)), 157 +
192 - ipAddressesOnSw3Eth1, 158 + replay(interfaceService);
193 - MacAddress.valueOf("00:00:00:00:00:03"))); 159 + }
194 - 160 +
195 - return configuredInterfaces; 161 + /**
162 + * Sets up the host service with details of some hosts.
163 + */
164 + private void setUpHostService() {
165 + hostService = createMock(HostService.class);
166 +
167 + hostService.addListener(anyObject(HostListener.class));
168 + expectLastCall().anyTimes();
169 +
170 + IpPrefix host1Address = IpPrefix.valueOf("192.168.10.1/32");
171 + Host host1 = new DefaultHost(ProviderId.NONE, HostId.NONE,
172 + MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
173 + new HostLocation(SW1_ETH1, 1),
174 + Sets.newHashSet(host1Address));
175 +
176 + expect(hostService.getHostsByIp(host1Address))
177 + .andReturn(Sets.newHashSet(host1)).anyTimes();
178 + hostService.startMonitoringIp(host1Address.toIpAddress());
179 + expectLastCall().anyTimes();
180 +
181 +
182 + IpPrefix host2Address = IpPrefix.valueOf("192.168.20.1/32");
183 + Host host2 = new DefaultHost(ProviderId.NONE, HostId.NONE,
184 + MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
185 + new HostLocation(SW2_ETH1, 1),
186 + Sets.newHashSet(host2Address));
187 +
188 + expect(hostService.getHostsByIp(host2Address))
189 + .andReturn(Sets.newHashSet(host2)).anyTimes();
190 + hostService.startMonitoringIp(host2Address.toIpAddress());
191 + expectLastCall().anyTimes();
192 +
193 +
194 + replay(hostService);
196 } 195 }
197 196
198 /** 197 /**
...@@ -200,7 +199,6 @@ public class RouterTest { ...@@ -200,7 +199,6 @@ public class RouterTest {
200 */ 199 */
201 @Test 200 @Test
202 public void testProcessRouteAdd() throws TestUtilsException { 201 public void testProcessRouteAdd() throws TestUtilsException {
203 -
204 // Construct a route entry 202 // Construct a route entry
205 RouteEntry routeEntry = new RouteEntry( 203 RouteEntry routeEntry = new RouteEntry(
206 IpPrefix.valueOf("1.1.1.0/24"), 204 IpPrefix.valueOf("1.1.1.0/24"),
...@@ -217,36 +215,13 @@ public class RouterTest { ...@@ -217,36 +215,13 @@ public class RouterTest {
217 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01")); 215 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
218 216
219 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>(); 217 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
220 - ingressPoints.add(new ConnectPoint( 218 + ingressPoints.add(SW2_ETH1);
221 - DeviceId.deviceId("of:0000000000000002"), 219 + ingressPoints.add(SW3_ETH1);
222 - PortNumber.portNumber("1")));
223 - ingressPoints.add(new ConnectPoint(
224 - DeviceId.deviceId("of:0000000000000003"),
225 - PortNumber.portNumber("1")));
226 -
227 - ConnectPoint egressPoint = new ConnectPoint(
228 - DeviceId.deviceId("of:0000000000000001"),
229 - PortNumber.portNumber("1"));
230 220
231 MultiPointToSinglePointIntent intent = 221 MultiPointToSinglePointIntent intent =
232 new MultiPointToSinglePointIntent(APPID, 222 new MultiPointToSinglePointIntent(APPID,
233 selectorBuilder.build(), treatmentBuilder.build(), 223 selectorBuilder.build(), treatmentBuilder.build(),
234 - ingressPoints, egressPoint); 224 + ingressPoints, SW1_ETH1);
235 -
236 - // Reset host service
237 - reset(hostService);
238 - Set<Host> hosts = new HashSet<Host>(1);
239 - Set<IpPrefix> ipPrefixes = new HashSet<IpPrefix>();
240 - ipPrefixes.add(IpPrefix.valueOf("192.168.10.1/32"));
241 - hosts.add(new DefaultHost(ProviderId.NONE, HostId.NONE,
242 - MacAddress.valueOf("00:00:00:00:00:01"), VlanId.NONE,
243 - new HostLocation(
244 - DeviceId.deviceId("of:0000000000000001"),
245 - PortNumber.portNumber(1), 1),
246 - ipPrefixes));
247 - expect(hostService.getHostsByIp(
248 - IpPrefix.valueOf("192.168.10.1/32"))).andReturn(hosts);
249 - replay(hostService);
250 225
251 // Set up test expectation 226 // Set up test expectation
252 reset(intentService); 227 reset(intentService);
...@@ -274,7 +249,6 @@ public class RouterTest { ...@@ -274,7 +249,6 @@ public class RouterTest {
274 */ 249 */
275 @Test 250 @Test
276 public void testRouteUpdate() throws TestUtilsException { 251 public void testRouteUpdate() throws TestUtilsException {
277 -
278 // Firstly add a route 252 // Firstly add a route
279 testProcessRouteAdd(); 253 testProcessRouteAdd();
280 254
...@@ -293,22 +267,14 @@ public class RouterTest { ...@@ -293,22 +267,14 @@ public class RouterTest {
293 DefaultTrafficTreatment.builder(); 267 DefaultTrafficTreatment.builder();
294 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01")); 268 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
295 269
296 - ConnectPoint egressPoint = new ConnectPoint(
297 - DeviceId.deviceId("of:0000000000000001"),
298 - PortNumber.portNumber("1"));
299 -
300 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>(); 270 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
301 - ingressPoints.add(new ConnectPoint( 271 + ingressPoints.add(SW2_ETH1);
302 - DeviceId.deviceId("of:0000000000000002"), 272 + ingressPoints.add(SW3_ETH1);
303 - PortNumber.portNumber("1")));
304 - ingressPoints.add(new ConnectPoint(
305 - DeviceId.deviceId("of:0000000000000003"),
306 - PortNumber.portNumber("1")));
307 273
308 MultiPointToSinglePointIntent intent = 274 MultiPointToSinglePointIntent intent =
309 new MultiPointToSinglePointIntent(APPID, 275 new MultiPointToSinglePointIntent(APPID,
310 selectorBuilder.build(), treatmentBuilder.build(), 276 selectorBuilder.build(), treatmentBuilder.build(),
311 - ingressPoints, egressPoint); 277 + ingressPoints, SW1_ETH1);
312 278
313 // Start to construct a new route entry and new intent 279 // Start to construct a new route entry and new intent
314 RouteEntry routeEntryUpdate = new RouteEntry( 280 RouteEntry routeEntryUpdate = new RouteEntry(
...@@ -325,38 +291,16 @@ public class RouterTest { ...@@ -325,38 +291,16 @@ public class RouterTest {
325 DefaultTrafficTreatment.builder(); 291 DefaultTrafficTreatment.builder();
326 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02")); 292 treatmentBuilderNew.setEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
327 293
328 - ConnectPoint egressPointNew = new ConnectPoint(
329 - DeviceId.deviceId("of:0000000000000002"),
330 - PortNumber.portNumber("1"));
331 294
332 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>(); 295 Set<ConnectPoint> ingressPointsNew = new HashSet<ConnectPoint>();
333 - ingressPointsNew.add(new ConnectPoint( 296 + ingressPointsNew.add(SW1_ETH1);
334 - DeviceId.deviceId("of:0000000000000001"), 297 + ingressPointsNew.add(SW3_ETH1);
335 - PortNumber.portNumber("1")));
336 - ingressPointsNew.add(new ConnectPoint(
337 - DeviceId.deviceId("of:0000000000000003"),
338 - PortNumber.portNumber("1")));
339 298
340 MultiPointToSinglePointIntent intentNew = 299 MultiPointToSinglePointIntent intentNew =
341 new MultiPointToSinglePointIntent(APPID, 300 new MultiPointToSinglePointIntent(APPID,
342 selectorBuilderNew.build(), 301 selectorBuilderNew.build(),
343 treatmentBuilderNew.build(), 302 treatmentBuilderNew.build(),
344 - ingressPointsNew, egressPointNew); 303 + ingressPointsNew, SW2_ETH1);
345 -
346 - // Reset host service
347 - reset(hostService);
348 - Set<Host> hosts = new HashSet<Host>(1);
349 - Set<IpPrefix> ipPrefixes = new HashSet<IpPrefix>();
350 - ipPrefixes.add(IpPrefix.valueOf("192.168.20.1/32"));
351 - hosts.add(new DefaultHost(ProviderId.NONE, HostId.NONE,
352 - MacAddress.valueOf("00:00:00:00:00:02"), VlanId.NONE,
353 - new HostLocation(
354 - DeviceId.deviceId("of:0000000000000002"),
355 - PortNumber.portNumber(1), 1),
356 - ipPrefixes));
357 - expect(hostService.getHostsByIp(
358 - IpPrefix.valueOf("192.168.20.1/32"))).andReturn(hosts);
359 - replay(hostService);
360 304
361 // Set up test expectation 305 // Set up test expectation
362 reset(intentService); 306 reset(intentService);
...@@ -383,7 +327,6 @@ public class RouterTest { ...@@ -383,7 +327,6 @@ public class RouterTest {
383 */ 327 */
384 @Test 328 @Test
385 public void testProcessRouteDelete() throws TestUtilsException { 329 public void testProcessRouteDelete() throws TestUtilsException {
386 -
387 // Firstly add a route 330 // Firstly add a route
388 testProcessRouteAdd(); 331 testProcessRouteAdd();
389 332
...@@ -402,22 +345,14 @@ public class RouterTest { ...@@ -402,22 +345,14 @@ public class RouterTest {
402 DefaultTrafficTreatment.builder(); 345 DefaultTrafficTreatment.builder();
403 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01")); 346 treatmentBuilder.setEthDst(MacAddress.valueOf("00:00:00:00:00:01"));
404 347
405 - ConnectPoint egressPoint = new ConnectPoint(
406 - DeviceId.deviceId("of:0000000000000001"),
407 - PortNumber.portNumber("1"));
408 -
409 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>(); 348 Set<ConnectPoint> ingressPoints = new HashSet<ConnectPoint>();
410 - ingressPoints.add(new ConnectPoint( 349 + ingressPoints.add(SW2_ETH1);
411 - DeviceId.deviceId("of:0000000000000002"), 350 + ingressPoints.add(SW3_ETH1);
412 - PortNumber.portNumber("1")));
413 - ingressPoints.add(new ConnectPoint(
414 - DeviceId.deviceId("of:0000000000000003"),
415 - PortNumber.portNumber("1")));
416 351
417 MultiPointToSinglePointIntent intent = 352 MultiPointToSinglePointIntent intent =
418 new MultiPointToSinglePointIntent(APPID, 353 new MultiPointToSinglePointIntent(APPID,
419 selectorBuilder.build(), treatmentBuilder.build(), 354 selectorBuilder.build(), treatmentBuilder.build(),
420 - ingressPoints, egressPoint); 355 + ingressPoints, SW1_ETH1);
421 356
422 // Set up expectation 357 // Set up expectation
423 reset(intentService); 358 reset(intentService);
...@@ -442,7 +377,6 @@ public class RouterTest { ...@@ -442,7 +377,6 @@ public class RouterTest {
442 */ 377 */
443 @Test 378 @Test
444 public void testLocalRouteAdd() throws TestUtilsException { 379 public void testLocalRouteAdd() throws TestUtilsException {
445 -
446 // Construct a route entry, the next hop is the local BGP speaker 380 // Construct a route entry, the next hop is the local BGP speaker
447 RouteEntry routeEntry = new RouteEntry( 381 RouteEntry routeEntry = new RouteEntry(
448 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0")); 382 IpPrefix.valueOf("1.1.1.0/24"), IpAddress.valueOf("0.0.0.0"));
......
...@@ -26,12 +26,12 @@ import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory; ...@@ -26,12 +26,12 @@ import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
26 import org.junit.After; 26 import org.junit.After;
27 import org.junit.Before; 27 import org.junit.Before;
28 import org.junit.Test; 28 import org.junit.Test;
29 +import org.onlab.junit.TestUtils;
30 +import org.onlab.junit.TestUtils.TestUtilsException;
29 import org.onlab.onos.sdnip.RouteListener; 31 import org.onlab.onos.sdnip.RouteListener;
30 import org.onlab.onos.sdnip.RouteUpdate; 32 import org.onlab.onos.sdnip.RouteUpdate;
31 import org.onlab.packet.IpAddress; 33 import org.onlab.packet.IpAddress;
32 import org.onlab.packet.IpPrefix; 34 import org.onlab.packet.IpPrefix;
33 -import org.onlab.util.TestUtils;
34 -import org.onlab.util.TestUtils.TestUtilsException;
35 35
36 import com.google.common.net.InetAddresses; 36 import com.google.common.net.InetAddresses;
37 37
......
...@@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.is; ...@@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.is;
6 import static org.hamcrest.Matchers.not; 6 import static org.hamcrest.Matchers.not;
7 import static org.junit.Assert.assertEquals; 7 import static org.junit.Assert.assertEquals;
8 import static org.junit.Assert.assertThat; 8 import static org.junit.Assert.assertThat;
9 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
9 10
10 /** 11 /**
11 * This class tests the immutability, equality, and non-equality of 12 * This class tests the immutability, equality, and non-equality of
...@@ -17,7 +18,7 @@ public class IntentIdTest { ...@@ -17,7 +18,7 @@ public class IntentIdTest {
17 */ 18 */
18 @Test 19 @Test
19 public void intentIdFollowsGuidelineForImmutableObject() { 20 public void intentIdFollowsGuidelineForImmutableObject() {
20 - ImmutableClassChecker.assertThatClassIsImmutable(IntentId.class); 21 + assertThatClassIsImmutable(IntentId.class);
21 } 22 }
22 23
23 /** 24 /**
......
...@@ -11,6 +11,7 @@ import static org.hamcrest.MatcherAssert.assertThat; ...@@ -11,6 +11,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
11 import static org.hamcrest.Matchers.equalTo; 11 import static org.hamcrest.Matchers.equalTo;
12 import static org.hamcrest.Matchers.is; 12 import static org.hamcrest.Matchers.is;
13 import static org.hamcrest.Matchers.not; 13 import static org.hamcrest.Matchers.not;
14 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
14 import static org.onlab.onos.net.NetTestTools.hid; 15 import static org.onlab.onos.net.NetTestTools.hid;
15 16
16 /** 17 /**
...@@ -104,6 +105,6 @@ public class TestHostToHostIntent { ...@@ -104,6 +105,6 @@ public class TestHostToHostIntent {
104 */ 105 */
105 @Test 106 @Test
106 public void checkImmutability() { 107 public void checkImmutability() {
107 - ImmutableClassChecker.assertThatClassIsImmutable(HostToHostIntent.class); 108 + assertThatClassIsImmutable(HostToHostIntent.class);
108 } 109 }
109 } 110 }
......
...@@ -4,6 +4,7 @@ import static org.hamcrest.CoreMatchers.not; ...@@ -4,6 +4,7 @@ import static org.hamcrest.CoreMatchers.not;
4 import static org.hamcrest.MatcherAssert.assertThat; 4 import static org.hamcrest.MatcherAssert.assertThat;
5 import static org.hamcrest.Matchers.equalTo; 5 import static org.hamcrest.Matchers.equalTo;
6 import static org.hamcrest.Matchers.is; 6 import static org.hamcrest.Matchers.is;
7 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
7 import static org.onlab.onos.net.NetTestTools.link; 8 import static org.onlab.onos.net.NetTestTools.link;
8 9
9 import java.util.HashSet; 10 import java.util.HashSet;
...@@ -154,6 +155,6 @@ public class TestLinkCollectionIntent { ...@@ -154,6 +155,6 @@ public class TestLinkCollectionIntent {
154 */ 155 */
155 @Test 156 @Test
156 public void checkImmutability() { 157 public void checkImmutability() {
157 - ImmutableClassChecker.assertThatClassIsImmutable(LinkCollectionIntent.class); 158 + assertThatClassIsImmutable(LinkCollectionIntent.class);
158 } 159 }
159 } 160 }
......
...@@ -15,6 +15,7 @@ import static org.hamcrest.CoreMatchers.not; ...@@ -15,6 +15,7 @@ import static org.hamcrest.CoreMatchers.not;
15 import static org.hamcrest.MatcherAssert.assertThat; 15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.equalTo; 16 import static org.hamcrest.Matchers.equalTo;
17 import static org.hamcrest.Matchers.is; 17 import static org.hamcrest.Matchers.is;
18 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
18 import static org.onlab.onos.net.NetTestTools.connectPoint; 19 import static org.onlab.onos.net.NetTestTools.connectPoint;
19 20
20 /** 21 /**
...@@ -135,7 +136,6 @@ public class TestMultiPointToSinglePointIntent { ...@@ -135,7 +136,6 @@ public class TestMultiPointToSinglePointIntent {
135 */ 136 */
136 @Test 137 @Test
137 public void checkImmutability() { 138 public void checkImmutability() {
138 - ImmutableClassChecker. 139 + assertThatClassIsImmutable(MultiPointToSinglePointIntent.class);
139 - assertThatClassIsImmutable(MultiPointToSinglePointIntent.class);
140 } 140 }
141 } 141 }
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
35 <dependency> 35 <dependency>
36 <groupId>org.onlab.onos</groupId> 36 <groupId>org.onlab.onos</groupId>
37 <artifactId>onlab-junit</artifactId> 37 <artifactId>onlab-junit</artifactId>
38 + <scope>test</scope>
38 </dependency> 39 </dependency>
39 </dependencies> 40 </dependencies>
40 41
......
...@@ -11,6 +11,7 @@ import java.util.Arrays; ...@@ -11,6 +11,7 @@ import java.util.Arrays;
11 import java.util.Collection; 11 import java.util.Collection;
12 import java.util.Collections; 12 import java.util.Collections;
13 import java.util.Map; 13 import java.util.Map;
14 +import java.util.Set;
14 import java.util.concurrent.ExecutorService; 15 import java.util.concurrent.ExecutorService;
15 import java.util.concurrent.Executors; 16 import java.util.concurrent.Executors;
16 import java.util.concurrent.Future; 17 import java.util.concurrent.Future;
...@@ -159,6 +160,21 @@ public class DistributedFlowRuleStore ...@@ -159,6 +160,21 @@ public class DistributedFlowRuleStore
159 } 160 }
160 }); 161 });
161 162
163 + clusterCommunicator.addSubscriber(GET_DEVICE_FLOW_ENTRIES, new ClusterMessageHandler() {
164 +
165 + @Override
166 + public void handle(ClusterMessage message) {
167 + DeviceId deviceId = SERIALIZER.decode(message.payload());
168 + log.info("Received get flow entries request for {} from {}", deviceId, message.sender());
169 + Set<FlowEntry> flowEntries = getFlowEntriesInternal(deviceId);
170 + try {
171 + message.respond(SERIALIZER.encode(flowEntries));
172 + } catch (IOException e) {
173 + log.error("Failed to respond to peer's getFlowEntries request", e);
174 + }
175 + }
176 + });
177 +
162 log.info("Started"); 178 log.info("Started");
163 } 179 }
164 180
...@@ -217,9 +233,33 @@ public class DistributedFlowRuleStore ...@@ -217,9 +233,33 @@ public class DistributedFlowRuleStore
217 233
218 @Override 234 @Override
219 public synchronized Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) { 235 public synchronized Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
236 +
237 + ReplicaInfo replicaInfo = replicaInfoManager.getReplicaInfoFor(deviceId);
238 + if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
239 + return getFlowEntriesInternal(deviceId);
240 + }
241 +
242 + log.info("Forwarding getFlowEntries to {}, which is the primary (master) for device {}",
243 + replicaInfo.master().orNull(), deviceId);
244 +
245 + ClusterMessage message = new ClusterMessage(
246 + clusterService.getLocalNode().id(),
247 + GET_DEVICE_FLOW_ENTRIES,
248 + SERIALIZER.encode(deviceId));
249 +
250 + try {
251 + ClusterMessageResponse response = clusterCommunicator.sendAndReceive(message, replicaInfo.master().get());
252 + return SERIALIZER.decode(response.get(FLOW_RULE_STORE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS));
253 + } catch (IOException | TimeoutException e) {
254 + // FIXME: throw a FlowStoreException
255 + throw new RuntimeException(e);
256 + }
257 + }
258 +
259 + private Set<FlowEntry> getFlowEntriesInternal(DeviceId deviceId) {
220 Collection<? extends FlowEntry> rules = flowEntries.get(deviceId); 260 Collection<? extends FlowEntry> rules = flowEntries.get(deviceId);
221 if (rules == null) { 261 if (rules == null) {
222 - return Collections.emptyList(); 262 + return Collections.emptySet();
223 } 263 }
224 return ImmutableSet.copyOf(rules); 264 return ImmutableSet.copyOf(rules);
225 } 265 }
......
...@@ -13,4 +13,7 @@ public final class FlowStoreMessageSubjects { ...@@ -13,4 +13,7 @@ public final class FlowStoreMessageSubjects {
13 13
14 public static final MessageSubject GET_FLOW_ENTRY 14 public static final MessageSubject GET_FLOW_ENTRY
15 = new MessageSubject("peer-forward-get-flow-entry"); 15 = new MessageSubject("peer-forward-get-flow-entry");
16 +
17 + public static final MessageSubject GET_DEVICE_FLOW_ENTRIES
18 + = new MessageSubject("peer-forward-get-device-flow-entries");
16 } 19 }
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
34 <version>2.10.1</version> 34 <version>2.10.1</version>
35 <configuration> 35 <configuration>
36 <show>package</show> 36 <show>package</show>
37 - <excludePackageNames>org.onlab.thirdparty:*.impl:*.impl.*:org.onlab.onos.provider.*:org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli*:org.onlab.onos.tvue:org.onlab.onos.foo:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.optical:org.onlab.onos.config:org.onlab.onos.calendar:org.onlab.onos.sdnip*:org.onlab.onos.metrics</excludePackageNames> 37 + <excludePackageNames>org.onlab.thirdparty:*.impl:*.impl.*:org.onlab.onos.provider.*:org.onlab.onos.gui:org.onlab.onos.rest:org.onlab.onos.cli*:org.onlab.onos.tvue:org.onlab.onos.foo:org.onlab.onos.mobility:org.onlab.onos.proxyarp:org.onlab.onos.fwd:org.onlab.onos.ifwd:org.onlab.onos.optical:org.onlab.onos.config:org.onlab.onos.calendar:org.onlab.onos.sdnip*:org.onlab.onos.metrics:org.onlab.onos.store.*:org.onlab.onos.openflow.*</excludePackageNames>
38 <docfilessubdirs>true</docfilessubdirs> 38 <docfilessubdirs>true</docfilessubdirs>
39 <doctitle>ONOS Java API</doctitle> 39 <doctitle>ONOS Java API</doctitle>
40 <groups> 40 <groups>
......
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
248 <dependency> 248 <dependency>
249 <groupId>org.onlab.onos</groupId> 249 <groupId>org.onlab.onos</groupId>
250 <artifactId>onlab-junit</artifactId> 250 <artifactId>onlab-junit</artifactId>
251 - <version>1.0.0-SNAPSHOT</version> 251 + <version>${project.version}</version>
252 <scope>test</scope> 252 <scope>test</scope>
253 </dependency> 253 </dependency>
254 254
......
...@@ -27,6 +27,16 @@ ...@@ -27,6 +27,16 @@
27 <artifactId>guava-testlib</artifactId> 27 <artifactId>guava-testlib</artifactId>
28 <scope>compile</scope> 28 <scope>compile</scope>
29 </dependency> 29 </dependency>
30 + <dependency>
31 + <groupId>org.hamcrest</groupId>
32 + <artifactId>hamcrest-core</artifactId>
33 + <scope>compile</scope>
34 + </dependency>
35 + <dependency>
36 + <groupId>org.hamcrest</groupId>
37 + <artifactId>hamcrest-library</artifactId>
38 + <scope>compile</scope>
39 + </dependency>
30 </dependencies> 40 </dependencies>
31 41
32 </project> 42 </project>
......
1 -package org.onlab.onos.net.intent; 1 +package org.onlab.junit;
2 -//TODO is this the right package?
3 2
4 import org.hamcrest.Description; 3 import org.hamcrest.Description;
5 import org.hamcrest.StringDescription; 4 import org.hamcrest.StringDescription;
......
1 -package org.onlab.util; 1 +package org.onlab.junit;
2 2
3 import java.lang.reflect.Constructor; 3 import java.lang.reflect.Constructor;
4 import java.lang.reflect.Field; 4 import java.lang.reflect.Field;
......
1 +package org.onlab.junit;
2 +
3 +import org.hamcrest.Description;
4 +import org.hamcrest.StringDescription;
5 +import org.onlab.junit.TestUtils.TestUtilsException;
6 +
7 +import java.lang.reflect.Constructor;
8 +import java.lang.reflect.Method;
9 +import java.lang.reflect.Modifier;
10 +
11 +
12 +/**
13 + * Hamcrest style class for verifying that a class follows the
14 + * accepted rules for utility classes.
15 + *
16 + * The rules that are enforced for utility classes:
17 + * - the class must be declared final
18 + * - the class must have only one constructor
19 + * - the constructor must be private and inaccessible to callers
20 + * - the class must have only static methods
21 + */
22 +
23 +public class UtilityClassChecker {
24 +
25 + private String failureReason = "";
26 +
27 + /**
28 + * Method to determine if a given class is a properly specified
29 + * utility class. In addition to checking that the class meets the criteria
30 + * for utility classes, an object of the class type is allocated to force
31 + * test code coverage onto the class constructor.
32 + *
33 + * @param clazz the class to check
34 + * @return true if the given class is a properly specified utility class.
35 + */
36 + private boolean isProperlyDefinedUtilityClass(Class<?> clazz) {
37 + // class must be declared final
38 + if (!Modifier.isFinal(clazz.getModifiers())) {
39 + failureReason = "a class that is not final";
40 + return false;
41 + }
42 +
43 + // class must have only one constructor
44 + final Constructor<?>[] constructors = clazz.getDeclaredConstructors();
45 + if (constructors.length != 1) {
46 + failureReason = "a class with more than one constructor";
47 + return false;
48 + }
49 +
50 + // constructor must not be accessible outside of the class
51 + final Constructor<?> constructor = constructors[0];
52 + if (constructor.isAccessible()) {
53 + failureReason = "a class with an accessible default constructor";
54 + return false;
55 + }
56 +
57 + // constructor must be private
58 + if (!Modifier.isPrivate(constructor.getModifiers())) {
59 + failureReason = "a class with a default constructor that is not private";
60 + return false;
61 + }
62 +
63 + // class must have only static methods
64 + for (final Method method : clazz.getMethods()) {
65 + if (method.getDeclaringClass().equals(clazz)) {
66 + if (!Modifier.isStatic(method.getModifiers())) {
67 + failureReason = "a class with one or more non-static methods";
68 + return false;
69 + }
70 + }
71 +
72 + }
73 +
74 + try {
75 + final Object newObject = TestUtils.callConstructor(constructor);
76 + if (newObject == null) {
77 + failureReason = "could not instantiate a new object";
78 + return false;
79 + }
80 + } catch (TestUtilsException e) {
81 + failureReason = "could not instantiate a new object";
82 + return false;
83 + }
84 + return true;
85 + }
86 +
87 + /**
88 + * Describe why an error was reported. Uses Hamcrest style Description
89 + * interfaces.
90 + *
91 + * @param description the Description object to use for reporting the
92 + * mismatch
93 + */
94 + public void describeMismatch(Description description) {
95 + description.appendText(failureReason);
96 + }
97 +
98 + /**
99 + * Describe the source object that caused an error, using a Hamcrest
100 + * Matcher style interface. In this case, it always returns
101 + * that we are looking for a properly defined utility class.
102 + *
103 + * @param description the Description object to use to report the "to"
104 + * object
105 + */
106 + public void describeTo(Description description) {
107 + description.appendText("a properly defined utility class");
108 + }
109 +
110 + /**
111 + * Assert that the given class adheres to the utility class rules.
112 + *
113 + * @param clazz the class to check
114 + *
115 + * @throws java.lang.AssertionError if the class is not a valid
116 + * utility class
117 + */
118 + public static void assertThatClassIsUtility(Class<?> clazz) {
119 + final UtilityClassChecker checker = new UtilityClassChecker();
120 + if (!checker.isProperlyDefinedUtilityClass(clazz)) {
121 + final Description toDescription = new StringDescription();
122 + final Description mismatchDescription = new StringDescription();
123 +
124 + checker.describeTo(toDescription);
125 + checker.describeMismatch(mismatchDescription);
126 + final String reason =
127 + "\n" +
128 + "Expected: is \"" + toDescription.toString() + "\"\n" +
129 + " but : was \"" + mismatchDescription.toString() + "\"";
130 +
131 + throw new AssertionError(reason);
132 + }
133 + }
134 +}
1 +package org.onlab.junit;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.hamcrest.MatcherAssert.assertThat;
6 +import static org.hamcrest.Matchers.containsString;
7 +import static org.hamcrest.Matchers.is;
8 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
9 +
10 +/**
11 + * Set of unit tests to check the implementation of the immutable class
12 + * checker.
13 + */
14 +public class ImmutableClassCheckerTest {
15 + /**
16 + * Test class for non final class check.
17 + */
18 + // CHECKSTYLE IGNORE FinalClass FOR NEXT 1 LINES
19 + static class NonFinal {
20 + private NonFinal() { }
21 + }
22 +
23 + /**
24 + * Check that a non final class correctly produces an error.
25 + * @throws Exception if any of the reflection lookups fail.
26 + */
27 + @Test
28 + public void testNonFinalClass() throws Exception {
29 + boolean gotException = false;
30 + try {
31 + assertThatClassIsImmutable(NonFinal.class);
32 + } catch (AssertionError assertion) {
33 + assertThat(assertion.getMessage(),
34 + containsString("is not final"));
35 + gotException = true;
36 + }
37 + assertThat(gotException, is(true));
38 + }
39 +
40 + /**
41 + * Test class for non private member class check.
42 + */
43 + static final class FinalProtectedMember {
44 + protected final int x = 0;
45 + }
46 +
47 + /**
48 + * Check that a final class with a non-private member is properly detected.
49 + *
50 + * @throws Exception if any of the reflection lookups fail.
51 + */
52 + @Test
53 + public void testFinalProtectedMember() throws Exception {
54 + boolean gotException = false;
55 + try {
56 + assertThatClassIsImmutable(FinalProtectedMember.class);
57 + } catch (AssertionError assertion) {
58 + assertThat(assertion.getMessage(),
59 + containsString("a field named 'x' that is not private"));
60 + gotException = true;
61 + }
62 + assertThat(gotException, is(true));
63 + }
64 +
65 + /**
66 + * Test class for non private member class check.
67 + */
68 + static final class NotFinalPrivateMember {
69 + private int x = 0;
70 + }
71 +
72 + /**
73 + * Check that a final class with a non-final private
74 + * member is properly detected.
75 + *
76 + * @throws Exception if any of the reflection lookups fail.
77 + */
78 + @Test
79 + public void testNotFinalPrivateMember() throws Exception {
80 + boolean gotException = false;
81 + try {
82 + assertThatClassIsImmutable(NotFinalPrivateMember.class);
83 + } catch (AssertionError assertion) {
84 + assertThat(assertion.getMessage(),
85 + containsString("a field named 'x' that is not final"));
86 + gotException = true;
87 + }
88 + assertThat(gotException, is(true));
89 + }
90 +
91 + /**
92 + * Test class for non private member class check.
93 + */
94 + static final class ClassWithSetter {
95 + private final int x = 0;
96 + public void setX(int newX) {
97 + }
98 + }
99 +
100 + /**
101 + * Check that a final class with a final private
102 + * member that is modifyable by a setter is properly detected.
103 + *
104 + * @throws Exception if any of the reflection lookups fail.
105 + */
106 + @Test
107 + public void testClassWithSetter() throws Exception {
108 + boolean gotException = false;
109 + try {
110 + assertThatClassIsImmutable(ClassWithSetter.class);
111 + } catch (AssertionError assertion) {
112 + assertThat(assertion.getMessage(),
113 + containsString("a class with a setter named 'setX'"));
114 + gotException = true;
115 + }
116 + assertThat(gotException, is(true));
117 + }
118 +
119 +}
120 +
1 -package org.onlab.util; 1 +package org.onlab.junit;
2 2
3 import static org.junit.Assert.assertArrayEquals; 3 import static org.junit.Assert.assertArrayEquals;
4 import static org.junit.Assert.assertEquals; 4 import static org.junit.Assert.assertEquals;
...@@ -6,7 +6,7 @@ import static org.junit.Assert.assertNull; ...@@ -6,7 +6,7 @@ import static org.junit.Assert.assertNull;
6 6
7 import org.junit.Before; 7 import org.junit.Before;
8 import org.junit.Test; 8 import org.junit.Test;
9 -import org.onlab.util.TestUtils.TestUtilsException; 9 +import org.onlab.junit.TestUtils.TestUtilsException;
10 10
11 /** 11 /**
12 * Test and usage examples for TestUtils. 12 * Test and usage examples for TestUtils.
......
1 +package org.onlab.junit;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.hamcrest.MatcherAssert.assertThat;
6 +import static org.hamcrest.Matchers.containsString;
7 +import static org.hamcrest.Matchers.is;
8 +import static org.onlab.junit.UtilityClassChecker.assertThatClassIsUtility;
9 +
10 +/**
11 + * Set of unit tests to check the implementation of the utility class
12 + * checker.
13 + */
14 +public class UtilityClassCheckerTest {
15 +
16 + // CHECKSTYLE:OFF test data intentionally not final
17 + /**
18 + * Test class for non final class check.
19 + */
20 + static class NonFinal {
21 + private NonFinal() { }
22 + }
23 + // CHECKSTYLE:ON
24 +
25 + /**
26 + * Check that a non final class correctly produces an error.
27 + * @throws Exception if any of the reflection lookups fail.
28 + */
29 + @Test
30 + public void testNonFinalClass() throws Exception {
31 + boolean gotException = false;
32 + try {
33 + assertThatClassIsUtility(NonFinal.class);
34 + } catch (AssertionError assertion) {
35 + assertThat(assertion.getMessage(),
36 + containsString("is not final"));
37 + gotException = true;
38 + }
39 + assertThat(gotException, is(true));
40 + }
41 +
42 + /**
43 + * Test class for final no constructor class check.
44 + */
45 + static final class FinalNoConstructor {
46 + }
47 +
48 + /**
49 + * Check that a final class with no declared constructor correctly produces
50 + * an error. In this case, the compiler generates a default constructor
51 + * for you, but the constructor is 'protected' and will fail the check.
52 + *
53 + * @throws Exception if any of the reflection lookups fail.
54 + */
55 + @Test
56 + public void testFinalNoConstructorClass() throws Exception {
57 + boolean gotException = false;
58 + try {
59 + assertThatClassIsUtility(FinalNoConstructor.class);
60 + } catch (AssertionError assertion) {
61 + assertThat(assertion.getMessage(),
62 + containsString("class with a default constructor that " +
63 + "is not private"));
64 + gotException = true;
65 + }
66 + assertThat(gotException, is(true));
67 + }
68 +
69 + /**
70 + * Test class for class with more than one constructor check.
71 + */
72 + static final class TwoConstructors {
73 + private TwoConstructors() { }
74 + private TwoConstructors(int x) { }
75 + }
76 +
77 + /**
78 + * Check that a non static class correctly produces an error.
79 + * @throws Exception if any of the reflection lookups fail.
80 + */
81 + @Test
82 + public void testOnlyOneConstructor() throws Exception {
83 + boolean gotException = false;
84 + try {
85 + assertThatClassIsUtility(TwoConstructors.class);
86 + } catch (AssertionError assertion) {
87 + assertThat(assertion.getMessage(),
88 + containsString("more than one constructor"));
89 + gotException = true;
90 + }
91 + assertThat(gotException, is(true));
92 + }
93 +
94 + /**
95 + * Test class with a non private constructor.
96 + */
97 + static final class NonPrivateConstructor {
98 + protected NonPrivateConstructor() { }
99 + }
100 +
101 + /**
102 + * Check that a class with a non private constructor correctly
103 + * produces an error.
104 + * @throws Exception if any of the reflection lookups fail.
105 + */
106 + @Test
107 + public void testNonPrivateConstructor() throws Exception {
108 +
109 + boolean gotException = false;
110 + try {
111 + assertThatClassIsUtility(NonPrivateConstructor.class);
112 + } catch (AssertionError assertion) {
113 + assertThat(assertion.getMessage(),
114 + containsString("constructor that is not private"));
115 + gotException = true;
116 + }
117 + assertThat(gotException, is(true));
118 + }
119 +
120 + /**
121 + * Test class with a non static method.
122 + */
123 + static final class NonStaticMethod {
124 + private NonStaticMethod() { }
125 + public void aPublicMethod() { }
126 + }
127 +
128 + /**
129 + * Check that a class with a non static method correctly produces an error.
130 + * @throws Exception if any of the reflection lookups fail.
131 + */
132 + @Test
133 + public void testNonStaticMethod() throws Exception {
134 +
135 + boolean gotException = false;
136 + try {
137 + assertThatClassIsUtility(NonStaticMethod.class);
138 + } catch (AssertionError assertion) {
139 + assertThat(assertion.getMessage(),
140 + containsString("one or more non-static methods"));
141 + gotException = true;
142 + }
143 + assertThat(gotException, is(true));
144 + }
145 +}
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
24 <dependency> 24 <dependency>
25 <groupId>org.onlab.onos</groupId> 25 <groupId>org.onlab.onos</groupId>
26 <artifactId>onlab-junit</artifactId> 26 <artifactId>onlab-junit</artifactId>
27 + <scope>test</scope>
27 </dependency> 28 </dependency>
28 <dependency> 29 <dependency>
29 <groupId>io.netty</groupId> 30 <groupId>io.netty</groupId>
......
1 +package org.onlab.packet;
2 +
3 +import java.nio.ByteBuffer;
4 +import static com.google.common.base.Preconditions.checkNotNull;
5 +
6 +/**
7 + * The class representing an IPv4 address.
8 + * This class is immutable.
9 + */
10 +public final class Ip4Address implements Comparable<Ip4Address> {
11 + private final int value;
12 +
13 + /** The length of the address in bytes (octets). */
14 + public static final int BYTE_LENGTH = 4;
15 +
16 + /** The length of the address in bits. */
17 + public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;
18 +
19 + /**
20 + * Default constructor.
21 + */
22 + public Ip4Address() {
23 + this.value = 0;
24 + }
25 +
26 + /**
27 + * Copy constructor.
28 + *
29 + * @param other the object to copy from
30 + */
31 + public Ip4Address(Ip4Address other) {
32 + this.value = other.value;
33 + }
34 +
35 + /**
36 + * Constructor from an integer value.
37 + *
38 + * @param value the value to use
39 + */
40 + public Ip4Address(int value) {
41 + this.value = value;
42 + }
43 +
44 + /**
45 + * Constructor from a byte array with the IPv4 address stored in network
46 + * byte order (i.e., the most significant byte first).
47 + *
48 + * @param value the value to use
49 + */
50 + public Ip4Address(byte[] value) {
51 + this(value, 0);
52 + }
53 +
54 + /**
55 + * Constructor from a byte array with the IPv4 address stored in network
56 + * byte order (i.e., the most significant byte first), and a given offset
57 + * from the beginning of the byte array.
58 + *
59 + * @param value the value to use
60 + * @param offset the offset in bytes from the beginning of the byte array
61 + */
62 + public Ip4Address(byte[] value, int offset) {
63 + checkNotNull(value);
64 +
65 + // Verify the arguments
66 + if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
67 + String msg;
68 + if (value.length < BYTE_LENGTH) {
69 + msg = "Invalid IPv4 address array: array length: " +
70 + value.length + ". Must be at least " + BYTE_LENGTH;
71 + } else {
72 + msg = "Invalid IPv4 address array: array offset: " +
73 + offset + ". Must be in the interval [0, " +
74 + (value.length - BYTE_LENGTH) + "]";
75 + }
76 + throw new IllegalArgumentException(msg);
77 + }
78 +
79 + // Read the address
80 + ByteBuffer bb = ByteBuffer.wrap(value);
81 + this.value = bb.getInt(offset);
82 + }
83 +
84 + /**
85 + * Constructs an IPv4 address from a string representation of the address.
86 + *<p>
87 + * Example: "1.2.3.4"
88 + *
89 + * @param value the value to use
90 + */
91 + public Ip4Address(String value) {
92 + checkNotNull(value);
93 +
94 + String[] splits = value.split("\\.");
95 + if (splits.length != 4) {
96 + final String msg = "Invalid IPv4 address string: " + value;
97 + throw new IllegalArgumentException(msg);
98 + }
99 +
100 + int result = 0;
101 + for (int i = 0; i < BYTE_LENGTH; i++) {
102 + result |= Integer.parseInt(splits[i]) <<
103 + ((BYTE_LENGTH - (i + 1)) * Byte.SIZE);
104 + }
105 + this.value = result;
106 + }
107 +
108 + /**
109 + * Gets the IPv4 address as a byte array.
110 + *
111 + * @return a byte array with the IPv4 address stored in network byte order
112 + * (i.e., the most significant byte first).
113 + */
114 + public byte[] toOctets() {
115 + return ByteBuffer.allocate(BYTE_LENGTH).putInt(value).array();
116 + }
117 +
118 + /**
119 + * Creates an IPv4 network mask prefix.
120 + *
121 + * @param prefixLen the length of the mask prefix. Must be in the interval
122 + * [0, 32].
123 + * @return a new IPv4 address that contains a mask prefix of the
124 + * specified length
125 + */
126 + public static Ip4Address makeMaskPrefix(int prefixLen) {
127 + // Verify the prefix length
128 + if ((prefixLen < 0) || (prefixLen > Ip4Address.BIT_LENGTH)) {
129 + final String msg = "Invalid IPv4 prefix length: " + prefixLen +
130 + ". Must be in the interval [0, 32].";
131 + throw new IllegalArgumentException(msg);
132 + }
133 +
134 + long v =
135 + (0xffffffffL << (Ip4Address.BIT_LENGTH - prefixLen)) & 0xffffffffL;
136 + return new Ip4Address((int) v);
137 + }
138 +
139 + /**
140 + * Creates an IPv4 address by masking it with a network mask of given
141 + * mask length.
142 + *
143 + * @param addr the address to mask
144 + * @param prefixLen the length of the mask prefix. Must be in the interval
145 + * [0, 32].
146 + * @return a new IPv4 address that is masked with a mask prefix of the
147 + * specified length
148 + */
149 + public static Ip4Address makeMaskedAddress(final Ip4Address addr,
150 + int prefixLen) {
151 + Ip4Address mask = Ip4Address.makeMaskPrefix(prefixLen);
152 + long v = addr.value & mask.value;
153 +
154 + return new Ip4Address((int) v);
155 + }
156 +
157 + /**
158 + * Gets the value of the IPv4 address.
159 + *
160 + * @return the value of the IPv4 address
161 + */
162 + public int getValue() {
163 + return value;
164 + }
165 +
166 + /**
167 + * Converts the IPv4 value to a '.' separated string.
168 + *
169 + * @return the IPv4 value as a '.' separated string
170 + */
171 + @Override
172 + public String toString() {
173 + return ((this.value >> 24) & 0xff) + "." +
174 + ((this.value >> 16) & 0xff) + "." +
175 + ((this.value >> 8) & 0xff) + "." +
176 + (this.value & 0xff);
177 + }
178 +
179 + @Override
180 + public boolean equals(Object o) {
181 + if (!(o instanceof Ip4Address)) {
182 + return false;
183 + }
184 + Ip4Address other = (Ip4Address) o;
185 + if (this.value != other.value) {
186 + return false;
187 + }
188 + return true;
189 + }
190 +
191 + @Override
192 + public int hashCode() {
193 + return this.value;
194 + }
195 +
196 + @Override
197 + public int compareTo(Ip4Address o) {
198 + Long lv = ((long) this.value) & 0xffffffffL;
199 + Long rv = ((long) o.value) & 0xffffffffL;
200 + return lv.compareTo(rv);
201 + }
202 +}
1 +package org.onlab.packet;
2 +
3 +import java.util.Objects;
4 +
5 +/**
6 + * The class representing an IPv4 network address.
7 + * This class is immutable.
8 + */
9 +public final class Ip4Prefix {
10 + private final Ip4Address address; // The IPv4 address
11 + private final short prefixLen; // The prefix length
12 +
13 + /**
14 + * Default constructor.
15 + */
16 + public Ip4Prefix() {
17 + this.address = new Ip4Address();
18 + this.prefixLen = 0;
19 + }
20 +
21 + /**
22 + * Copy constructor.
23 + *
24 + * @param other the object to copy from
25 + */
26 + public Ip4Prefix(Ip4Prefix other) {
27 + this.address = new Ip4Address(other.address);
28 + this.prefixLen = other.prefixLen;
29 + }
30 +
31 + /**
32 + * Constructor for a given address and prefix length.
33 + *
34 + * @param address the address to use
35 + * @param prefixLen the prefix length to use
36 + */
37 + public Ip4Prefix(Ip4Address address, short prefixLen) {
38 + this.address = Ip4Address.makeMaskedAddress(address, prefixLen);
39 + this.prefixLen = prefixLen;
40 + }
41 +
42 + /**
43 + * Constructs an IPv4 prefix from a string representation of the
44 + * prefix.
45 + *<p>
46 + * Example: "1.2.0.0/16"
47 + *
48 + * @param value the value to use
49 + */
50 + public Ip4Prefix(String value) {
51 + String[] splits = value.split("/");
52 + if (splits.length != 2) {
53 + throw new IllegalArgumentException("Specified IPv4 prefix must contain an IPv4 " +
54 + "address and a prefix length separated by '/'");
55 + }
56 + this.prefixLen = Short.decode(splits[1]);
57 + this.address = Ip4Address.makeMaskedAddress(new Ip4Address(splits[0]),
58 + this.prefixLen);
59 + }
60 +
61 + /**
62 + * Gets the address value of the IPv4 prefix.
63 + *
64 + * @return the address value of the IPv4 prefix
65 + */
66 + public Ip4Address getAddress() {
67 + return address;
68 + }
69 +
70 + /**
71 + * Gets the prefix length value of the IPv4 prefix.
72 + *
73 + * @return the prefix length value of the IPv4 prefix
74 + */
75 + public short getPrefixLen() {
76 + return prefixLen;
77 + }
78 +
79 + /**
80 + * Converts the IPv4 prefix value to an "address/prefixLen" string.
81 + *
82 + * @return the IPv4 prefix value as an "address/prefixLen" string
83 + */
84 + @Override
85 + public String toString() {
86 + return this.address.toString() + "/" + this.prefixLen;
87 + }
88 +
89 + /**
90 + * Compares the value of two Ip4Prefix objects.
91 + * <p/>
92 + * Note the value of the IPv4 address is compared directly between the
93 + * objects, and must match exactly for the objects to be considered equal.
94 + * This may result in objects which represent the same IP prefix being
95 + * classified as unequal, because the unsignificant bits of the address
96 + * field don't match (the bits to the right of the prefix length).
97 + * <p/>
98 + * TODO Change this behavior so that objects that represent the same prefix
99 + * are classified as equal according to this equals method.
100 + *
101 + * @see Object#equals(Object)
102 + */
103 + @Override
104 + public boolean equals(Object other) {
105 + if (other == this) {
106 + return true;
107 + }
108 +
109 + if (!(other instanceof Ip4Prefix)) {
110 + return false;
111 + }
112 +
113 + Ip4Prefix otherIp4Prefix = (Ip4Prefix) other;
114 +
115 + return Objects.equals(this.address, otherIp4Prefix.address)
116 + && this.prefixLen == otherIp4Prefix.prefixLen;
117 + }
118 +
119 + @Override
120 + public int hashCode() {
121 + return Objects.hash(address, prefixLen);
122 + }
123 +}
1 +package org.onlab.packet;
2 +
3 +import java.net.InetAddress;
4 +import java.net.UnknownHostException;
5 +import java.nio.ByteBuffer;
6 +import java.util.Objects;
7 +
8 +import com.google.common.net.InetAddresses;
9 +import com.google.common.primitives.UnsignedLongs;
10 +
11 +import static com.google.common.base.Preconditions.checkNotNull;
12 +import static com.google.common.base.Preconditions.checkState;
13 +
14 +/**
15 + * The class representing an IPv6 address.
16 + * This class is immutable.
17 + */
18 +public final class Ip6Address implements Comparable<Ip6Address> {
19 + private final long valueHigh; // The higher (more significant) 64 bits
20 + private final long valueLow; // The lower (less significant) 64 bits
21 +
22 + /** The length of the address in bytes (octets). */
23 + public static final int BYTE_LENGTH = 16;
24 +
25 + /** The length of the address in bits. */
26 + public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;
27 +
28 + /**
29 + * Default constructor.
30 + */
31 + public Ip6Address() {
32 + this.valueHigh = 0;
33 + this.valueLow = 0;
34 + }
35 +
36 + /**
37 + * Copy constructor.
38 + *
39 + * @param other the object to copy from
40 + */
41 + public Ip6Address(Ip6Address other) {
42 + this.valueHigh = other.valueHigh;
43 + this.valueLow = other.valueLow;
44 + }
45 +
46 + /**
47 + * Constructor from integer values.
48 + *
49 + * @param valueHigh the higher (more significant) 64 bits of the address
50 + * @param valueLow the lower (less significant) 64 bits of the address
51 + */
52 + public Ip6Address(long valueHigh, long valueLow) {
53 + this.valueHigh = valueHigh;
54 + this.valueLow = valueLow;
55 + }
56 +
57 + /**
58 + * Constructor from a byte array with the IPv6 address stored in network
59 + * byte order (i.e., the most significant byte first).
60 + *
61 + * @param value the value to use
62 + */
63 + public Ip6Address(byte[] value) {
64 + this(value, 0);
65 + }
66 +
67 + /**
68 + * Constructor from a byte array with the IPv6 address stored in network
69 + * byte order (i.e., the most significant byte first), and a given offset
70 + * from the beginning of the byte array.
71 + *
72 + * @param value the value to use
73 + * @param offset the offset in bytes from the beginning of the byte array
74 + */
75 + public Ip6Address(byte[] value, int offset) {
76 + checkNotNull(value);
77 +
78 + // Verify the arguments
79 + if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
80 + String msg;
81 + if (value.length < BYTE_LENGTH) {
82 + msg = "Invalid IPv6 address array: array length: " +
83 + value.length + ". Must be at least " + BYTE_LENGTH;
84 + } else {
85 + msg = "Invalid IPv6 address array: array offset: " +
86 + offset + ". Must be in the interval [0, " +
87 + (value.length - BYTE_LENGTH) + "]";
88 + }
89 + throw new IllegalArgumentException(msg);
90 + }
91 +
92 + // Read the address
93 + ByteBuffer bb = ByteBuffer.wrap(value);
94 + bb.position(offset);
95 + this.valueHigh = bb.getLong();
96 + this.valueLow = bb.getLong();
97 + }
98 +
99 + /**
100 + * Constructs an IPv6 address from a string representation of the address.
101 + *<p>
102 + * Example: "1111:2222::8888"
103 + *
104 + * @param value the value to use
105 + */
106 + public Ip6Address(String value) {
107 + checkNotNull(value);
108 +
109 + if (value.isEmpty()) {
110 + final String msg = "Specified IPv6 cannot be an empty string";
111 + throw new IllegalArgumentException(msg);
112 + }
113 + InetAddress addr = null;
114 + try {
115 + addr = InetAddresses.forString(value);
116 + } catch (IllegalArgumentException e) {
117 + final String msg = "Invalid IPv6 address string: " + value;
118 + throw new IllegalArgumentException(msg);
119 + }
120 + byte[] bytes = addr.getAddress();
121 + ByteBuffer bb = ByteBuffer.wrap(bytes);
122 + this.valueHigh = bb.getLong();
123 + this.valueLow = bb.getLong();
124 + }
125 +
126 + /**
127 + * Gets the IPv6 address as a byte array.
128 + *
129 + * @return a byte array with the IPv6 address stored in network byte order
130 + * (i.e., the most significant byte first).
131 + */
132 + public byte[] toOctets() {
133 + return ByteBuffer.allocate(BYTE_LENGTH)
134 + .putLong(valueHigh).putLong(valueLow).array();
135 + }
136 +
137 + /**
138 + * Creates an IPv6 network mask prefix.
139 + *
140 + * @param prefixLen the length of the mask prefix. Must be in the interval
141 + * [0, 128].
142 + * @return a new IPv6 address that contains a mask prefix of the
143 + * specified length
144 + */
145 + public static Ip6Address makeMaskPrefix(int prefixLen) {
146 + long vh, vl;
147 +
148 + // Verify the prefix length
149 + if ((prefixLen < 0) || (prefixLen > Ip6Address.BIT_LENGTH)) {
150 + final String msg = "Invalid IPv6 prefix length: " + prefixLen +
151 + ". Must be in the interval [0, 128].";
152 + throw new IllegalArgumentException(msg);
153 + }
154 +
155 + if (prefixLen == 0) {
156 + //
157 + // NOTE: Apparently, the result of "<< 64" shifting to the left
158 + // results in all 1s instead of all 0s, hence we handle it as
159 + // a special case.
160 + //
161 + vh = 0;
162 + vl = 0;
163 + } else if (prefixLen <= 64) {
164 + vh = (0xffffffffffffffffL << (64 - prefixLen)) & 0xffffffffffffffffL;
165 + vl = 0;
166 + } else {
167 + vh = -1L; // All 1s
168 + vl = (0xffffffffffffffffL << (128 - prefixLen)) & 0xffffffffffffffffL;
169 + }
170 + return new Ip6Address(vh, vl);
171 + }
172 +
173 + /**
174 + * Creates an IPv6 address by masking it with a network mask of given
175 + * mask length.
176 + *
177 + * @param addr the address to mask
178 + * @param prefixLen the length of the mask prefix. Must be in the interval
179 + * [0, 128].
180 + * @return a new IPv6 address that is masked with a mask prefix of the
181 + * specified length
182 + */
183 + public static Ip6Address makeMaskedAddress(final Ip6Address addr,
184 + int prefixLen) {
185 + Ip6Address mask = Ip6Address.makeMaskPrefix(prefixLen);
186 + long vh = addr.valueHigh & mask.valueHigh;
187 + long vl = addr.valueLow & mask.valueLow;
188 +
189 + return new Ip6Address(vh, vl);
190 + }
191 +
192 + /**
193 + * Gets the value of the higher (more significant) 64 bits of the address.
194 + *
195 + * @return the value of the higher (more significant) 64 bits of the
196 + * address
197 + */
198 + public long getValueHigh() {
199 + return valueHigh;
200 + }
201 +
202 + /**
203 + * Gets the value of the lower (less significant) 64 bits of the address.
204 + *
205 + * @return the value of the lower (less significant) 64 bits of the
206 + * address
207 + */
208 + public long getValueLow() {
209 + return valueLow;
210 + }
211 +
212 + /**
213 + * Converts the IPv6 value to a ':' separated string.
214 + *
215 + * @return the IPv6 value as a ':' separated string
216 + */
217 + @Override
218 + public String toString() {
219 + ByteBuffer bb = ByteBuffer.allocate(Ip6Address.BYTE_LENGTH);
220 + bb.putLong(valueHigh);
221 + bb.putLong(valueLow);
222 + InetAddress inetAddr = null;
223 + try {
224 + inetAddr = InetAddress.getByAddress(bb.array());
225 + } catch (UnknownHostException e) {
226 + // Should never happen
227 + checkState(false, "Internal error: Ip6Address.toString()");
228 + return "::";
229 + }
230 + return InetAddresses.toAddrString(inetAddr);
231 + }
232 +
233 + @Override
234 + public boolean equals(Object o) {
235 + if (!(o instanceof Ip6Address)) {
236 + return false;
237 + }
238 + Ip6Address other = (Ip6Address) o;
239 + return this.valueHigh == other.valueHigh
240 + && this.valueLow == other.valueLow;
241 + }
242 +
243 + @Override
244 + public int hashCode() {
245 + return Objects.hash(valueHigh, valueLow);
246 + }
247 +
248 + @Override
249 + public int compareTo(Ip6Address o) {
250 + // Compare the high-order 64-bit value
251 + if (this.valueHigh != o.valueHigh) {
252 + return UnsignedLongs.compare(this.valueHigh, o.valueHigh);
253 + }
254 + // Compare the low-order 64-bit value
255 + if (this.valueLow != o.valueLow) {
256 + return UnsignedLongs.compare(this.valueLow, o.valueLow);
257 + }
258 + return 0;
259 + }
260 +}
1 +package org.onlab.packet;
2 +
3 +import java.util.Objects;
4 +
5 +/**
6 + * The class representing an IPv6 network address.
7 + * This class is immutable.
8 + */
9 +public final class Ip6Prefix {
10 + private final Ip6Address address; // The IPv6 address
11 + private final short prefixLen; // The prefix length
12 +
13 + /**
14 + * Default constructor.
15 + */
16 + public Ip6Prefix() {
17 + this.address = new Ip6Address();
18 + this.prefixLen = 0;
19 + }
20 +
21 + /**
22 + * Copy constructor.
23 + *
24 + * @param other the object to copy from
25 + */
26 + public Ip6Prefix(Ip6Prefix other) {
27 + this.address = new Ip6Address(other.address);
28 + this.prefixLen = other.prefixLen;
29 + }
30 +
31 + /**
32 + * Constructor for a given address and prefix length.
33 + *
34 + * @param address the address to use
35 + * @param prefixLen the prefix length to use
36 + */
37 + public Ip6Prefix(Ip6Address address, short prefixLen) {
38 + this.address = Ip6Address.makeMaskedAddress(address, prefixLen);
39 + this.prefixLen = prefixLen;
40 + }
41 +
42 + /**
43 + * Constructs an IPv6 prefix from a string representation of the
44 + * prefix.
45 + *<p>
46 + * Example: "1111:2222::/32"
47 + *
48 + * @param value the value to use
49 + */
50 + public Ip6Prefix(String value) {
51 + String[] splits = value.split("/");
52 + if (splits.length != 2) {
53 + throw new IllegalArgumentException("Specified IPv6 prefix must contain an IPv6 " +
54 + "address and a prefix length separated by '/'");
55 + }
56 + this.prefixLen = Short.decode(splits[1]);
57 + this.address = Ip6Address.makeMaskedAddress(new Ip6Address(splits[0]),
58 + this.prefixLen);
59 + }
60 +
61 + /**
62 + * Gets the address value of the IPv6 prefix.
63 + *
64 + * @return the address value of the IPv6 prefix
65 + */
66 + public Ip6Address getAddress() {
67 + return address;
68 + }
69 +
70 + /**
71 + * Gets the prefix length value of the IPv6 prefix.
72 + *
73 + * @return the prefix length value of the IPv6 prefix
74 + */
75 + public short getPrefixLen() {
76 + return prefixLen;
77 + }
78 +
79 + /**
80 + * Converts the IPv6 prefix value to an "address/prefixLen" string.
81 + *
82 + * @return the IPv6 prefix value as an "address/prefixLen" string
83 + */
84 + @Override
85 + public String toString() {
86 + return this.address.toString() + "/" + this.prefixLen;
87 + }
88 +
89 + /**
90 + * Compares the value of two Ip6Prefix objects.
91 + * <p/>
92 + * Note the value of the IPv6 address is compared directly between the
93 + * objects, and must match exactly for the objects to be considered equal.
94 + * This may result in objects which represent the same IP prefix being
95 + * classified as unequal, because the unsignificant bits of the address
96 + * field don't match (the bits to the right of the prefix length).
97 + * <p/>
98 + * TODO Change this behavior so that objects that represent the same prefix
99 + * are classified as equal according to this equals method.
100 + *
101 + * @see Object#equals(Object)
102 + */
103 + @Override
104 + public boolean equals(Object other) {
105 + if (other == this) {
106 + return true;
107 + }
108 +
109 + if (!(other instanceof Ip6Prefix)) {
110 + return false;
111 + }
112 +
113 + Ip6Prefix otherIp6Prefix = (Ip6Prefix) other;
114 +
115 + return Objects.equals(this.address, otherIp6Prefix.address)
116 + && this.prefixLen == otherIp6Prefix.prefixLen;
117 + }
118 +
119 + @Override
120 + public int hashCode() {
121 + return Objects.hash(address, prefixLen);
122 + }
123 +}
1 +package org.onlab.packet;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.hamcrest.Matchers.is;
6 +import static org.hamcrest.Matchers.not;
7 +import static org.junit.Assert.assertThat;
8 +import static org.junit.Assert.assertTrue;
9 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
10 +
11 +/**
12 + * Tests for class {@link Ip4Address}.
13 + */
14 +public class Ip4AddressTest {
15 + /**
16 + * Tests the immutability of {@link Ip4Address}.
17 + */
18 + @Test
19 + public void testImmutable() {
20 + assertThatClassIsImmutable(Ip4Address.class);
21 + }
22 +
23 + /**
24 + * Tests the length of the address in bytes (octets).
25 + */
26 + @Test
27 + public void testAddrBytelen() {
28 + assertThat(Ip4Address.BYTE_LENGTH, is(4));
29 + }
30 +
31 + /**
32 + * Tests the length of the address in bits.
33 + */
34 + @Test
35 + public void testAddrBitlen() {
36 + assertThat(Ip4Address.BIT_LENGTH, is(32));
37 + }
38 +
39 + /**
40 + * Tests default class constructor.
41 + */
42 + @Test
43 + public void testDefaultConstructor() {
44 + Ip4Address ip4Address = new Ip4Address();
45 + assertThat(ip4Address.toString(), is("0.0.0.0"));
46 + }
47 +
48 + /**
49 + * Tests valid class copy constructor.
50 + */
51 + @Test
52 + public void testCopyConstructor() {
53 + Ip4Address fromAddr = new Ip4Address("1.2.3.4");
54 + Ip4Address ip4Address = new Ip4Address(fromAddr);
55 + assertThat(ip4Address.toString(), is("1.2.3.4"));
56 +
57 + fromAddr = new Ip4Address("0.0.0.0");
58 + ip4Address = new Ip4Address(fromAddr);
59 + assertThat(ip4Address.toString(), is("0.0.0.0"));
60 +
61 + fromAddr = new Ip4Address("255.255.255.255");
62 + ip4Address = new Ip4Address(fromAddr);
63 + assertThat(ip4Address.toString(), is("255.255.255.255"));
64 + }
65 +
66 + /**
67 + * Tests invalid class copy constructor for a null object to copy from.
68 + */
69 + @Test(expected = NullPointerException.class)
70 + public void testInvalidConstructorNullObject() {
71 + Ip4Address fromAddr = null;
72 + Ip4Address ip4Address = new Ip4Address(fromAddr);
73 + }
74 +
75 + /**
76 + * Tests valid class constructor for an integer value.
77 + */
78 + @Test
79 + public void testConstructorForInteger() {
80 + Ip4Address ip4Address = new Ip4Address(0x01020304);
81 + assertThat(ip4Address.toString(), is("1.2.3.4"));
82 +
83 + ip4Address = new Ip4Address(0);
84 + assertThat(ip4Address.toString(), is("0.0.0.0"));
85 +
86 + ip4Address = new Ip4Address(0xffffffff);
87 + assertThat(ip4Address.toString(), is("255.255.255.255"));
88 + }
89 +
90 + /**
91 + * Tests valid class constructor for an array value.
92 + */
93 + @Test
94 + public void testConstructorForArray() {
95 + final byte[] value1 = new byte[] {1, 2, 3, 4};
96 + Ip4Address ip4Address = new Ip4Address(value1);
97 + assertThat(ip4Address.toString(), is("1.2.3.4"));
98 +
99 + final byte[] value2 = new byte[] {0, 0, 0, 0};
100 + ip4Address = new Ip4Address(value2);
101 + assertThat(ip4Address.toString(), is("0.0.0.0"));
102 +
103 + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
104 + (byte) 0xff, (byte) 0xff};
105 + ip4Address = new Ip4Address(value3);
106 + assertThat(ip4Address.toString(), is("255.255.255.255"));
107 + }
108 +
109 + /**
110 + * Tests valid class constructor for an array value and an offset.
111 + */
112 + @Test
113 + public void testConstructorForArrayAndOffset() {
114 + final byte[] value1 = new byte[] {11, 22, 33, // Preamble
115 + 1, 2, 3, 4,
116 + 44, 55}; // Extra bytes
117 + Ip4Address ip4Address = new Ip4Address(value1, 3);
118 + assertThat(ip4Address.toString(), is("1.2.3.4"));
119 +
120 + final byte[] value2 = new byte[] {11, 22, // Preamble
121 + 0, 0, 0, 0,
122 + 33}; // Extra bytes
123 + ip4Address = new Ip4Address(value2, 2);
124 + assertThat(ip4Address.toString(), is("0.0.0.0"));
125 +
126 + final byte[] value3 = new byte[] {11, 22, // Preamble
127 + (byte) 0xff, (byte) 0xff,
128 + (byte) 0xff, (byte) 0xff,
129 + 33}; // Extra bytes
130 + ip4Address = new Ip4Address(value3, 2);
131 + assertThat(ip4Address.toString(), is("255.255.255.255"));
132 + }
133 +
134 + /**
135 + * Tests invalid class constructor for a null array.
136 + */
137 + @Test(expected = NullPointerException.class)
138 + public void testInvalidConstructorNullArray() {
139 + final byte[] fromArray = null;
140 + Ip4Address ip4Address = new Ip4Address(fromArray);
141 + }
142 +
143 + /**
144 + * Tests invalid class constructor for an array that is too short.
145 + */
146 + @Test(expected = IllegalArgumentException.class)
147 + public void testInvalidConstructorShortArray() {
148 + final byte[] fromArray = new byte[] {1, 2, 3};
149 + Ip4Address ip4Address = new Ip4Address(fromArray);
150 + }
151 +
152 + /**
153 + * Tests invalid class constructor for an array and an invalid offset.
154 + */
155 + @Test(expected = IllegalArgumentException.class)
156 + public void testInvalidConstructorArrayInvalidOffset() {
157 + final byte[] value1 = new byte[] {11, 22, 33, // Preamble
158 + 1, 2, 3, 4,
159 + 44, 55}; // Extra bytes
160 + Ip4Address ip4Address = new Ip4Address(value1, 6);
161 + }
162 +
163 + /**
164 + * Tests valid class constructor for a string.
165 + */
166 + @Test
167 + public void testConstructorForString() {
168 + Ip4Address ip4Address = new Ip4Address("1.2.3.4");
169 + assertThat(ip4Address.toString(), is("1.2.3.4"));
170 +
171 + ip4Address = new Ip4Address("0.0.0.0");
172 + assertThat(ip4Address.toString(), is("0.0.0.0"));
173 +
174 + ip4Address = new Ip4Address("255.255.255.255");
175 + assertThat(ip4Address.toString(), is("255.255.255.255"));
176 + }
177 +
178 + /**
179 + * Tests invalid class constructor for a null string.
180 + */
181 + @Test(expected = NullPointerException.class)
182 + public void testInvalidConstructorNullString() {
183 + String fromString = null;
184 + Ip4Address ip4Address = new Ip4Address(fromString);
185 + }
186 +
187 + /**
188 + * Tests invalid class constructor for an empty string.
189 + */
190 + @Test(expected = IllegalArgumentException.class)
191 + public void testInvalidConstructors() {
192 + // Check constructor for invalid ID: empty string
193 + Ip4Address ip4Address = new Ip4Address("");
194 + }
195 +
196 + /**
197 + * Tests returning the address as a byte array.
198 + */
199 + @Test
200 + public void testAddressToOctets() {
201 + final byte[] value1 = new byte[] {1, 2, 3, 4};
202 + Ip4Address ip4Address = new Ip4Address("1.2.3.4");
203 + assertThat(ip4Address.toOctets(), is(value1));
204 +
205 + final byte[] value2 = new byte[] {0, 0, 0, 0};
206 + ip4Address = new Ip4Address("0.0.0.0");
207 + assertThat(ip4Address.toOctets(), is(value2));
208 +
209 + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
210 + (byte) 0xff, (byte) 0xff};
211 + ip4Address = new Ip4Address("255.255.255.255");
212 + assertThat(ip4Address.toOctets(), is(value3));
213 + }
214 +
215 + /**
216 + * Tests making a mask prefix for a given prefix length.
217 + */
218 + @Test
219 + public void testMakeMaskPrefix() {
220 + Ip4Address ip4Address = Ip4Address.makeMaskPrefix(25);
221 + assertThat(ip4Address.toString(), is("255.255.255.128"));
222 +
223 + ip4Address = Ip4Address.makeMaskPrefix(0);
224 + assertThat(ip4Address.toString(), is("0.0.0.0"));
225 +
226 + ip4Address = Ip4Address.makeMaskPrefix(32);
227 + assertThat(ip4Address.toString(), is("255.255.255.255"));
228 + }
229 +
230 + /**
231 + * Tests making of a masked address.
232 + */
233 + @Test
234 + public void testMakeMaskedAddress() {
235 + Ip4Address ip4Address = new Ip4Address("1.2.3.5");
236 + Ip4Address ip4AddressMasked =
237 + Ip4Address.makeMaskedAddress(ip4Address, 24);
238 + assertThat(ip4AddressMasked.toString(), is("1.2.3.0"));
239 +
240 + ip4AddressMasked = Ip4Address.makeMaskedAddress(ip4Address, 0);
241 + assertThat(ip4AddressMasked.toString(), is("0.0.0.0"));
242 +
243 + ip4AddressMasked = Ip4Address.makeMaskedAddress(ip4Address, 32);
244 + assertThat(ip4AddressMasked.toString(), is("1.2.3.5"));
245 + }
246 +
247 + /**
248 + * Tests getting the value of an address.
249 + */
250 + @Test
251 + public void testGetValue() {
252 + Ip4Address ip4Address = new Ip4Address("1.2.3.4");
253 + assertThat(ip4Address.getValue(), is(0x01020304));
254 +
255 + ip4Address = new Ip4Address("0.0.0.0");
256 + assertThat(ip4Address.getValue(), is(0));
257 +
258 + ip4Address = new Ip4Address("255.255.255.255");
259 + assertThat(ip4Address.getValue(), is(-1));
260 + }
261 +
262 + /**
263 + * Tests equality of {@link Ip4Address}.
264 + */
265 + @Test
266 + public void testEquality() {
267 + Ip4Address addr1 = new Ip4Address("1.2.3.4");
268 + Ip4Address addr2 = new Ip4Address("1.2.3.4");
269 + assertThat(addr1, is(addr2));
270 +
271 + addr1 = new Ip4Address("0.0.0.0");
272 + addr2 = new Ip4Address("0.0.0.0");
273 + assertThat(addr1, is(addr2));
274 +
275 + addr1 = new Ip4Address("255.255.255.255");
276 + addr2 = new Ip4Address("255.255.255.255");
277 + assertThat(addr1, is(addr2));
278 + }
279 +
280 + /**
281 + * Tests non-equality of {@link Ip4Address}.
282 + */
283 + @Test
284 + public void testNonEquality() {
285 + Ip4Address addr1 = new Ip4Address("1.2.3.4");
286 + Ip4Address addr2 = new Ip4Address("1.2.3.5");
287 + Ip4Address addr3 = new Ip4Address("0.0.0.0");
288 + Ip4Address addr4 = new Ip4Address("255.255.255.255");
289 + assertThat(addr1, is(not(addr2)));
290 + assertThat(addr3, is(not(addr2)));
291 + assertThat(addr4, is(not(addr2)));
292 + }
293 +
294 + /**
295 + * Tests comparison of {@link Ip4Address}.
296 + */
297 + @Test
298 + public void testComparison() {
299 + Ip4Address addr1 = new Ip4Address("1.2.3.4");
300 + Ip4Address addr2 = new Ip4Address("1.2.3.4");
301 + Ip4Address addr3 = new Ip4Address("1.2.3.3");
302 + Ip4Address addr4 = new Ip4Address("1.2.3.5");
303 + assertTrue(addr1.compareTo(addr2) == 0);
304 + assertTrue(addr1.compareTo(addr3) > 0);
305 + assertTrue(addr1.compareTo(addr4) < 0);
306 +
307 + addr1 = new Ip4Address("255.2.3.4");
308 + addr2 = new Ip4Address("255.2.3.4");
309 + addr3 = new Ip4Address("255.2.3.3");
310 + addr4 = new Ip4Address("255.2.3.5");
311 + assertTrue(addr1.compareTo(addr2) == 0);
312 + assertTrue(addr1.compareTo(addr3) > 0);
313 + assertTrue(addr1.compareTo(addr4) < 0);
314 + }
315 +
316 + /**
317 + * Tests object string representation.
318 + */
319 + @Test
320 + public void testToString() {
321 + Ip4Address ip4Address = new Ip4Address("1.2.3.4");
322 + assertThat(ip4Address.toString(), is("1.2.3.4"));
323 +
324 + ip4Address = new Ip4Address("0.0.0.0");
325 + assertThat(ip4Address.toString(), is("0.0.0.0"));
326 +
327 + ip4Address = new Ip4Address("255.255.255.255");
328 + assertThat(ip4Address.toString(), is("255.255.255.255"));
329 + }
330 +}
1 +package org.onlab.packet;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.hamcrest.Matchers.equalTo;
6 +import static org.hamcrest.Matchers.is;
7 +import static org.hamcrest.Matchers.not;
8 +import static org.junit.Assert.assertThat;
9 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
10 +
11 +/**
12 + * Tests for class {@link Ip4Prefix}.
13 + */
14 +public class Ip4PrefixTest {
15 + /**
16 + * Tests the immutability of {@link Ip4Prefix}.
17 + */
18 + @Test
19 + public void testImmutable() {
20 + assertThatClassIsImmutable(Ip4Prefix.class);
21 + }
22 +
23 + /**
24 + * Tests default class constructor.
25 + */
26 + @Test
27 + public void testDefaultConstructor() {
28 + Ip4Prefix ip4prefix = new Ip4Prefix();
29 + assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
30 + }
31 +
32 + /**
33 + * Tests valid class copy constructor.
34 + */
35 + @Test
36 + public void testCopyConstructor() {
37 + Ip4Prefix fromAddr = new Ip4Prefix("1.2.3.0/24");
38 + Ip4Prefix ip4prefix = new Ip4Prefix(fromAddr);
39 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
40 +
41 + fromAddr = new Ip4Prefix("0.0.0.0/0");
42 + ip4prefix = new Ip4Prefix(fromAddr);
43 + assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
44 +
45 + fromAddr = new Ip4Prefix("255.255.255.255/32");
46 + ip4prefix = new Ip4Prefix(fromAddr);
47 + assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
48 + }
49 +
50 + /**
51 + * Tests invalid class copy constructor for a null object to copy from.
52 + */
53 + @Test(expected = NullPointerException.class)
54 + public void testInvalidConstructorNullObject() {
55 + Ip4Prefix fromAddr = null;
56 + Ip4Prefix ip4prefix = new Ip4Prefix(fromAddr);
57 + }
58 +
59 + /**
60 + * Tests valid class constructor for an address and prefix length.
61 + */
62 + @Test
63 + public void testConstructorForAddressAndPrefixLength() {
64 + Ip4Prefix ip4prefix =
65 + new Ip4Prefix(new Ip4Address("1.2.3.0"), (short) 24);
66 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
67 +
68 + ip4prefix = new Ip4Prefix(new Ip4Address("1.2.3.4"), (short) 24);
69 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
70 +
71 + ip4prefix = new Ip4Prefix(new Ip4Address("1.2.3.5"), (short) 32);
72 + assertThat(ip4prefix.toString(), is("1.2.3.5/32"));
73 +
74 + ip4prefix = new Ip4Prefix(new Ip4Address("0.0.0.0"), (short) 0);
75 + assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
76 +
77 + ip4prefix =
78 + new Ip4Prefix(new Ip4Address("255.255.255.255"), (short) 32);
79 + assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
80 + }
81 +
82 + /**
83 + * Tests valid class constructor for a string.
84 + */
85 + @Test
86 + public void testConstructorForString() {
87 + Ip4Prefix ip4prefix = new Ip4Prefix("1.2.3.0/24");
88 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
89 +
90 + ip4prefix = new Ip4Prefix("1.2.3.4/24");
91 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
92 +
93 + ip4prefix = new Ip4Prefix("1.2.3.5/32");
94 + assertThat(ip4prefix.toString(), is("1.2.3.5/32"));
95 +
96 + ip4prefix = new Ip4Prefix("0.0.0.0/0");
97 + assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
98 +
99 + ip4prefix = new Ip4Prefix("255.255.255.255/32");
100 + assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
101 + }
102 +
103 + /**
104 + * Tests invalid class constructor for a null string.
105 + */
106 + @Test(expected = NullPointerException.class)
107 + public void testInvalidConstructorNullString() {
108 + String fromString = null;
109 + Ip4Prefix ip4prefix = new Ip4Prefix(fromString);
110 + }
111 +
112 + /**
113 + * Tests invalid class constructor for an empty string.
114 + */
115 + @Test(expected = IllegalArgumentException.class)
116 + public void testInvalidConstructors() {
117 + // Check constructor for invalid ID: empty string
118 + Ip4Prefix ip4prefix = new Ip4Prefix("");
119 + }
120 +
121 + /**
122 + * Tests getting the value of an address.
123 + */
124 + @Test
125 + public void testGetValue() {
126 + Ip4Prefix ip4prefix = new Ip4Prefix("1.2.3.0/24");
127 + assertThat(ip4prefix.getAddress(), equalTo(new Ip4Address("1.2.3.0")));
128 + assertThat(ip4prefix.getPrefixLen(), is((short) 24));
129 +
130 + ip4prefix = new Ip4Prefix("0.0.0.0/0");
131 + assertThat(ip4prefix.getAddress(), equalTo(new Ip4Address("0.0.0.0")));
132 + assertThat(ip4prefix.getPrefixLen(), is((short) 0));
133 +
134 + ip4prefix = new Ip4Prefix("255.255.255.255/32");
135 + assertThat(ip4prefix.getAddress(),
136 + equalTo(new Ip4Address("255.255.255.255")));
137 + assertThat(ip4prefix.getPrefixLen(), is((short) 32));
138 + }
139 +
140 + /**
141 + * Tests equality of {@link Ip4Address}.
142 + */
143 + @Test
144 + public void testEquality() {
145 + Ip4Prefix addr1net = new Ip4Prefix("1.2.3.0/24");
146 + Ip4Prefix addr2net = new Ip4Prefix("1.2.3.0/24");
147 + assertThat(addr1net, is(addr2net));
148 +
149 + addr1net = new Ip4Prefix("1.2.3.0/24");
150 + addr2net = new Ip4Prefix("1.2.3.4/24");
151 + assertThat(addr1net, is(addr2net));
152 +
153 + addr1net = new Ip4Prefix("0.0.0.0/0");
154 + addr2net = new Ip4Prefix("0.0.0.0/0");
155 + assertThat(addr1net, is(addr2net));
156 +
157 + addr1net = new Ip4Prefix("255.255.255.255/32");
158 + addr2net = new Ip4Prefix("255.255.255.255/32");
159 + assertThat(addr1net, is(addr2net));
160 + }
161 +
162 + /**
163 + * Tests non-equality of {@link Ip4Address}.
164 + */
165 + @Test
166 + public void testNonEquality() {
167 + Ip4Prefix addr1net = new Ip4Prefix("1.2.0.0/16");
168 + Ip4Prefix addr2net = new Ip4Prefix("1.3.0.0/16");
169 + Ip4Prefix addr3net = new Ip4Prefix("1.3.0.0/24");
170 + Ip4Prefix addr4net = new Ip4Prefix("0.0.0.0/0");
171 + Ip4Prefix addr5net = new Ip4Prefix("255.255.255.255/32");
172 + assertThat(addr1net, is(not(addr2net)));
173 + assertThat(addr3net, is(not(addr2net)));
174 + assertThat(addr4net, is(not(addr2net)));
175 + assertThat(addr5net, is(not(addr2net)));
176 + }
177 +
178 + /**
179 + * Tests object string representation.
180 + */
181 + @Test
182 + public void testToString() {
183 + Ip4Prefix ip4prefix = new Ip4Prefix("1.2.3.0/24");
184 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
185 +
186 + ip4prefix = new Ip4Prefix("1.2.3.4/24");
187 + assertThat(ip4prefix.toString(), is("1.2.3.0/24"));
188 +
189 + ip4prefix = new Ip4Prefix("0.0.0.0/0");
190 + assertThat(ip4prefix.toString(), is("0.0.0.0/0"));
191 +
192 + ip4prefix = new Ip4Prefix("255.255.255.255/32");
193 + assertThat(ip4prefix.toString(), is("255.255.255.255/32"));
194 + }
195 +}
1 +package org.onlab.packet;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.hamcrest.Matchers.is;
6 +import static org.hamcrest.Matchers.not;
7 +import static org.junit.Assert.assertThat;
8 +import static org.junit.Assert.assertTrue;
9 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
10 +
11 +/**
12 + * Tests for class {@link Ip6Address}.
13 + */
14 +public class Ip6AddressTest {
15 + /**
16 + * Tests the immutability of {@link Ip6Address}.
17 + */
18 + @Test
19 + public void testImmutable() {
20 + assertThatClassIsImmutable(Ip6Address.class);
21 + }
22 +
23 + /**
24 + * Tests the length of the address in bytes (octets).
25 + */
26 + @Test
27 + public void testAddrBytelen() {
28 + assertThat(Ip6Address.BYTE_LENGTH, is(16));
29 + }
30 +
31 + /**
32 + * Tests the length of the address in bits.
33 + */
34 + @Test
35 + public void testAddrBitlen() {
36 + assertThat(Ip6Address.BIT_LENGTH, is(128));
37 + }
38 +
39 + /**
40 + * Tests default class constructor.
41 + */
42 + @Test
43 + public void testDefaultConstructor() {
44 + Ip6Address ip6Address = new Ip6Address();
45 + assertThat(ip6Address.toString(), is("::"));
46 + }
47 +
48 + /**
49 + * Tests valid class copy constructor.
50 + */
51 + @Test
52 + public void testCopyConstructor() {
53 + Ip6Address fromAddr =
54 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
55 + Ip6Address ip6Address = new Ip6Address(fromAddr);
56 + assertThat(ip6Address.toString(),
57 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
58 +
59 + fromAddr = new Ip6Address("::");
60 + ip6Address = new Ip6Address(fromAddr);
61 + assertThat(ip6Address.toString(), is("::"));
62 +
63 + fromAddr = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
64 + ip6Address = new Ip6Address(fromAddr);
65 + assertThat(ip6Address.toString(),
66 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
67 + }
68 +
69 + /**
70 + * Tests invalid class copy constructor for a null object to copy from.
71 + */
72 + @Test(expected = NullPointerException.class)
73 + public void testInvalidConstructorNullObject() {
74 + Ip6Address fromAddr = null;
75 + Ip6Address ip6Address = new Ip6Address(fromAddr);
76 + }
77 +
78 + /**
79 + * Tests valid class constructor for integer values.
80 + */
81 + @Test
82 + public void testConstructorForInteger() {
83 + Ip6Address ip6Address =
84 + new Ip6Address(0x1111222233334444L, 0x5555666677778888L);
85 + assertThat(ip6Address.toString(),
86 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
87 +
88 + ip6Address = new Ip6Address(0L, 0L);
89 + assertThat(ip6Address.toString(), is("::"));
90 +
91 + ip6Address = new Ip6Address(-1L, -1L);
92 + assertThat(ip6Address.toString(),
93 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
94 + }
95 +
96 + /**
97 + * Tests valid class constructor for an array value.
98 + */
99 + @Test
100 + public void testConstructorForArray() {
101 + final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22,
102 + 0x33, 0x33, 0x44, 0x44,
103 + 0x55, 0x55, 0x66, 0x66,
104 + 0x77, 0x77,
105 + (byte) 0x88, (byte) 0x88};
106 + Ip6Address ip6Address = new Ip6Address(value1);
107 + assertThat(ip6Address.toString(),
108 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
109 +
110 + final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00,
111 + 0x00, 0x00, 0x00, 0x00,
112 + 0x00, 0x00, 0x00, 0x00,
113 + 0x00, 0x00, 0x00, 0x00};
114 + ip6Address = new Ip6Address(value2);
115 + assertThat(ip6Address.toString(), is("::"));
116 +
117 + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
118 + (byte) 0xff, (byte) 0xff,
119 + (byte) 0xff, (byte) 0xff,
120 + (byte) 0xff, (byte) 0xff,
121 + (byte) 0xff, (byte) 0xff,
122 + (byte) 0xff, (byte) 0xff,
123 + (byte) 0xff, (byte) 0xff,
124 + (byte) 0xff, (byte) 0xff};
125 + ip6Address = new Ip6Address(value3);
126 + assertThat(ip6Address.toString(),
127 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
128 + }
129 +
130 + /**
131 + * Tests valid class constructor for an array value and an offset.
132 + */
133 + @Test
134 + public void testConstructorForArrayAndOffset() {
135 + final byte[] value1 = new byte[] {11, 22, 33, // Preamble
136 + 0x11, 0x11, 0x22, 0x22,
137 + 0x33, 0x33, 0x44, 0x44,
138 + 0x55, 0x55, 0x66, 0x66,
139 + 0x77, 0x77,
140 + (byte) 0x88, (byte) 0x88,
141 + 44, 55}; // Extra bytes
142 + Ip6Address ip6Address = new Ip6Address(value1, 3);
143 + assertThat(ip6Address.toString(),
144 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
145 +
146 + final byte[] value2 = new byte[] {11, 22, // Preamble
147 + 0x00, 0x00, 0x00, 0x00,
148 + 0x00, 0x00, 0x00, 0x00,
149 + 0x00, 0x00, 0x00, 0x00,
150 + 0x00, 0x00, 0x00, 0x00,
151 + 33}; // Extra bytes
152 + ip6Address = new Ip6Address(value2, 2);
153 + assertThat(ip6Address.toString(), is("::"));
154 +
155 + final byte[] value3 = new byte[] {11, 22, // Preamble
156 + (byte) 0xff, (byte) 0xff,
157 + (byte) 0xff, (byte) 0xff,
158 + (byte) 0xff, (byte) 0xff,
159 + (byte) 0xff, (byte) 0xff,
160 + (byte) 0xff, (byte) 0xff,
161 + (byte) 0xff, (byte) 0xff,
162 + (byte) 0xff, (byte) 0xff,
163 + (byte) 0xff, (byte) 0xff,
164 + 33}; // Extra bytes
165 + ip6Address = new Ip6Address(value3, 2);
166 + assertThat(ip6Address.toString(),
167 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
168 + }
169 +
170 + /**
171 + * Tests invalid class constructor for a null array.
172 + */
173 + @Test(expected = NullPointerException.class)
174 + public void testInvalidConstructorNullArray() {
175 + final byte[] fromArray = null;
176 + Ip6Address ip6Address = new Ip6Address(fromArray);
177 + }
178 +
179 + /**
180 + * Tests invalid class constructor for an array that is too short.
181 + */
182 + @Test(expected = IllegalArgumentException.class)
183 + public void testInvalidConstructorShortArray() {
184 + final byte[] fromArray = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
185 + Ip6Address ip6Address = new Ip6Address(fromArray);
186 + }
187 +
188 + /**
189 + * Tests invalid class constructor for an array and an invalid offset.
190 + */
191 + @Test(expected = IllegalArgumentException.class)
192 + public void testInvalidConstructorArrayInvalidOffset() {
193 + final byte[] value1 = new byte[] {11, 22, 33, // Preamble
194 + 0x11, 0x11, 0x22, 0x22,
195 + 0x33, 0x33, 0x44, 0x44,
196 + 0x55, 0x55, 0x66, 0x66,
197 + 0x77, 0x77,
198 + (byte) 0x88, (byte) 0x88,
199 + 44, 55}; // Extra bytes
200 + Ip6Address ip6Address = new Ip6Address(value1, 6);
201 + }
202 +
203 + /**
204 + * Tests valid class constructor for a string.
205 + */
206 + @Test
207 + public void testConstructorForString() {
208 + Ip6Address ip6Address =
209 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
210 + assertThat(ip6Address.toString(),
211 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
212 +
213 + ip6Address = new Ip6Address("::");
214 + assertThat(ip6Address.toString(), is("::"));
215 +
216 + ip6Address = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
217 + assertThat(ip6Address.toString(),
218 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
219 + }
220 +
221 + /**
222 + * Tests invalid class constructor for a null string.
223 + */
224 + @Test(expected = NullPointerException.class)
225 + public void testInvalidConstructorNullString() {
226 + String fromString = null;
227 + Ip6Address ip6Address = new Ip6Address(fromString);
228 + }
229 +
230 + /**
231 + * Tests invalid class constructor for an empty string.
232 + */
233 + @Test(expected = IllegalArgumentException.class)
234 + public void testInvalidConstructors() {
235 + // Check constructor for invalid ID: empty string
236 + Ip6Address ip6Address = new Ip6Address("");
237 + }
238 +
239 + /**
240 + * Tests returning the address as a byte array.
241 + */
242 + @Test
243 + public void testAddressToOctets() {
244 + final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22,
245 + 0x33, 0x33, 0x44, 0x44,
246 + 0x55, 0x55, 0x66, 0x66,
247 + 0x77, 0x77,
248 + (byte) 0x88, (byte) 0x88};
249 + Ip6Address ip6Address =
250 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
251 + assertThat(ip6Address.toOctets(), is(value1));
252 +
253 + final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00,
254 + 0x00, 0x00, 0x00, 0x00,
255 + 0x00, 0x00, 0x00, 0x00,
256 + 0x00, 0x00, 0x00, 0x00};
257 + ip6Address = new Ip6Address("::");
258 + assertThat(ip6Address.toOctets(), is(value2));
259 +
260 + final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
261 + (byte) 0xff, (byte) 0xff,
262 + (byte) 0xff, (byte) 0xff,
263 + (byte) 0xff, (byte) 0xff,
264 + (byte) 0xff, (byte) 0xff,
265 + (byte) 0xff, (byte) 0xff,
266 + (byte) 0xff, (byte) 0xff,
267 + (byte) 0xff, (byte) 0xff};
268 + ip6Address = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
269 + assertThat(ip6Address.toOctets(), is(value3));
270 + }
271 +
272 + /**
273 + * Tests making a mask prefix for a given prefix length.
274 + */
275 + @Test
276 + public void testMakeMaskPrefix() {
277 + Ip6Address ip6Address = Ip6Address.makeMaskPrefix(8);
278 + assertThat(ip6Address.toString(), is("ff00::"));
279 +
280 + ip6Address = Ip6Address.makeMaskPrefix(120);
281 + assertThat(ip6Address.toString(),
282 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"));
283 +
284 + ip6Address = Ip6Address.makeMaskPrefix(0);
285 + assertThat(ip6Address.toString(), is("::"));
286 +
287 + ip6Address = Ip6Address.makeMaskPrefix(128);
288 + assertThat(ip6Address.toString(),
289 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
290 +
291 + ip6Address = Ip6Address.makeMaskPrefix(64);
292 + assertThat(ip6Address.toString(), is("ffff:ffff:ffff:ffff::"));
293 + }
294 +
295 + /**
296 + * Tests making of a masked address.
297 + */
298 + @Test
299 + public void testMakeMaskedAddress() {
300 + Ip6Address ip6Address =
301 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885");
302 + Ip6Address ip6AddressMasked =
303 + Ip6Address.makeMaskedAddress(ip6Address, 8);
304 + assertThat(ip6AddressMasked.toString(), is("1100::"));
305 +
306 + ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 120);
307 + assertThat(ip6AddressMasked.toString(),
308 + is("1111:2222:3333:4444:5555:6666:7777:8800"));
309 +
310 + ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 0);
311 + assertThat(ip6AddressMasked.toString(), is("::"));
312 +
313 + ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 128);
314 + assertThat(ip6AddressMasked.toString(),
315 + is("1111:2222:3333:4444:5555:6666:7777:8885"));
316 +
317 + ip6AddressMasked = Ip6Address.makeMaskedAddress(ip6Address, 64);
318 + assertThat(ip6AddressMasked.toString(), is("1111:2222:3333:4444::"));
319 + }
320 +
321 + /**
322 + * Tests getting the value of an address.
323 + */
324 + @Test
325 + public void testGetValue() {
326 + Ip6Address ip6Address =
327 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
328 + assertThat(ip6Address.getValueHigh(), is(0x1111222233334444L));
329 + assertThat(ip6Address.getValueLow(), is(0x5555666677778888L));
330 +
331 + ip6Address = new Ip6Address(0, 0);
332 + assertThat(ip6Address.getValueHigh(), is(0L));
333 + assertThat(ip6Address.getValueLow(), is(0L));
334 +
335 + ip6Address = new Ip6Address(-1L, -1L);
336 + assertThat(ip6Address.getValueHigh(), is(-1L));
337 + assertThat(ip6Address.getValueLow(), is(-1L));
338 + }
339 +
340 + /**
341 + * Tests equality of {@link Ip6Address}.
342 + */
343 + @Test
344 + public void testEquality() {
345 + Ip6Address addr1 =
346 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
347 + Ip6Address addr2 =
348 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
349 + assertThat(addr1, is(addr2));
350 +
351 + addr1 = new Ip6Address("::");
352 + addr2 = new Ip6Address("::");
353 + assertThat(addr1, is(addr2));
354 +
355 + addr1 = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
356 + addr2 = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
357 + assertThat(addr1, is(addr2));
358 + }
359 +
360 + /**
361 + * Tests non-equality of {@link Ip6Address}.
362 + */
363 + @Test
364 + public void testNonEquality() {
365 + Ip6Address addr1 =
366 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
367 + Ip6Address addr2 =
368 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:888A");
369 + Ip6Address addr3 = new Ip6Address("::");
370 + Ip6Address addr4 =
371 + new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
372 + assertThat(addr1, is(not(addr2)));
373 + assertThat(addr3, is(not(addr2)));
374 + assertThat(addr4, is(not(addr2)));
375 + }
376 +
377 + /**
378 + * Tests comparison of {@link Ip6Address}.
379 + */
380 + @Test
381 + public void testComparison() {
382 + Ip6Address addr1 =
383 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
384 + Ip6Address addr2 =
385 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
386 + Ip6Address addr3 =
387 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8887");
388 + Ip6Address addr4 =
389 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8889");
390 + assertTrue(addr1.compareTo(addr2) == 0);
391 + assertTrue(addr1.compareTo(addr3) > 0);
392 + assertTrue(addr1.compareTo(addr4) < 0);
393 +
394 + addr1 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
395 + addr2 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
396 + addr3 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8887");
397 + addr4 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8889");
398 + assertTrue(addr1.compareTo(addr2) == 0);
399 + assertTrue(addr1.compareTo(addr3) > 0);
400 + assertTrue(addr1.compareTo(addr4) < 0);
401 +
402 + addr1 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
403 + addr2 = new Ip6Address("ffff:2222:3333:4444:5555:6666:7777:8888");
404 + addr3 = new Ip6Address("ffff:2222:3333:4443:5555:6666:7777:8888");
405 + addr4 = new Ip6Address("ffff:2222:3333:4445:5555:6666:7777:8888");
406 + assertTrue(addr1.compareTo(addr2) == 0);
407 + assertTrue(addr1.compareTo(addr3) > 0);
408 + assertTrue(addr1.compareTo(addr4) < 0);
409 + }
410 +
411 + /**
412 + * Tests object string representation.
413 + */
414 + @Test
415 + public void testToString() {
416 + Ip6Address ip6Address =
417 + new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8888");
418 + assertThat(ip6Address.toString(),
419 + is("1111:2222:3333:4444:5555:6666:7777:8888"));
420 +
421 + ip6Address = new Ip6Address("1111::8888");
422 + assertThat(ip6Address.toString(), is("1111::8888"));
423 +
424 + ip6Address = new Ip6Address("1111::");
425 + assertThat(ip6Address.toString(), is("1111::"));
426 +
427 + ip6Address = new Ip6Address("::8888");
428 + assertThat(ip6Address.toString(), is("::8888"));
429 +
430 + ip6Address = new Ip6Address("::");
431 + assertThat(ip6Address.toString(), is("::"));
432 +
433 + ip6Address = new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
434 + assertThat(ip6Address.toString(),
435 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
436 + }
437 +}
1 +package org.onlab.packet;
2 +
3 +import org.junit.Test;
4 +
5 +import static org.hamcrest.Matchers.equalTo;
6 +import static org.hamcrest.Matchers.is;
7 +import static org.hamcrest.Matchers.not;
8 +import static org.junit.Assert.assertThat;
9 +import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
10 +
11 +/**
12 + * Tests for class {@link Ip6Prefix}.
13 + */
14 +public class Ip6PrefixTest {
15 + /**
16 + * Tests the immutability of {@link Ip6Prefix}.
17 + */
18 + @Test
19 + public void testImmutable() {
20 + assertThatClassIsImmutable(Ip6Prefix.class);
21 + }
22 +
23 + /**
24 + * Tests default class constructor.
25 + */
26 + @Test
27 + public void testDefaultConstructor() {
28 + Ip6Prefix ip6prefix = new Ip6Prefix();
29 + assertThat(ip6prefix.toString(), is("::/0"));
30 + }
31 +
32 + /**
33 + * Tests valid class copy constructor.
34 + */
35 + @Test
36 + public void testCopyConstructor() {
37 + Ip6Prefix fromAddr = new Ip6Prefix("1100::/8");
38 + Ip6Prefix ip6prefix = new Ip6Prefix(fromAddr);
39 + assertThat(ip6prefix.toString(), is("1100::/8"));
40 +
41 + fromAddr = new Ip6Prefix("::/0");
42 + ip6prefix = new Ip6Prefix(fromAddr);
43 + assertThat(ip6prefix.toString(), is("::/0"));
44 +
45 + fromAddr =
46 + new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
47 + ip6prefix = new Ip6Prefix(fromAddr);
48 + assertThat(ip6prefix.toString(),
49 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
50 + }
51 +
52 + /**
53 + * Tests invalid class copy constructor for a null object to copy from.
54 + */
55 + @Test(expected = NullPointerException.class)
56 + public void testInvalidConstructorNullObject() {
57 + Ip6Prefix fromAddr = null;
58 + Ip6Prefix ip6prefix = new Ip6Prefix(fromAddr);
59 + }
60 +
61 + /**
62 + * Tests valid class constructor for an address and prefix length.
63 + */
64 + @Test
65 + public void testConstructorForAddressAndPrefixLength() {
66 + Ip6Prefix ip6prefix =
67 + new Ip6Prefix(new Ip6Address("1100::"), (short) 8);
68 + assertThat(ip6prefix.toString(), is("1100::/8"));
69 +
70 + ip6prefix =
71 + new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
72 + (short) 8);
73 + assertThat(ip6prefix.toString(), is("1100::/8"));
74 +
75 + ip6prefix =
76 + new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8800"),
77 + (short) 120);
78 + assertThat(ip6prefix.toString(),
79 + is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
80 +
81 + ip6prefix = new Ip6Prefix(new Ip6Address("::"), (short) 0);
82 + assertThat(ip6prefix.toString(), is("::/0"));
83 +
84 + ip6prefix =
85 + new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
86 + (short) 128);
87 + assertThat(ip6prefix.toString(),
88 + is("1111:2222:3333:4444:5555:6666:7777:8885/128"));
89 +
90 + ip6prefix =
91 + new Ip6Prefix(new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
92 + (short) 128);
93 + assertThat(ip6prefix.toString(),
94 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
95 +
96 + ip6prefix =
97 + new Ip6Prefix(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885"),
98 + (short) 64);
99 + assertThat(ip6prefix.toString(), is("1111:2222:3333:4444::/64"));
100 + }
101 +
102 + /**
103 + * Tests valid class constructor for a string.
104 + */
105 + @Test
106 + public void testConstructorForString() {
107 + Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
108 + assertThat(ip6prefix.toString(), is("1100::/8"));
109 +
110 + ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
111 + assertThat(ip6prefix.toString(), is("1100::/8"));
112 +
113 + ip6prefix =
114 + new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8800/120");
115 + assertThat(ip6prefix.toString(),
116 + is("1111:2222:3333:4444:5555:6666:7777:8800/120"));
117 +
118 + ip6prefix = new Ip6Prefix("::/0");
119 + assertThat(ip6prefix.toString(), is("::/0"));
120 +
121 + ip6prefix =
122 + new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/128");
123 + assertThat(ip6prefix.toString(),
124 + is("1111:2222:3333:4444:5555:6666:7777:8885/128"));
125 +
126 + ip6prefix = new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
127 + assertThat(ip6prefix.toString(),
128 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
129 +
130 + ip6prefix =
131 + new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/64");
132 + assertThat(ip6prefix.toString(), is("1111:2222:3333:4444::/64"));
133 + }
134 +
135 + /**
136 + * Tests invalid class constructor for a null string.
137 + */
138 + @Test(expected = NullPointerException.class)
139 + public void testInvalidConstructorNullString() {
140 + String fromString = null;
141 + Ip6Prefix ip6prefix = new Ip6Prefix(fromString);
142 + }
143 +
144 + /**
145 + * Tests invalid class constructor for an empty string.
146 + */
147 + @Test(expected = IllegalArgumentException.class)
148 + public void testInvalidConstructors() {
149 + // Check constructor for invalid ID: empty string
150 + Ip6Prefix ip6prefix = new Ip6Prefix("");
151 + }
152 +
153 + /**
154 + * Tests getting the value of an address.
155 + */
156 + @Test
157 + public void testGetValue() {
158 + Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
159 + assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("1100::")));
160 + assertThat(ip6prefix.getPrefixLen(), is((short) 8));
161 +
162 + ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
163 + assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("1100::")));
164 + assertThat(ip6prefix.getPrefixLen(), is((short) 8));
165 +
166 + ip6prefix =
167 + new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8800/120");
168 + assertThat(ip6prefix.getAddress(),
169 + equalTo(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8800")));
170 + assertThat(ip6prefix.getPrefixLen(), is((short) 120));
171 +
172 + ip6prefix = new Ip6Prefix("::/0");
173 + assertThat(ip6prefix.getAddress(), equalTo(new Ip6Address("::")));
174 + assertThat(ip6prefix.getPrefixLen(), is((short) 0));
175 +
176 + ip6prefix =
177 + new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/128");
178 + assertThat(ip6prefix.getAddress(),
179 + equalTo(new Ip6Address("1111:2222:3333:4444:5555:6666:7777:8885")));
180 + assertThat(ip6prefix.getPrefixLen(), is((short) 128));
181 +
182 + ip6prefix =
183 + new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
184 + assertThat(ip6prefix.getAddress(),
185 + equalTo(new Ip6Address("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff")));
186 + assertThat(ip6prefix.getPrefixLen(), is((short) 128));
187 +
188 + ip6prefix =
189 + new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/64");
190 + assertThat(ip6prefix.getAddress(),
191 + equalTo(new Ip6Address("1111:2222:3333:4444::")));
192 + assertThat(ip6prefix.getPrefixLen(), is((short) 64));
193 + }
194 +
195 + /**
196 + * Tests equality of {@link Ip6Address}.
197 + */
198 + @Test
199 + public void testEquality() {
200 + Ip6Prefix addr1net = new Ip6Prefix("1100::/8");
201 + Ip6Prefix addr2net = new Ip6Prefix("1100::/8");
202 + assertThat(addr1net, is(addr2net));
203 +
204 + addr1net = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
205 + addr2net = new Ip6Prefix("1100::/8");
206 + assertThat(addr1net, is(addr2net));
207 +
208 + addr1net = new Ip6Prefix("::/0");
209 + addr2net = new Ip6Prefix("::/0");
210 + assertThat(addr1net, is(addr2net));
211 +
212 + addr1net =
213 + new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
214 + addr2net =
215 + new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
216 + assertThat(addr1net, is(addr2net));
217 + }
218 +
219 + /**
220 + * Tests non-equality of {@link Ip6Address}.
221 + */
222 + @Test
223 + public void testNonEquality() {
224 + Ip6Prefix addr1net = new Ip6Prefix("1100::/8");
225 + Ip6Prefix addr2net = new Ip6Prefix("1200::/8");
226 + Ip6Prefix addr3net = new Ip6Prefix("1200::/12");
227 + Ip6Prefix addr4net = new Ip6Prefix("::/0");
228 + Ip6Prefix addr5net =
229 + new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
230 + assertThat(addr1net, is(not(addr2net)));
231 + assertThat(addr3net, is(not(addr2net)));
232 + assertThat(addr4net, is(not(addr2net)));
233 + assertThat(addr5net, is(not(addr2net)));
234 + }
235 +
236 + /**
237 + * Tests object string representation.
238 + */
239 + @Test
240 + public void testToString() {
241 + Ip6Prefix ip6prefix = new Ip6Prefix("1100::/8");
242 + assertThat(ip6prefix.toString(), is("1100::/8"));
243 +
244 + ip6prefix = new Ip6Prefix("1111:2222:3333:4444:5555:6666:7777:8885/8");
245 + assertThat(ip6prefix.toString(), is("1100::/8"));
246 +
247 + ip6prefix = new Ip6Prefix("::/0");
248 + assertThat(ip6prefix.toString(), is("::/0"));
249 +
250 + ip6prefix =
251 + new Ip6Prefix("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128");
252 + assertThat(ip6prefix.toString(),
253 + is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128"));
254 + }
255 +}