Merge branch 'master' of ssh://gerrit.onlab.us:29418/onos-next
diff --git a/apps/optical/src/main/java/org/onlab/onos/optical/cfg/OpticalConfigProvider.java b/apps/optical/src/main/java/org/onlab/onos/optical/cfg/OpticalConfigProvider.java
index 5c9de15..4b9bc9f 100644
--- a/apps/optical/src/main/java/org/onlab/onos/optical/cfg/OpticalConfigProvider.java
+++ b/apps/optical/src/main/java/org/onlab/onos/optical/cfg/OpticalConfigProvider.java
@@ -368,12 +368,12 @@
}
@Override
- public void roleChanged(Device device, MastershipRole newRole) {
+ public void roleChanged(DeviceId device, MastershipRole newRole) {
// TODO Auto-generated method stub.
}
@Override
- public boolean isReachable(Device device) {
+ public boolean isReachable(DeviceId device) {
return false;
}
}
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java
index af67f1a..901ac90 100644
--- a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSession.java
@@ -246,11 +246,13 @@
InetAddress inetAddr;
if (localAddress instanceof InetSocketAddress) {
inetAddr = ((InetSocketAddress) localAddress).getAddress();
- localIp4Address = IpAddress.valueOf(inetAddr.getAddress());
+ localIp4Address = IpAddress.valueOf(IpAddress.Version.INET,
+ inetAddr.getAddress());
}
if (remoteAddress instanceof InetSocketAddress) {
inetAddr = ((InetSocketAddress) remoteAddress).getAddress();
- remoteIp4Address = IpAddress.valueOf(inetAddr.getAddress());
+ remoteIp4Address = IpAddress.valueOf(IpAddress.Version.INET,
+ inetAddr.getAddress());
}
log.debug("BGP Session Connected from {} on {}",
diff --git a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java
index 1b5dfb5..247c95f 100644
--- a/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java
+++ b/apps/sdnip/src/main/java/org/onlab/onos/sdnip/bgp/BgpSessionManager.java
@@ -105,7 +105,8 @@
if (bgpSession.getLocalAddress() instanceof InetSocketAddress) {
InetAddress inetAddr =
((InetSocketAddress) bgpSession.getLocalAddress()).getAddress();
- IpAddress ip4Address = IpAddress.valueOf(inetAddr.getAddress());
+ IpAddress ip4Address = IpAddress.valueOf(IpAddress.Version.INET,
+ inetAddr.getAddress());
updateMyBgpId(ip4Address);
}
return true;
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentCommand.java
index e1ede9f..ed98c7e 100644
--- a/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/net/AddPointToPointIntentCommand.java
@@ -74,7 +74,7 @@
* @param deviceString string representing the device/port
* @return port number as a string, empty string if the port is not found
*/
- private String getPortNumber(String deviceString) {
+ public static String getPortNumber(String deviceString) {
int slash = deviceString.indexOf('/');
if (slash <= 0) {
return "";
@@ -88,7 +88,7 @@
* @param deviceString string representing the device/port
* @return device ID string
*/
- private String getDeviceId(String deviceString) {
+ public static String getDeviceId(String deviceString) {
int slash = deviceString.indexOf('/');
if (slash <= 0) {
return "";
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
index 88548a1..f5c65e5 100644
--- a/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
+++ b/cli/src/main/java/org/onlab/onos/cli/net/IntentsListCommand.java
@@ -20,6 +20,7 @@
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
import org.onlab.onos.cli.AbstractShellCommand;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Link;
@@ -44,6 +45,11 @@
description = "Lists the inventory of intents and their states")
public class IntentsListCommand extends AbstractShellCommand {
+ @Option(name = "-i", aliases = "--installable", description = "Output Installable Intents",
+ required = false, multiValued = false)
+ private boolean showInstallable = false;
+
+
@Override
protected void execute() {
IntentService service = get(IntentService.class);
@@ -93,7 +99,7 @@
}
List<Intent> installable = service.getInstallableIntents(intent.id());
- if (installable != null && !installable.isEmpty()) {
+ if (showInstallable && installable != null && !installable.isEmpty()) {
print(" installable=%s", installable);
}
}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/ResourceAllocationsCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/ResourceAllocationsCommand.java
new file mode 100644
index 0000000..b91ed3e
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/ResourceAllocationsCommand.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.onos.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.cli.AbstractShellCommand;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.link.LinkService;
+import org.onlab.onos.net.resource.LinkResourceAllocations;
+import org.onlab.onos.net.resource.LinkResourceService;
+
+import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getDeviceId;
+import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getPortNumber;
+import static org.onlab.onos.net.DeviceId.deviceId;
+import static org.onlab.onos.net.PortNumber.portNumber;
+
+/**
+ * Lists allocations by link.
+ */
+@Command(scope = "onos", name = "resource-allocations",
+ description = "Lists allocations by link")
+public class ResourceAllocationsCommand extends AbstractShellCommand {
+
+ private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
+ private static final String COMPACT = "%s/%s-%s/%s";
+
+ @Argument(index = 0, name = "srcString", description = "Link source",
+ required = false, multiValued = false)
+ String srcString = null;
+ @Argument(index = 1, name = "dstString", description = "Link destination",
+ required = false, multiValued = false)
+ String dstString = null;
+
+ @Override
+ protected void execute() {
+ LinkResourceService resourceService = get(LinkResourceService.class);
+ LinkService linkService = get(LinkService.class);
+
+ Iterable<LinkResourceAllocations> itr = null;
+ try {
+ DeviceId ingressDeviceId = deviceId(getDeviceId(srcString));
+ PortNumber ingressPortNumber = portNumber(getPortNumber(srcString));
+ ConnectPoint src = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ DeviceId egressDeviceId = deviceId(getDeviceId(dstString));
+ PortNumber egressPortNumber = portNumber(getPortNumber(dstString));
+ ConnectPoint dst = new ConnectPoint(egressDeviceId, egressPortNumber);
+
+ Link link = linkService.getLink(src, dst);
+
+ itr = resourceService.getAllocations(link);
+
+ for (LinkResourceAllocations allocation : itr) {
+ print("%s", allocation.getResourceAllocation(link));
+ }
+
+ } catch (Exception e) {
+ print("----- Displaying all resource allocations -----", e.getMessage());
+ itr = resourceService.getAllocations();
+ for (LinkResourceAllocations allocation : itr) {
+ print("%s", allocation);
+ }
+
+ }
+ }
+}
diff --git a/cli/src/main/java/org/onlab/onos/cli/net/ResourceAvailableCommand.java b/cli/src/main/java/org/onlab/onos/cli/net/ResourceAvailableCommand.java
new file mode 100644
index 0000000..e67990d
--- /dev/null
+++ b/cli/src/main/java/org/onlab/onos/cli/net/ResourceAvailableCommand.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.onos.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.onos.cli.AbstractShellCommand;
+import org.onlab.onos.net.ConnectPoint;
+import org.onlab.onos.net.DeviceId;
+import org.onlab.onos.net.Link;
+import org.onlab.onos.net.PortNumber;
+import org.onlab.onos.net.link.LinkService;
+import org.onlab.onos.net.resource.LinkResourceService;
+import org.onlab.onos.net.resource.ResourceRequest;
+
+import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getDeviceId;
+import static org.onlab.onos.cli.net.AddPointToPointIntentCommand.getPortNumber;
+import static org.onlab.onos.net.DeviceId.deviceId;
+import static org.onlab.onos.net.PortNumber.portNumber;
+
+/**
+ * Lists allocations by link.
+ */
+@Command(scope = "onos", name = "resource-available",
+ description = "Lists available resources by link")
+public class ResourceAvailableCommand extends AbstractShellCommand {
+
+ private static final String FMT = "src=%s/%s, dst=%s/%s, type=%s%s";
+ private static final String COMPACT = "%s/%s-%s/%s";
+
+ @Argument(index = 0, name = "srcString", description = "Link source",
+ required = false, multiValued = false)
+ String srcString = null;
+ @Argument(index = 1, name = "dstString", description = "Link destination",
+ required = false, multiValued = false)
+ String dstString = null;
+
+ @Override
+ protected void execute() {
+ LinkResourceService resourceService = get(LinkResourceService.class);
+ LinkService linkService = get(LinkService.class);
+
+ Iterable<ResourceRequest> itr = null;
+ try {
+ DeviceId ingressDeviceId = deviceId(getDeviceId(srcString));
+ PortNumber ingressPortNumber = portNumber(getPortNumber(srcString));
+ ConnectPoint src = new ConnectPoint(ingressDeviceId, ingressPortNumber);
+
+ DeviceId egressDeviceId = deviceId(getDeviceId(dstString));
+ PortNumber egressPortNumber = portNumber(getPortNumber(dstString));
+ ConnectPoint dst = new ConnectPoint(egressDeviceId, egressPortNumber);
+
+ Link link = linkService.getLink(src, dst);
+
+ itr = resourceService.getAvailableResources(link);
+
+ int lambdaCount = 0;
+ for (ResourceRequest req : itr) {
+ switch (req.type()) {
+ case LAMBDA:
+ lambdaCount++;
+ break;
+ case BANDWIDTH:
+ print("%s", req);
+ break;
+ default:
+ break;
+ }
+ }
+ if (lambdaCount > 0) {
+ print("Number of available lambdas: %d", lambdaCount);
+ }
+
+ } catch (Exception e) {
+ print("Invalid link", e.getMessage());
+ }
+ }
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index bbccb94..78b1dc1 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -158,7 +158,22 @@
<null/>
</completers>
</command>
-
+ <command>
+ <action class="org.onlab.onos.cli.net.ResourceAllocationsCommand"/>
+ <completers>
+ <ref component-id="connectPointCompleter"/>
+ <ref component-id="connectPointCompleter"/>
+ <null/>
+ </completers>
+ </command>
+ <command>
+ <action class="org.onlab.onos.cli.net.ResourceAvailableCommand"/>
+ <completers>
+ <ref component-id="connectPointCompleter"/>
+ <ref component-id="connectPointCompleter"/>
+ <null/>
+ </completers>
+ </command>
<command>
<action class="org.onlab.onos.cli.net.ClustersListCommand"/>
</command>
diff --git a/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java b/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
index dafa273..5447545 100644
--- a/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/mastership/MastershipEvent.java
@@ -40,7 +40,9 @@
MASTER_CHANGED,
/**
- * Signifies that the list of backup nodes has changed.
+ * Signifies that the list of backup nodes has changed. If
+ * the change in the backups list is accompanied by a change in
+ * master, the event is subsumed by MASTER_CHANGED.
*/
BACKUPS_CHANGED
}
@@ -49,9 +51,9 @@
* Creates an event of a given type and for the specified device,
* role information, and the current time.
*
- * @param type device event type
+ * @param type mastership event type
* @param device event device subject
- * @param info mastership role information subject
+ * @param info mastership role information
*/
public MastershipEvent(Type type, DeviceId device, RoleInfo info) {
super(type, device);
diff --git a/core/api/src/main/java/org/onlab/onos/net/NetworkResource.java b/core/api/src/main/java/org/onlab/onos/net/NetworkResource.java
index 65bb4e8..faf3241 100644
--- a/core/api/src/main/java/org/onlab/onos/net/NetworkResource.java
+++ b/core/api/src/main/java/org/onlab/onos/net/NetworkResource.java
@@ -16,7 +16,7 @@
package org.onlab.onos.net;
/**
- * Representation of a network resource.
+ * Representation of a network resource, e.g. a link, lambda, MPLS tag.
*/
public interface NetworkResource {
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/Tunnel.java b/core/api/src/main/java/org/onlab/onos/net/Tunnel.java
new file mode 100644
index 0000000..d5fad6c
--- /dev/null
+++ b/core/api/src/main/java/org/onlab/onos/net/Tunnel.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.onos.net;
+
+/**
+ * Abstraction of a generalized network tunnel.
+ */
+public interface Tunnel extends Link {
+
+ /**
+ * Tunnel technology type.
+ */
+ enum Type {
+ MPLS, VLAN, VXLAN, GRE, OPTICAL
+ }
+
+ /**
+ * Network resource backing the tunnel, e.g. lambda, VLAN id, MPLS tag.
+ *
+ * @return backing resource
+ */
+ NetworkResource resource();
+
+}
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
index 72dc03c..011f2a8 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockProviderService.java
@@ -25,6 +25,14 @@
public interface DeviceClockProviderService {
/**
+ * Checks if this service can issue Timestamp for specified device.
+ *
+ * @param deviceId device identifier.
+ * @return true if timestamp can be issued for specified device
+ */
+ public boolean isTimestampAvailable(DeviceId deviceId);
+
+ /**
* Updates the mastership term for the specified deviceId.
*
* @param deviceId device identifier.
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
index 2104d2e..2214cfd 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceClockService.java
@@ -24,7 +24,16 @@
public interface DeviceClockService {
/**
+ * Checks if this service can issue Timestamp for specified device.
+ *
+ * @param deviceId device identifier.
+ * @return true if timestamp can be issued for specified device
+ */
+ public boolean isTimestampAvailable(DeviceId deviceId);
+
+ /**
* Returns a new timestamp for the specified deviceId.
+ *
* @param deviceId device identifier.
* @return timestamp.
*/
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
index 8411b09..8dd405a 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceProvider.java
@@ -16,6 +16,7 @@
package org.onlab.onos.net.device;
import org.onlab.onos.net.Device;
+import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.provider.Provider;
@@ -42,16 +43,16 @@
* Notifies the provider of a mastership role change for the specified
* device as decided by the core.
*
- * @param device affected device
+ * @param deviceId device identifier
* @param newRole newly determined mastership role
*/
- void roleChanged(Device device, MastershipRole newRole);
+ void roleChanged(DeviceId deviceId, MastershipRole newRole);
/**
* Checks the reachability (connectivity) of a device from this provider.
*
- * @param device device to check
+ * @param deviceId device identifier
* @return true if reachable, false otherwise
*/
- boolean isReachable(Device device);
+ boolean isReachable(DeviceId deviceId);
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java b/core/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
index f1667db..6f71495 100644
--- a/core/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
+++ b/core/api/src/main/java/org/onlab/onos/net/device/DeviceProviderService.java
@@ -61,12 +61,12 @@
void portStatusChanged(DeviceId deviceId, PortDescription portDescription);
/**
- * Notifies the core about the providers inability to assert the specified
- * mastership role on the device.
+ * Notifies the core about the result of a RoleRequest sent to a device.
*
* @param deviceId identity of the device
- * @param role mastership role that was asserted but failed
+ * @param requested mastership role that was requested by the node
+ * @param replied mastership role the switch accepted
*/
- void unableToAssertRole(DeviceId deviceId, MastershipRole role);
+ void receivedRoleReply(DeviceId deviceId, MastershipRole requested, MastershipRole response);
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchEvent.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchEvent.java
index d5c762d..1dbf8bd 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchEvent.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchEvent.java
@@ -27,11 +27,14 @@
*/
public enum Type {
+ // Request has been forwarded to MASTER Node
/**
* Signifies that a batch operation has been initiated.
*/
BATCH_OPERATION_REQUESTED,
+ // MASTER Node has pushed the batch down to the Device
+ // (e.g., Received barrier reply)
/**
* Signifies that a batch operation has completed.
*/
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchRequest.java b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchRequest.java
index 4a2bcf9..f75c663 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/FlowRuleBatchRequest.java
@@ -25,29 +25,29 @@
public class FlowRuleBatchRequest {
private final int batchId;
- private final List<FlowEntry> toAdd;
- private final List<FlowEntry> toRemove;
+ private final List<FlowRule> toAdd;
+ private final List<FlowRule> toRemove;
- public FlowRuleBatchRequest(int batchId, List<? extends FlowEntry> toAdd, List<? extends FlowEntry> toRemove) {
+ public FlowRuleBatchRequest(int batchId, List<? extends FlowRule> toAdd, List<? extends FlowRule> toRemove) {
this.batchId = batchId;
this.toAdd = Collections.unmodifiableList(toAdd);
this.toRemove = Collections.unmodifiableList(toRemove);
}
- public List<FlowEntry> toAdd() {
+ public List<FlowRule> toAdd() {
return toAdd;
}
- public List<FlowEntry> toRemove() {
+ public List<FlowRule> toRemove() {
return toRemove;
}
public FlowRuleBatchOperation asBatchOperation() {
List<FlowRuleBatchEntry> entries = Lists.newArrayList();
- for (FlowEntry e : toAdd) {
+ for (FlowRule e : toAdd) {
entries.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, e));
}
- for (FlowEntry e : toRemove) {
+ for (FlowRule e : toRemove) {
entries.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, e));
}
return new FlowRuleBatchOperation(entries);
diff --git a/core/api/src/main/java/org/onlab/onos/net/flow/instructions/Instructions.java b/core/api/src/main/java/org/onlab/onos/net/flow/instructions/Instructions.java
index 0bdff77..0e77f4a 100644
--- a/core/api/src/main/java/org/onlab/onos/net/flow/instructions/Instructions.java
+++ b/core/api/src/main/java/org/onlab/onos/net/flow/instructions/Instructions.java
@@ -200,7 +200,7 @@
}
if (obj instanceof OutputInstruction) {
OutputInstruction that = (OutputInstruction) obj;
- Objects.equals(port, that.port);
+ return Objects.equals(port, that.port);
}
return false;
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceAllocation.java b/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceAllocation.java
index e540db2..62051ad 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceAllocation.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceAllocation.java
@@ -15,6 +15,8 @@
*/
package org.onlab.onos.net.resource;
+import com.google.common.base.MoreObjects;
+
/**
* Representation of allocated bandwidth resource.
*/
@@ -35,4 +37,11 @@
public BandwidthResourceAllocation(Bandwidth bandwidth) {
super(bandwidth);
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("bandwidth", bandwidth())
+ .toString();
+ }
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java b/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java
index cced791..52b4112 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/BandwidthResourceRequest.java
@@ -15,6 +15,8 @@
*/
package org.onlab.onos.net.resource;
+import com.google.common.base.MoreObjects;
+
/**
* Representation of a request for bandwidth resource.
*/
@@ -53,4 +55,11 @@
public ResourceType type() {
return ResourceType.BANDWIDTH;
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("bandwidth", bandwidth)
+ .toString();
+ }
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java
index 1c81f1f..9032cc4 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceAllocation.java
@@ -15,6 +15,8 @@
*/
package org.onlab.onos.net.resource;
+import com.google.common.base.MoreObjects;
+
import java.util.Objects;
/**
@@ -64,4 +66,11 @@
final LambdaResourceAllocation other = (LambdaResourceAllocation) obj;
return Objects.equals(this.lambda, other.lambda);
}
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
+ .toString();
+ }
}
diff --git a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java
index 382758a..dab8793 100644
--- a/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java
+++ b/core/api/src/main/java/org/onlab/onos/net/resource/LambdaResourceRequest.java
@@ -15,6 +15,8 @@
*/
package org.onlab.onos.net.resource;
+import com.google.common.base.MoreObjects;
+
/**
* Representation of a request for lambda resource.
*/
@@ -25,4 +27,9 @@
return ResourceType.LAMBDA;
}
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .toString();
+ }
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
index dfff752..68665e4 100644
--- a/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/device/impl/DeviceManager.java
@@ -17,6 +17,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.onos.net.device.DeviceEvent.Type.DEVICE_MASTERSHIP_CHANGED;
+import static org.onlab.onos.net.MastershipRole.*;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.List;
@@ -29,7 +30,6 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.cluster.ClusterService;
import org.onlab.onos.cluster.NodeId;
-import org.onlab.onos.cluster.RoleInfo;
import org.onlab.onos.event.AbstractListenerRegistry;
import org.onlab.onos.event.EventDeliveryService;
import org.onlab.onos.mastership.MastershipEvent;
@@ -59,8 +59,6 @@
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
-import com.google.common.collect.HashMultimap;
-
/**
* Provides implementation of the device SB & NB APIs.
*/
@@ -160,39 +158,15 @@
return store.isAvailable(deviceId);
}
- // Applies the specified role to the device; ignores NONE
- private void applyRole(DeviceId deviceId, MastershipRole newRole) {
- if (newRole.equals(MastershipRole.NONE)) {
- return;
- }
-
- Device device = store.getDevice(deviceId);
- // FIXME: Device might not be there yet. (eventual consistent)
- if (device == null) {
- return;
- }
-
- DeviceProvider provider = getProvider(device.providerId());
- if (provider != null) {
- provider.roleChanged(device, newRole);
- // only trigger event when request was sent to provider
- // TODO: consider removing this from Device event type?
- post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device));
-
- if (newRole.equals(MastershipRole.MASTER)) {
- provider.triggerProbe(device);
- }
- }
- }
-
// Check a device for control channel connectivity.
- private boolean isReachable(Device device) {
- // FIXME: Device might not be there yet. (eventual consistent)
- if (device == null) {
+ private boolean isReachable(DeviceId deviceId) {
+ DeviceProvider provider = getProvider(deviceId);
+ if (provider != null) {
+ return provider.isReachable(deviceId);
+ } else {
+ log.error("Provider not found for {}", deviceId);
return false;
}
- DeviceProvider provider = getProvider(device.providerId());
- return provider.isReachable(device);
}
@Override
@@ -234,6 +208,32 @@
super(provider);
}
+ /**
+ * Apply role in reaction to provider event.
+ *
+ * @param deviceId device identifier
+ * @param newRole new role to apply to the device
+ * @return true if the request was sent to provider
+ */
+ private boolean applyRole(DeviceId deviceId, MastershipRole newRole) {
+
+ if (newRole.equals(MastershipRole.NONE)) {
+ //no-op
+ return true;
+ }
+
+ DeviceProvider provider = provider();
+ if (provider == null) {
+ log.warn("Provider for {} was not found. Cannot apply role {}", deviceId, newRole);
+ return false;
+ }
+ provider.roleChanged(deviceId, newRole);
+ // not triggering probe when triggered by provider service event
+
+ return true;
+ }
+
+
@Override
public void deviceConnected(DeviceId deviceId,
DeviceDescription deviceDescription) {
@@ -242,26 +242,19 @@
checkValidity();
log.info("Device {} connected", deviceId);
- // check my Role
- MastershipRole role = mastershipService.requestRoleFor(deviceId);
- if (role != MastershipRole.MASTER) {
- // TODO: Do we need to explicitly tell the Provider that
- // this instance is no longer the MASTER? probably not
-// Device device = getDevice(deviceId);
-// if (device != null) {
-// // FIXME roleChanged should take DeviceId instead of Device
-// provider().roleChanged(device, role);
-// }
- return;
- }
- MastershipTerm term = termService.getMastershipTerm(deviceId);
-
final NodeId myNodeId = clusterService.getLocalNode().id();
+
+ // check my Role
+ mastershipService.requestRoleFor(deviceId);
+ final MastershipTerm term = termService.getMastershipTerm(deviceId);
if (!myNodeId.equals(term.master())) {
- // lost mastership after requestRole told this instance was MASTER.
- log.info("lost mastership before getting term info.");
+ log.info("Role of this node is STANDBY for {}", deviceId);
+ // TODO: Do we need to explicitly tell the Provider that
+ // this instance is not the MASTER
+ applyRole(deviceId, MastershipRole.STANDBY);
return;
}
+ log.info("Role of this node is MASTER for {}", deviceId);
// tell clock provider if this instance is the master
deviceClockProviderService.setMastershipTerm(deviceId, term);
@@ -269,24 +262,15 @@
DeviceEvent event = store.createOrUpdateDevice(provider().id(),
deviceId, deviceDescription);
+ applyRole(deviceId, MastershipRole.MASTER);
+
// If there was a change of any kind, tell the provider
// that this instance is the master.
- // Note: event can be null, if mastership was lost between
- // roleRequest and store update calls.
if (event != null) {
- // TODO: Check switch reconnected case. Is it assured that
- // event will never be null?
- // Could there be a situation MastershipService told this
- // instance is the new Master, but
- // event returned from the store is null?
-
- // FIXME: 1st argument should be deviceId, to allow setting
- // certain roles even if the store returned null.
- log.info("event: {} {}", event.type(), event);
- provider().roleChanged(event.subject(), role);
+ log.trace("event: {} {}", event.type(), event);
post(event);
} else {
- log.info("No event to publish");
+ post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, store.getDevice(deviceId)));
}
}
@@ -295,6 +279,7 @@
checkNotNull(deviceId, DEVICE_ID_NULL);
checkValidity();
+ log.info("Device {} disconnected from this node", deviceId);
DeviceEvent event = null;
try {
@@ -318,18 +303,18 @@
final NodeId myNodeId = clusterService.getLocalNode().id();
// TODO: Move this type of check inside device clock manager, etc.
if (myNodeId.equals(term.master())) {
- log.info("Marking {} offline", deviceId);
+ log.info("Retry marking {} offline", deviceId);
deviceClockProviderService.setMastershipTerm(deviceId, term);
event = store.markOffline(deviceId);
} else {
- log.error("Failed again marking {} offline. {}", deviceId, role);
+ log.info("Failed again marking {} offline. {}", deviceId, role);
}
} finally {
//relinquish master role and ability to be backup.
mastershipService.relinquishMastership(deviceId);
if (event != null) {
- log.info("Device {} disconnected", deviceId);
+ log.info("Device {} disconnected from cluster", deviceId);
post(event);
}
}
@@ -343,6 +328,13 @@
"Port descriptions list cannot be null");
checkValidity();
+ if (!deviceClockProviderService.isTimestampAvailable(deviceId)) {
+ // Never been a master for this device
+ // any update will be ignored.
+ log.trace("Ignoring {} port updates on standby node. {}", deviceId, portDescriptions);
+ return;
+ }
+
List<DeviceEvent> events = store.updatePorts(this.provider().id(),
deviceId, portDescriptions);
for (DeviceEvent event : events) {
@@ -357,6 +349,13 @@
checkNotNull(portDescription, PORT_DESCRIPTION_NULL);
checkValidity();
+ if (!deviceClockProviderService.isTimestampAvailable(deviceId)) {
+ // Never been a master for this device
+ // any update will be ignored.
+ log.trace("Ignoring {} port update on standby node. {}", deviceId, portDescription);
+ return;
+ }
+
final DeviceEvent event = store.updatePortStatus(this.provider().id(),
deviceId, portDescription);
if (event != null) {
@@ -367,16 +366,48 @@
}
@Override
- public void unableToAssertRole(DeviceId deviceId, MastershipRole role) {
+ public void receivedRoleReply(
+ DeviceId deviceId, MastershipRole requested, MastershipRole response) {
+ // Several things can happen here:
+ // 1. request and response match
+ // 2. request and response don't match
+ // 3. MastershipRole and requested match (and 1 or 2 are true)
+ // 4. MastershipRole and requested don't match (and 1 or 2 are true)
+ //
+ // 2, 4, and 3 with case 2 are failure modes.
+
// FIXME: implement response to this notification
- log.warn("Failed to assert role [{}] onto Device {}", role,
- deviceId);
- if (role == MastershipRole.MASTER) {
+
+ log.info("got reply to a role request for {}: asked for {}, and got {}",
+ deviceId, requested, response);
+
+ if (requested == null && response == null) {
+ // something was off with DeviceProvider, maybe check channel too?
+ log.warn("Failed to assert role [{}] onto Device {}", requested, deviceId);
mastershipService.relinquishMastership(deviceId);
- // TODO: Shouldn't we be triggering event?
- //final Device device = getDevice(deviceId);
- //post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device));
+ return;
}
+
+ if (requested.equals(response)) {
+ if (requested.equals(mastershipService.getLocalRole(deviceId))) {
+
+ return;
+ } else {
+ return;
+ // FIXME roleManager got the device to comply, but doesn't agree with
+ // the store; use the store's view, then try to reassert.
+ }
+ } else {
+ // we didn't get back what we asked for. Reelect someone else.
+ log.warn("Failed to assert role [{}] onto Device {}", response, deviceId);
+ if (response == MastershipRole.MASTER) {
+ mastershipService.relinquishMastership(deviceId);
+ // TODO: Shouldn't we be triggering event?
+ //final Device device = getDevice(deviceId);
+ //post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device));
+ }
+ }
+
}
}
@@ -390,118 +421,134 @@
// Intercepts mastership events
private class InternalMastershipListener implements MastershipListener {
- // random cache size
- private final int cacheSize = 5;
- // temporarily stores term number + events to check for duplicates. A hack.
- private HashMultimap<Integer, RoleInfo> eventCache =
- HashMultimap.create();
+ // Applies the specified role to the device; ignores NONE
+ /**
+ * Apply role in reaction to mastership event.
+ *
+ * @param deviceId device identifier
+ * @param newRole new role to apply to the device
+ * @return true if the request was sent to provider
+ */
+ private boolean applyRole(DeviceId deviceId, MastershipRole newRole) {
+ if (newRole.equals(MastershipRole.NONE)) {
+ //no-op
+ return true;
+ }
+
+ Device device = store.getDevice(deviceId);
+ // FIXME: Device might not be there yet. (eventual consistent)
+ // FIXME relinquish role
+ if (device == null) {
+ log.warn("{} was not there. Cannot apply role {}", deviceId, newRole);
+ return false;
+ }
+
+ DeviceProvider provider = getProvider(device.providerId());
+ if (provider == null) {
+ log.warn("Provider for {} was not found. Cannot apply role {}", deviceId, newRole);
+ return false;
+ }
+ provider.roleChanged(deviceId, newRole);
+
+ if (newRole.equals(MastershipRole.MASTER)) {
+ // only trigger event when request was sent to provider
+ // TODO: consider removing this from Device event type?
+ post(new DeviceEvent(DEVICE_MASTERSHIP_CHANGED, device));
+
+ provider.triggerProbe(device);
+ }
+ return true;
+ }
@Override
public void event(MastershipEvent event) {
+
+ if (event.type() != MastershipEvent.Type.MASTER_CHANGED) {
+ // Don't care if backup list changed.
+ return;
+ }
+
final DeviceId did = event.subject();
final NodeId myNodeId = clusterService.getLocalNode().id();
+ // myRole suggested by MastershipService
+ MastershipRole myNextRole;
if (myNodeId.equals(event.roleInfo().master())) {
+ // confirm latest info
MastershipTerm term = termService.getMastershipTerm(did);
-
- // TODO duplicate suppression should probably occur in the MastershipManager
- // itself, so listeners that can't deal with duplicates don't have to
- // so this check themselves.
-// if (checkDuplicate(event.roleInfo(), term.termNumber())) {
-// return;
-// }
-
- if (!myNodeId.equals(term.master())) {
- // something went wrong in consistency, let go
- log.warn("Mastership has changed after this event."
- + "Term Service suggests {} for {}", term, did);
- // FIXME: Is it possible to let go of MASTER role
- // but remain on STANDBY list?
- mastershipService.relinquishMastership(did);
- applyRole(did, MastershipRole.STANDBY);
- return;
- }
-
- // only set the new term if I am the master
- deviceClockProviderService.setMastershipTerm(did, term);
-
- // if the device is null here, we are the first master to claim the
- // device. No worries, the DeviceManager will create one soon.
- Device device = getDevice(did);
- if ((device != null) && !isAvailable(did)) {
- if (!isReachable(device)) {
- log.warn("Device {} has disconnected after this event", did);
- mastershipService.relinquishMastership(did);
- return;
- }
- //flag the device as online. Is there a better way to do this?
- DeviceEvent devEvent =
- store.createOrUpdateDevice(device.providerId(), did,
- new DefaultDeviceDescription(
- did.uri(), device.type(), device.manufacturer(),
- device.hwVersion(), device.swVersion(),
- device.serialNumber(), device.chassisId()));
- post(devEvent);
- }
- applyRole(did, MastershipRole.MASTER);
- } else if (event.roleInfo().backups().contains(myNodeId)) {
- if (!isReachable(getDevice(did))) {
- log.warn("Device {} has disconnected after this event", did);
- mastershipService.relinquishMastership(did);
- return;
- }
- applyRole(did, MastershipRole.STANDBY);
- } else {
- // Event suggests that this Node has no connection to this Device
- // confirm.
- final Device device = getDevice(did);
- if (!isReachable(device)) {
- // not connection to device, as expected
- return;
- }
- // connection seems to exist
- log.info("Detected mastership info mismatch, requesting Role");
- mastershipService.requestRoleFor(did);
- final MastershipTerm term = termService.getMastershipTerm(did);
- if (myNodeId.equals(term.master())) {
- // became MASTER
- // TODO: consider slicing out method for applying MASTER role
+ final boolean iHaveControl = myNodeId.equals(term.master());
+ if (iHaveControl) {
deviceClockProviderService.setMastershipTerm(did, term);
-
- //flag the device as online. Is there a better way to do this?
- DeviceEvent devEvent =
- store.createOrUpdateDevice(device.providerId(), did,
- new DefaultDeviceDescription(
- did.uri(), device.type(), device.manufacturer(),
- device.hwVersion(), device.swVersion(),
- device.serialNumber(), device.chassisId()));
- applyRole(did, MastershipRole.MASTER);
- post(devEvent);
+ myNextRole = MASTER;
} else {
- applyRole(did, MastershipRole.STANDBY);
+ myNextRole = STANDBY;
+ }
+ } else if (event.roleInfo().backups().contains(myNodeId)) {
+ myNextRole = STANDBY;
+ } else {
+ myNextRole = NONE;
+ }
+
+
+ final boolean isReachable = isReachable(did);
+ if (!isReachable) {
+ // device is not connected to this node
+ if (myNextRole != NONE) {
+ log.warn("Node was instructed to be {} role for {}, "
+ + "but this node cannot reach the device. "
+ + "Relinquishing role. ",
+ myNextRole, did);
+ mastershipService.relinquishMastership(did);
+ // FIXME disconnect?
+ }
+ return;
+ }
+
+ // device is connected to this node:
+
+ if (myNextRole == NONE) {
+ mastershipService.requestRoleFor(did);
+ MastershipTerm term = termService.getMastershipTerm(did);
+ if (myNodeId.equals(term.master())) {
+ myNextRole = MASTER;
+ } else {
+ myNextRole = STANDBY;
}
}
- }
- // checks for duplicate event, returning true if one is found.
- private boolean checkDuplicate(RoleInfo roleInfo, int term) {
- // turning off duplicate check
- return false;
-// synchronized (eventCache) {
-// if (eventCache.get(term).contains(roleInfo)) {
-// log.info("duplicate event detected; ignoring");
-// return true;
-// } else {
-// eventCache.put(term, roleInfo);
-// // purge by-term oldest entries to keep the cache size under limit
-// if (eventCache.size() > cacheSize) {
-// eventCache.removeAll(term - cacheSize);
-// }
-// return false;
-// }
-// }
+ switch (myNextRole) {
+ case MASTER:
+ final Device device = getDevice(did);
+ if ((device != null) && !isAvailable(did)) {
+ //flag the device as online. Is there a better way to do this?
+ DefaultDeviceDescription deviceDescription
+ = new DefaultDeviceDescription(did.uri(),
+ device.type(),
+ device.manufacturer(),
+ device.hwVersion(),
+ device.swVersion(),
+ device.serialNumber(),
+ device.chassisId());
+ DeviceEvent devEvent =
+ store.createOrUpdateDevice(device.providerId(), did,
+ deviceDescription);
+ post(devEvent);
+ }
+ // TODO: should apply role only if there is mismatch
+ log.info("Applying role {} to {}", myNextRole, did);
+ applyRole(did, MASTER);
+ break;
+ case STANDBY:
+ log.info("Applying role {} to {}", myNextRole, did);
+ applyRole(did, STANDBY);
+ break;
+ case NONE:
+ default:
+ // should never reach here
+ log.error("You didn't see anything. I did not exist.");
+ break;
+ }
}
-
}
// Store delegate to re-post events emitted from the store.
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 4fe9022..bd7fb94 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -371,10 +371,11 @@
final FlowRuleBatchRequest request = event.subject();
switch (event.type()) {
case BATCH_OPERATION_REQUESTED:
- for (FlowEntry entry : request.toAdd()) {
+ // Request has been forwarded to MASTER Node, and was
+ for (FlowRule entry : request.toAdd()) {
eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADD_REQUESTED, entry));
}
- for (FlowEntry entry : request.toRemove()) {
+ for (FlowRule entry : request.toRemove()) {
eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVE_REQUESTED, entry));
}
// FIXME: what about op.equals(FlowRuleOperation.MODIFY) ?
@@ -392,21 +393,15 @@
Futures.getUnchecked(result)));
}
}, futureListeners);
+ break;
- break;
case BATCH_OPERATION_COMPLETED:
- Set<FlowRule> failedItems = event.result().failedItems();
- for (FlowEntry entry : request.toAdd()) {
- if (!failedItems.contains(entry)) {
- eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_ADDED, entry));
- }
- }
- for (FlowEntry entry : request.toRemove()) {
- if (!failedItems.contains(entry)) {
- eventDispatcher.post(new FlowRuleEvent(FlowRuleEvent.Type.RULE_REMOVED, entry));
- }
- }
+ // MASTER Node has pushed the batch down to the Device
+
+ // Note: RULE_ADDED will be posted
+ // when Flow was actually confirmed by stats reply.
break;
+
default:
break;
}
diff --git a/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java b/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java
index f28dcdb..a6af018 100644
--- a/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java
+++ b/core/net/src/main/java/org/onlab/onos/net/host/impl/HostMonitor.java
@@ -67,6 +67,7 @@
private final ConcurrentMap<ProviderId, HostProvider> hostProviders;
private static final long DEFAULT_PROBE_RATE = 30000; // milliseconds
+ private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes();
private long probeRate = DEFAULT_PROBE_RATE;
private Timeout timeout;
@@ -215,15 +216,15 @@
.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH)
.setOpCode(ARP.OP_REQUEST);
- arp.setSenderHardwareAddress(sourceMac.getAddress())
+ arp.setSenderHardwareAddress(sourceMac.toBytes())
.setSenderProtocolAddress(sourceIp.toOctets())
- .setTargetHardwareAddress(MacAddress.ZERO_MAC_ADDRESS)
+ .setTargetHardwareAddress(ZERO_MAC_ADDRESS)
.setTargetProtocolAddress(targetIp.toOctets());
Ethernet ethernet = new Ethernet();
ethernet.setEtherType(Ethernet.TYPE_ARP)
- .setDestinationMACAddress(MacAddress.BROADCAST_MAC)
- .setSourceMACAddress(sourceMac.getAddress())
+ .setDestinationMACAddress(MacAddress.BROADCAST)
+ .setSourceMACAddress(sourceMac)
.setPayload(arp);
return ethernet;
diff --git a/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java b/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java
index 953e88a..0aae62d 100644
--- a/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManager.java
@@ -132,7 +132,8 @@
// for one of our external addresses.
if (isOutsidePort(inPort)) {
IpAddress target =
- IpAddress.valueOf(arp.getTargetProtocolAddress());
+ IpAddress.valueOf(IpAddress.Version.INET,
+ arp.getTargetProtocolAddress());
PortAddresses addresses =
hostService.getAddressBindingsForPort(inPort);
@@ -149,7 +150,8 @@
// it could be a request from an internal host to an external
// address. Forward it over to the correct port.
IpAddress source =
- IpAddress.valueOf(arp.getSenderProtocolAddress());
+ IpAddress.valueOf(IpAddress.Version.INET,
+ arp.getSenderProtocolAddress());
PortAddresses sourceAddresses = findPortInSubnet(source);
if (sourceAddresses != null) {
for (InterfaceIpAddress ia : sourceAddresses.ipAddresses()) {
@@ -164,8 +166,9 @@
// Continue with normal proxy ARP case
VlanId vlan = VlanId.vlanId(eth.getVlanID());
- Set<Host> hosts = hostService.getHostsByIp(IpAddress.valueOf(arp
- .getTargetProtocolAddress()));
+ Set<Host> hosts =
+ hostService.getHostsByIp(IpAddress.valueOf(IpAddress.Version.INET,
+ arp.getTargetProtocolAddress()));
Host dst = null;
Host src = hostService.getHost(HostId.hostId(eth.getSourceMAC(),
@@ -357,8 +360,8 @@
Ethernet request) {
Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress(request.getSourceMACAddress());
- eth.setSourceMACAddress(srcMac.getAddress());
+ eth.setDestinationMACAddress(request.getSourceMAC());
+ eth.setSourceMACAddress(srcMac);
eth.setEtherType(Ethernet.TYPE_ARP);
eth.setVlanID(request.getVlanID());
@@ -369,7 +372,7 @@
arp.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH);
arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
- arp.setSenderHardwareAddress(srcMac.getAddress());
+ arp.setSenderHardwareAddress(srcMac.toBytes());
arp.setTargetHardwareAddress(request.getSourceMACAddress());
arp.setTargetProtocolAddress(((ARP) request.getPayload())
diff --git a/core/net/src/main/java/org/onlab/onos/net/resource/impl/DefaultLinkResourceAllocations.java b/core/net/src/main/java/org/onlab/onos/net/resource/impl/DefaultLinkResourceAllocations.java
index 28ace88..13e02e5 100644
--- a/core/net/src/main/java/org/onlab/onos/net/resource/impl/DefaultLinkResourceAllocations.java
+++ b/core/net/src/main/java/org/onlab/onos/net/resource/impl/DefaultLinkResourceAllocations.java
@@ -15,11 +15,7 @@
*/
package org.onlab.onos.net.resource.impl;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
+import com.google.common.base.MoreObjects;
import org.onlab.onos.net.Link;
import org.onlab.onos.net.intent.IntentId;
import org.onlab.onos.net.resource.LinkResourceAllocations;
@@ -28,6 +24,11 @@
import org.onlab.onos.net.resource.ResourceRequest;
import org.onlab.onos.net.resource.ResourceType;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
/**
* Implementation of {@link LinkResourceAllocations}.
*/
@@ -38,11 +39,11 @@
/**
* Creates a new link resource allocations.
*
- * @param request requested resources
+ * @param request requested resources
* @param allocations allocated resources
*/
DefaultLinkResourceAllocations(LinkResourceRequest request,
- Map<Link, Set<ResourceAllocation>> allocations) {
+ Map<Link, Set<ResourceAllocation>> allocations) {
this.request = request;
this.allocations = allocations;
}
@@ -76,4 +77,10 @@
return result;
}
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("allocations", allocations)
+ .toString();
+ }
}
diff --git a/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
index 25fa922..d278c24 100644
--- a/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/device/impl/DeviceManagerTest.java
@@ -19,7 +19,6 @@
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.onlab.onos.cluster.ClusterEventListener;
import org.onlab.onos.cluster.ClusterService;
@@ -181,16 +180,6 @@
assertEquals("incorrect role", MastershipRole.MASTER, service.getRole(DID1));
}
- @Ignore("disabled until we settle the device-mastership wiring")
- @Test
- public void setRole() throws InterruptedException {
- connectDevice(DID1, SW1);
- validateEvents(DEVICE_ADDED, DEVICE_MASTERSHIP_CHANGED);
- assertEquals("incorrect role", MastershipRole.STANDBY, service.getRole(DID1));
- assertEquals("incorrect device", DID1, provider.deviceReceived.id());
- assertEquals("incorrect role", MastershipRole.STANDBY, provider.roleReceived);
- }
-
@Test
public void updatePorts() {
connectDevice(DID1, SW1);
@@ -262,7 +251,7 @@
private class TestProvider extends AbstractProvider implements DeviceProvider {
- private Device deviceReceived;
+ private DeviceId deviceReceived;
private MastershipRole roleReceived;
public TestProvider() {
@@ -274,13 +263,13 @@
}
@Override
- public void roleChanged(Device device, MastershipRole newRole) {
+ public void roleChanged(DeviceId device, MastershipRole newRole) {
deviceReceived = device;
roleReceived = newRole;
}
@Override
- public boolean isReachable(Device device) {
+ public boolean isReachable(DeviceId device) {
return false;
}
}
@@ -360,9 +349,16 @@
private final class TestClockProviderService implements
DeviceClockProviderService {
+ private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet();
+
@Override
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
- // TODO Auto-generated method stub
+ registerdBefore.add(deviceId);
+ }
+
+ @Override
+ public boolean isTimestampAvailable(DeviceId deviceId) {
+ return registerdBefore.contains(deviceId);
}
}
}
diff --git a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
index b986d6d..f67d992 100644
--- a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
@@ -148,7 +148,7 @@
int i = 0;
System.err.println("events :" + listener.events);
for (FlowRuleEvent e : listener.events) {
- assertTrue("unexpected event", e.type().equals(events[i]));
+ assertEquals("unexpected event", events[i], e.type());
i++;
}
@@ -178,15 +178,13 @@
RULE_ADDED, RULE_ADDED);
addFlowRule(1);
+ System.err.println("events :" + listener.events);
assertEquals("should still be 2 rules", 2, flowCount());
providerService.pushFlowMetrics(DID, ImmutableList.of(fe1));
validateEvents(RULE_UPDATED);
}
-
- // TODO: If preserving iteration order is a requirement, redo FlowRuleStore.
- //backing store is sensitive to the order of additions/removals
private boolean validateState(Map<FlowRule, FlowEntryState> expected) {
Map<FlowRule, FlowEntryState> expectedToCheck = new HashMap<>(expected);
Iterable<FlowEntry> rules = service.getFlowEntries(DID);
@@ -539,17 +537,17 @@
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
- return true;
+ return false;
}
@Override
public boolean isCancelled() {
- return true;
+ return false;
}
@Override
public boolean isDone() {
- return false;
+ return true;
}
@Override
@@ -562,12 +560,14 @@
public CompletedBatchOperation get(long timeout, TimeUnit unit)
throws InterruptedException,
ExecutionException, TimeoutException {
- return null;
+ return new CompletedBatchOperation(true, Collections.<FlowRule>emptySet());
}
@Override
public void addListener(Runnable task, Executor executor) {
- // TODO: add stuff.
+ if (isDone()) {
+ executor.execute(task);
+ }
}
}
diff --git a/core/net/src/test/java/org/onlab/onos/net/host/impl/HostMonitorTest.java b/core/net/src/test/java/org/onlab/onos/net/host/impl/HostMonitorTest.java
index 7405de2..654cab1 100644
--- a/core/net/src/test/java/org/onlab/onos/net/host/impl/HostMonitorTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/host/impl/HostMonitorTest.java
@@ -20,11 +20,9 @@
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -155,17 +153,20 @@
Instruction instruction = packet.treatment().instructions().get(0);
assertTrue(instruction instanceof OutputInstruction);
OutputInstruction oi = (OutputInstruction) instruction;
- assertTrue(oi.port().equals(portNum));
+ assertEquals(portNum, oi.port());
// Check the output packet is correct (well the important bits anyway)
Ethernet eth = new Ethernet();
- eth.deserialize(packet.data().array(), 0, packet.data().array().length);
+ final byte[] pktData = new byte[packet.data().remaining()];
+ packet.data().get(pktData);
+ eth.deserialize(pktData, 0, pktData.length);
ARP arp = (ARP) eth.getPayload();
- assertTrue(Arrays.equals(arp.getSenderProtocolAddress(),
- SOURCE_ADDR.toOctets()));
- assertTrue(Arrays.equals(arp.getSenderHardwareAddress(), sourceMac.toBytes()));
- assertTrue(Arrays.equals(arp.getTargetProtocolAddress(),
- TARGET_IP_ADDR.toOctets()));
+ assertArrayEquals(SOURCE_ADDR.toOctets(),
+ arp.getSenderProtocolAddress());
+ assertArrayEquals(sourceMac.toBytes(),
+ arp.getSenderHardwareAddress());
+ assertArrayEquals(TARGET_IP_ADDR.toOctets(),
+ arp.getTargetProtocolAddress());
}
class TestPacketService implements PacketService {
diff --git a/core/net/src/test/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManagerTest.java
index f720535..e82151e 100644
--- a/core/net/src/test/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/proxyarp/impl/ProxyArpManagerTest.java
@@ -19,12 +19,9 @@
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -91,6 +88,7 @@
private static final PortNumber P1 = PortNumber.portNumber(1);
private static final HostLocation LOC1 = new HostLocation(DID1, P1, 123L);
private static final HostLocation LOC2 = new HostLocation(DID2, P1, 123L);
+ private static final byte[] ZERO_MAC_ADDRESS = MacAddress.ZERO.toBytes();
private ProxyArpManager proxyArp;
@@ -483,7 +481,7 @@
*/
private void verifyPacketOut(Ethernet expected, ConnectPoint outPort,
OutboundPacket actual) {
- assertTrue(Arrays.equals(expected.serialize(), actual.data().array()));
+ assertArrayEquals(expected.serialize(), actual.data().array());
assertEquals(1, actual.treatment().instructions().size());
assertEquals(outPort.deviceId(), actual.sendThrough());
Instruction instruction = actual.treatment().instructions().get(0);
@@ -520,12 +518,12 @@
Ethernet eth = new Ethernet();
if (dstMac == null) {
- eth.setDestinationMACAddress(MacAddress.BROADCAST_MAC);
+ eth.setDestinationMACAddress(MacAddress.BROADCAST);
} else {
- eth.setDestinationMACAddress(dstMac.getAddress());
+ eth.setDestinationMACAddress(dstMac);
}
- eth.setSourceMACAddress(srcMac.getAddress());
+ eth.setSourceMACAddress(srcMac);
eth.setEtherType(Ethernet.TYPE_ARP);
eth.setVlanID(VLAN1.toShort());
@@ -536,12 +534,12 @@
arp.setProtocolAddressLength((byte) IpAddress.INET_BYTE_LENGTH);
arp.setHardwareAddressLength((byte) Ethernet.DATALAYER_ADDRESS_LENGTH);
- arp.setSenderHardwareAddress(srcMac.getAddress());
+ arp.setSenderHardwareAddress(srcMac.toBytes());
if (dstMac == null) {
- arp.setTargetHardwareAddress(MacAddress.ZERO_MAC_ADDRESS);
+ arp.setTargetHardwareAddress(ZERO_MAC_ADDRESS);
} else {
- arp.setTargetHardwareAddress(dstMac.getAddress());
+ arp.setTargetHardwareAddress(dstMac.toBytes());
}
arp.setSenderProtocolAddress(srcIp.toOctets());
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
index e3822ad..f372ced 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/impl/DistributedClusterStore.java
@@ -147,8 +147,7 @@
}
private IpAddress memberAddress(Member member) {
- byte[] address = member.getSocketAddress().getAddress().getAddress();
- return IpAddress.valueOf(address);
+ return IpAddress.valueOf(member.getSocketAddress().getAddress());
}
// Interceptor for membership events.
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManager.java b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManager.java
index 540de77..79612c9 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManager.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/cluster/messaging/impl/ClusterCommunicationManager.java
@@ -85,7 +85,6 @@
try {
netty.activate();
} catch (Exception e) {
- // TODO Auto-generated catch block
log.error("NettyMessagingService#activate", e);
}
messagingService = netty;
@@ -95,6 +94,12 @@
@Deactivate
public void deactivate() {
// TODO: cleanup messageingService if needed.
+ // FIXME: workaround until it becomes a service.
+ try {
+ ((NettyMessagingService) messagingService).deactivate();
+ } catch (Exception e) {
+ log.error("NettyMessagingService#deactivate", e);
+ }
log.info("Stopped");
}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
index f7f24e9..486d41e 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/DeviceClockManager.java
@@ -72,4 +72,9 @@
log.info("adding term info {} {}", deviceId, term.master());
deviceMastershipTerms.put(deviceId, term);
}
+
+ @Override
+ public boolean isTimestampAvailable(DeviceId deviceId) {
+ return deviceMastershipTerms.containsKey(deviceId);
+ }
}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java
index 5449277..66366c1 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/device/impl/GossipDeviceStore.java
@@ -1216,7 +1216,7 @@
@Override
public void handle(ClusterMessage message) {
- log.info("Received device update event from peer: {}", message.sender());
+ log.debug("Received device update event from peer: {}", message.sender());
InternalDeviceEvent event = (InternalDeviceEvent) SERIALIZER.decode(message.payload());
ProviderId providerId = event.providerId();
@@ -1231,7 +1231,7 @@
@Override
public void handle(ClusterMessage message) {
- log.info("Received device offline event from peer: {}", message.sender());
+ log.debug("Received device offline event from peer: {}", message.sender());
InternalDeviceOfflineEvent event = (InternalDeviceOfflineEvent) SERIALIZER.decode(message.payload());
DeviceId deviceId = event.deviceId();
@@ -1245,7 +1245,7 @@
@Override
public void handle(ClusterMessage message) {
- log.info("Received device removed event from peer: {}", message.sender());
+ log.debug("Received device removed event from peer: {}", message.sender());
InternalDeviceRemovedEvent event = (InternalDeviceRemovedEvent) SERIALIZER.decode(message.payload());
DeviceId deviceId = event.deviceId();
@@ -1259,13 +1259,19 @@
@Override
public void handle(ClusterMessage message) {
- log.info("Received port update event from peer: {}", message.sender());
+ log.debug("Received port update event from peer: {}", message.sender());
InternalPortEvent event = (InternalPortEvent) SERIALIZER.decode(message.payload());
ProviderId providerId = event.providerId();
DeviceId deviceId = event.deviceId();
Timestamped<List<PortDescription>> portDescriptions = event.portDescriptions();
+ if (getDevice(deviceId) == null) {
+ log.info("{} not found on this node yet, ignoring.", deviceId);
+ // Note: dropped information will be recovered by anti-entropy
+ return;
+ }
+
notifyDelegate(updatePortsInternal(providerId, deviceId, portDescriptions));
}
}
@@ -1274,14 +1280,19 @@
@Override
public void handle(ClusterMessage message) {
- log.info("Received port status update event from peer: {}", message.sender());
+ log.debug("Received port status update event from peer: {}", message.sender());
InternalPortStatusEvent event = (InternalPortStatusEvent) SERIALIZER.decode(message.payload());
- log.info("{}", event);
ProviderId providerId = event.providerId();
DeviceId deviceId = event.deviceId();
Timestamped<PortDescription> portDescription = event.portDescription();
+ if (getDevice(deviceId) == null) {
+ log.info("{} not found on this node yet, ignoring.", deviceId);
+ // Note: dropped information will be recovered by anti-entropy
+ return;
+ }
+
notifyDelegateIfNotNull(updatePortStatusInternal(providerId, deviceId, portDescription));
}
}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/flow/ReplicaInfoEvent.java b/core/store/dist/src/main/java/org/onlab/onos/store/flow/ReplicaInfoEvent.java
index c956c8a..ef4de4d 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/flow/ReplicaInfoEvent.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/flow/ReplicaInfoEvent.java
@@ -36,7 +36,7 @@
*/
MASTER_CHANGED,
//
- // BACKUPS_CHANGED?
+ BACKUPS_CHANGED,
}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/DistributedFlowRuleStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/DistributedFlowRuleStore.java
index bd2742a..ca3b29c 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/DistributedFlowRuleStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/DistributedFlowRuleStore.java
@@ -284,9 +284,10 @@
if (!replicaInfo.master().isPresent()) {
log.warn("No master for {}", deviceId);
- // TODO: revisit if this should be returning empty collection.
+ // TODO: revisit if this should be returning empty collection or throwing exception.
// FIXME: throw a FlowStoreException
- throw new RuntimeException("No master for " + deviceId);
+ //throw new RuntimeException("No master for " + deviceId);
+ return Collections.emptyList();
}
if (replicaInfo.master().get().equals(clusterService.getLocalNode().id())) {
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/ReplicaInfoManager.java b/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/ReplicaInfoManager.java
index 5d766e6..c3fa99a 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/ReplicaInfoManager.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/flow/impl/ReplicaInfoManager.java
@@ -18,10 +18,9 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.MASTER_CHANGED;
+import static org.onlab.onos.store.flow.ReplicaInfoEvent.Type.BACKUPS_CHANGED;
import java.util.Collections;
-import java.util.List;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -96,12 +95,24 @@
@Override
public void event(MastershipEvent event) {
- // TODO: distinguish stby list update, when MastershipService,
- // start publishing them
- final List<NodeId> standbyList = Collections.<NodeId>emptyList();
- eventDispatcher.post(new ReplicaInfoEvent(MASTER_CHANGED,
- event.subject(),
- new ReplicaInfo(event.roleInfo().master(), standbyList)));
+ final ReplicaInfo replicaInfo
+ = new ReplicaInfo(event.roleInfo().master(),
+ event.roleInfo().backups());
+
+ switch (event.type()) {
+ case MASTER_CHANGED:
+ eventDispatcher.post(new ReplicaInfoEvent(MASTER_CHANGED,
+ event.subject(),
+ replicaInfo));
+ break;
+ case BACKUPS_CHANGED:
+ eventDispatcher.post(new ReplicaInfoEvent(BACKUPS_CHANGED,
+ event.subject(),
+ replicaInfo));
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java b/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
index fc89e3a..713be4e 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStore.java
@@ -16,6 +16,7 @@
package org.onlab.onos.store.mastership.impl;
import static org.onlab.onos.mastership.MastershipEvent.Type.MASTER_CHANGED;
+import static org.onlab.onos.mastership.MastershipEvent.Type.BACKUPS_CHANGED;
import static org.apache.commons.lang3.concurrent.ConcurrentUtils.putIfAbsent;
import java.util.HashSet;
@@ -43,6 +44,7 @@
import org.onlab.onos.store.serializers.KryoSerializer;
import org.onlab.util.KryoNamespace;
+import com.google.common.base.Objects;
import com.hazelcast.core.EntryEvent;
import com.hazelcast.core.EntryListener;
import com.hazelcast.core.IAtomicLong;
@@ -297,8 +299,7 @@
case NONE:
rv.reassign(nodeId, NONE, STANDBY);
roleMap.put(deviceId, rv);
- // TODO: BACKUPS_CHANGED?
- return null;
+ return new MastershipEvent(BACKUPS_CHANGED, deviceId, rv.roleInfo());
default:
log.warn("unknown Mastership Role {}", currentRole);
}
@@ -327,7 +328,8 @@
roleMap.put(deviceId, rv);
return new MastershipEvent(MASTER_CHANGED, deviceId, rv.roleInfo());
} else {
- // no master candidate
+ // No master candidate - no more backups, device is likely
+ // fully disconnected
roleMap.put(deviceId, rv);
// Should there be new event type?
return null;
@@ -338,8 +340,7 @@
boolean modified = rv.reassign(nodeId, STANDBY, NONE);
if (modified) {
roleMap.put(deviceId, rv);
- // TODO: BACKUPS_CHANGED?
- return null;
+ return new MastershipEvent(BACKUPS_CHANGED, deviceId, rv.roleInfo());
}
return null;
default:
@@ -441,8 +442,24 @@
@Override
public void entryUpdated(EntryEvent<DeviceId, RoleValue> event) {
- notifyDelegate(new MastershipEvent(
- MASTER_CHANGED, event.getKey(), event.getValue().roleInfo()));
+ // compare old and current RoleValues. If master is different,
+ // emit MASTER_CHANGED. else, emit BACKUPS_CHANGED.
+ RoleValue oldValue = event.getOldValue();
+ RoleValue newValue = event.getValue();
+
+ NodeId oldMaster = null;
+ if (oldValue != null) {
+ oldMaster = oldValue.get(MASTER);
+ }
+ NodeId newMaster = newValue.get(MASTER);
+
+ if (Objects.equal(oldMaster, newMaster)) {
+ notifyDelegate(new MastershipEvent(
+ MASTER_CHANGED, event.getKey(), event.getValue().roleInfo()));
+ } else {
+ notifyDelegate(new MastershipEvent(
+ BACKUPS_CHANGED, event.getKey(), event.getValue().roleInfo()));
+ }
}
@Override
diff --git a/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java b/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java
index 8cc05e8..aa5d911 100644
--- a/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java
+++ b/core/store/dist/src/main/java/org/onlab/onos/store/mastership/impl/RoleValue.java
@@ -55,6 +55,13 @@
return value.get(type);
}
+ /**
+ * Returns the first node to match the MastershipRole, or if there
+ * are none, null.
+ *
+ * @param type the role
+ * @return a node ID or null
+ */
public NodeId get(MastershipRole type) {
return value.get(type).isEmpty() ? null : value.get(type).get(0);
}
diff --git a/core/store/dist/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java b/core/store/dist/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java
index f598374..d3b7ad1 100644
--- a/core/store/dist/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java
+++ b/core/store/dist/src/test/java/org/onlab/onos/store/mastership/impl/DistributedMastershipStoreTest.java
@@ -214,11 +214,11 @@
dms.roleMap.get(DID1).nodesOfRole(STANDBY).size());
//If STANDBY, should drop to NONE
- assertNull("wrong event:", dms.relinquishRole(N1, DID1));
+ assertEquals("wrong event:", Type.BACKUPS_CHANGED, dms.relinquishRole(N1, DID1).type());
assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID1));
//NONE - nothing happens
- assertNull("wrong event:", dms.relinquishRole(N1, DID2));
+ assertEquals("wrong event:", Type.BACKUPS_CHANGED, dms.relinquishRole(N1, DID2).type());
assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID2));
}
diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpAddressSerializer.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpAddressSerializer.java
index 686adb2..858d455 100644
--- a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpAddressSerializer.java
+++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpAddressSerializer.java
@@ -46,7 +46,13 @@
final int octLen = input.readInt();
byte[] octs = new byte[octLen];
input.readBytes(octs);
- return IpAddress.valueOf(octs);
+ // Use the address size to decide whether it is IPv4 or IPv6 address
+ if (octLen == IpAddress.INET_BYTE_LENGTH) {
+ return IpAddress.valueOf(IpAddress.Version.INET, octs);
+ }
+ if (octLen == IpAddress.INET6_BYTE_LENGTH) {
+ return IpAddress.valueOf(IpAddress.Version.INET6, octs);
+ }
+ return null; // Shouldn't be reached
}
-
}
diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpPrefixSerializer.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpPrefixSerializer.java
index 004f75f..16bd0f4 100644
--- a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpPrefixSerializer.java
+++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/IpPrefixSerializer.java
@@ -15,6 +15,7 @@
*/
package org.onlab.onos.store.serializers;
+import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import com.esotericsoftware.kryo.Kryo;
@@ -51,6 +52,13 @@
byte[] octs = new byte[octLen];
input.readBytes(octs);
int prefLen = input.readInt();
- return IpPrefix.valueOf(octs, prefLen);
+ // Use the address size to decide whether it is IPv4 or IPv6 address
+ if (octLen == IpAddress.INET_BYTE_LENGTH) {
+ return IpPrefix.valueOf(IpAddress.Version.INET, octs, prefLen);
+ }
+ if (octLen == IpAddress.INET6_BYTE_LENGTH) {
+ return IpPrefix.valueOf(IpAddress.Version.INET6, octs, prefLen);
+ }
+ return null; // Shouldn't be reached
}
}
diff --git a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MacAddressSerializer.java b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MacAddressSerializer.java
index 4837e84..8e4467e 100644
--- a/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MacAddressSerializer.java
+++ b/core/store/serializers/src/main/java/org/onlab/onos/store/serializers/MacAddressSerializer.java
@@ -36,7 +36,7 @@
@Override
public void write(Kryo kryo, Output output, MacAddress object) {
- output.writeBytes(object.getAddress());
+ output.writeBytes(object.toBytes());
}
@Override
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
index 64e5e16..d32ac53 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/NoOpClockProviderService.java
@@ -15,13 +15,16 @@
*/
package org.onlab.onos.store.trivial.impl;
+import java.util.Set;
+
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.mastership.MastershipTerm;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceClockProviderService;
-//FIXME: Code clone in onos-core-trivial, onos-core-hz-net
+import com.google.common.collect.Sets;
+
/**
* Dummy implementation of {@link DeviceClockProviderService}.
*/
@@ -29,7 +32,15 @@
@Service
public class NoOpClockProviderService implements DeviceClockProviderService {
+ private Set<DeviceId> registerdBefore = Sets.newConcurrentHashSet();
+
@Override
public void setMastershipTerm(DeviceId deviceId, MastershipTerm term) {
+ registerdBefore.add(deviceId);
+ }
+
+ @Override
+ public boolean isTimestampAvailable(DeviceId deviceId) {
+ return registerdBefore.contains(deviceId);
}
}
diff --git a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java
index 49b0c71..b7d26fb 100644
--- a/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java
+++ b/core/store/trivial/src/main/java/org/onlab/onos/store/trivial/impl/SimpleFlowRuleStore.java
@@ -16,8 +16,12 @@
package org.onlab.onos.store.trivial.impl;
import com.google.common.base.Function;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
import com.google.common.collect.FluentIterable;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.SettableFuture;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -43,13 +47,15 @@
import org.onlab.util.NewConcurrentHashMap;
import org.slf4j.Logger;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.commons.lang3.concurrent.ConcurrentUtils.createIfAbsentUnchecked;
import static org.onlab.onos.net.flow.FlowRuleEvent.Type.RULE_REMOVED;
@@ -72,6 +78,18 @@
private final ConcurrentMap<DeviceId, ConcurrentMap<FlowId, List<StoredFlowEntry>>>
flowEntries = new ConcurrentHashMap<>();
+ private final AtomicInteger localBatchIdGen = new AtomicInteger();
+
+ // TODO: make this configurable
+ private int pendingFutureTimeoutMinutes = 5;
+
+ private Cache<Integer, SettableFuture<CompletedBatchOperation>> pendingFutures =
+ CacheBuilder.newBuilder()
+ .expireAfterWrite(pendingFutureTimeoutMinutes, TimeUnit.MINUTES)
+ // TODO Explicitly fail the future if expired?
+ //.removalListener(listener)
+ .build();
+
@Activate
public void activate() {
log.info("Started");
@@ -173,10 +191,6 @@
}
// new flow rule added
existing.add(f);
- notifyDelegate(FlowRuleBatchEvent.requested(
- new FlowRuleBatchRequest(1, /* FIXME generate something */
- Arrays.<FlowEntry>asList(f),
- Collections.<FlowEntry>emptyList())));
}
}
@@ -190,11 +204,6 @@
if (entry.equals(rule)) {
synchronized (entry) {
entry.setState(FlowEntryState.PENDING_REMOVE);
- // TODO: Should we notify only if it's "remote" event?
- notifyDelegate(FlowRuleBatchEvent.requested(
- new FlowRuleBatchRequest(1, /* FIXME generate something */
- Collections.<FlowEntry>emptyList(),
- Arrays.<FlowEntry>asList(entry))));
}
}
}
@@ -251,20 +260,47 @@
@Override
public Future<CompletedBatchOperation> storeBatch(
FlowRuleBatchOperation batchOperation) {
+ List<FlowRule> toAdd = new ArrayList<>();
+ List<FlowRule> toRemove = new ArrayList<>();
for (FlowRuleBatchEntry entry : batchOperation.getOperations()) {
+ final FlowRule flowRule = entry.getTarget();
if (entry.getOperator().equals(FlowRuleOperation.ADD)) {
- storeFlowRule(entry.getTarget());
+ if (!getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) {
+ storeFlowRule(flowRule);
+ toAdd.add(flowRule);
+ }
} else if (entry.getOperator().equals(FlowRuleOperation.REMOVE)) {
- deleteFlowRule(entry.getTarget());
+ if (getFlowEntries(flowRule.deviceId(), flowRule.id()).contains(flowRule)) {
+ deleteFlowRule(flowRule);
+ toRemove.add(flowRule);
+ }
} else {
throw new UnsupportedOperationException("Unsupported operation type");
}
}
- return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowEntry>emptySet()));
+
+ if (toAdd.isEmpty() && toRemove.isEmpty()) {
+ return Futures.immediateFuture(new CompletedBatchOperation(true, Collections.<FlowRule>emptySet()));
+ }
+
+ SettableFuture<CompletedBatchOperation> r = SettableFuture.create();
+ final int batchId = localBatchIdGen.incrementAndGet();
+
+ pendingFutures.put(batchId, r);
+ notifyDelegate(FlowRuleBatchEvent.requested(new FlowRuleBatchRequest(batchId, toAdd, toRemove)));
+
+ return r;
}
@Override
public void batchOperationComplete(FlowRuleBatchEvent event) {
+ final Integer batchId = event.subject().batchId();
+ SettableFuture<CompletedBatchOperation> future
+ = pendingFutures.getIfPresent(batchId);
+ if (future != null) {
+ future.set(event.result());
+ pendingFutures.invalidate(batchId);
+ }
notifyDelegate(event);
}
}
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
index 17f168f..2d3f890 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitch.java
@@ -115,17 +115,25 @@
public String serialNumber();
/**
+ * Checks if the switch is still connected.
+ *
+ * @return whether the switch is still connected
+ */
+ public boolean isConnected();
+
+ /**
* Disconnects the switch by closing the TCP connection. Results in a call
* to the channel handler's channelDisconnected method for cleanup
*/
public void disconnectSwitch();
/**
- * Notifies the controller that role assertion has failed.
+ * Notifies the controller that the device has responded to a set-role request.
*
- * @param role the failed role
+ * @param requested the role requested by the controller
+ * @param response the role set at the device
*/
- public void returnRoleAssertFailure(RoleState role);
+ public void returnRoleReply(RoleState requested, RoleState reponse);
/**
* Indicates if this switch is optical.
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java
index a96c56f..192f045 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/OpenFlowSwitchListener.java
@@ -53,5 +53,5 @@
* @param dpid the switch that failed role assertion
* @param role the role imposed by the controller
*/
- public void roleAssertFailed(Dpid dpid, RoleState role);
+ public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response);
}
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java
index 9950515..61359cd 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/AbstractOpenFlowSwitch.java
@@ -217,8 +217,8 @@
}
@Override
- public void returnRoleAssertFailure(RoleState role) {
- this.agent.returnRoleAssertFailed(dpid, role);
+ public void returnRoleReply(RoleState requested, RoleState response) {
+ this.agent.returnRoleReply(dpid, requested, response);
}
@Override
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowAgent.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowAgent.java
index fa2823f..6b73efc 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowAgent.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowAgent.java
@@ -97,5 +97,5 @@
* @param dpid the switch that failed role assertion
* @param role the failed role
*/
- public void returnRoleAssertFailed(Dpid dpid, RoleState role);
+ public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response);
}
diff --git a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowSwitchDriver.java b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowSwitchDriver.java
index 2647fed..b6a4770 100644
--- a/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowSwitchDriver.java
+++ b/openflow/api/src/main/java/org/onlab/onos/openflow/controller/driver/OpenFlowSwitchDriver.java
@@ -187,13 +187,6 @@
public void setConnected(boolean connected);
/**
- * Checks if the switch is still connected.
- *
- * @return whether the switch is still connected
- */
- public boolean isConnected();
-
- /**
* Writes the message to the output stream
* in a driver specific manner.
*
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
index 70c9b1b..098771d 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/OpenFlowControllerImpl.java
@@ -374,9 +374,9 @@
}
@Override
- public void returnRoleAssertFailed(Dpid dpid, RoleState role) {
+ public void returnRoleReply(Dpid dpid, RoleState requested, RoleState response) {
for (OpenFlowSwitchListener l : ofSwitchListener) {
- l.roleAssertFailed(dpid, role);
+ l.receivedRoleReply(dpid, requested, response);
}
}
}
diff --git a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java
index c9f71b7..6e5b236 100644
--- a/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java
+++ b/openflow/ctl/src/main/java/org/onlab/onos/openflow/controller/impl/RoleManager.java
@@ -17,6 +17,7 @@
import java.io.IOException;
import java.util.Collections;
+import java.util.concurrent.TimeUnit;
import org.onlab.onos.openflow.controller.RoleState;
import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver;
@@ -41,31 +42,29 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
/**
* A utility class to handle role requests and replies for this channel.
* After a role request is submitted the role changer keeps track of the
* pending request, collects the reply (if any) and times out the request
* if necessary.
- *
- * To simplify role handling we only keep track of the /last/ pending
- * role reply send to the switch. If multiple requests are pending and
- * we receive replies for earlier requests we ignore them. However, this
- * way of handling pending requests implies that we could wait forever if
- * a new request is submitted before the timeout triggers. If necessary
- * we could work around that though.
*/
class RoleManager implements RoleHandler {
protected static final long NICIRA_EXPERIMENTER = 0x2320;
private static Logger log = LoggerFactory.getLogger(RoleManager.class);
- // indicates that a request is currently pending
- // needs to be volatile to allow correct double-check idiom
- private volatile boolean requestPending;
- // the transaction Id of the pending request
- private int pendingXid;
- // the role that's pending
- private RoleState pendingRole;
+
+ // The time until cached XID is evicted. Arbitray for now.
+ private final int pendingXidTimeoutSeconds = 60;
+
+ // The cache for pending expected RoleReplies keyed on expected XID
+ private Cache<Integer, RoleState> pendingReplies =
+ CacheBuilder.newBuilder()
+ .expireAfterWrite(pendingXidTimeoutSeconds, TimeUnit.SECONDS)
+ .build();
// the expectation set by the caller for the returned role
private RoleRecvStatus expectation;
@@ -73,9 +72,6 @@
public RoleManager(OpenFlowSwitchDriver sw) {
- this.requestPending = false;
- this.pendingXid = -1;
- this.pendingRole = null;
this.expectation = RoleRecvStatus.MATCHED_CURRENT_ROLE;
this.sw = sw;
}
@@ -157,15 +153,11 @@
}
// OF1.0 switch with support for NX_ROLE_REQUEST vendor extn.
// make Role.EQUAL become Role.SLAVE
- pendingRole = role;
- role = (role == RoleState.EQUAL) ? RoleState.SLAVE : role;
- pendingXid = sendNxRoleRequest(role);
- requestPending = true;
+ RoleState roleToSend = (role == RoleState.EQUAL) ? RoleState.SLAVE : role;
+ pendingReplies.put(sendNxRoleRequest(roleToSend), role);
} else {
// OF1.3 switch, use OFPT_ROLE_REQUEST message
- pendingXid = sendOF13RoleRequest(role);
- pendingRole = role;
- requestPending = true;
+ pendingReplies.put(sendOF13RoleRequest(role), role);
}
return true;
}
@@ -192,12 +184,17 @@
@Override
public synchronized RoleRecvStatus deliverRoleReply(RoleReplyInfo rri)
throws SwitchStateException {
- if (!requestPending) {
+ int xid = (int) rri.getXid();
+ RoleState receivedRole = rri.getRole();
+ RoleState expectedRole = pendingReplies.getIfPresent(xid);
+
+ if (expectedRole == null) {
RoleState currentRole = (sw != null) ? sw.getRole() : null;
if (currentRole != null) {
if (currentRole == rri.getRole()) {
// Don't disconnect if the role reply we received is
// for the same role we are already in.
+ // FIXME: but we do from the caller anyways.
log.debug("Received unexpected RoleReply from "
+ "Switch: {}. "
+ "Role in reply is same as current role of this "
@@ -223,34 +220,33 @@
return RoleRecvStatus.OTHER_EXPECTATION;
}
- int xid = (int) rri.getXid();
- RoleState role = rri.getRole();
- // XXX S should check generation id meaningfully and other cases of expectations
+ // XXX Should check generation id meaningfully and other cases of expectations
+ //if (pendingXid != xid) {
+ // log.info("Received older role reply from " +
+ // "switch {} ({}). Ignoring. " +
+ // "Waiting for {}, xid={}",
+ // new Object[] {sw.getStringId(), rri,
+ // pendingRole, pendingXid });
+ // return RoleRecvStatus.OLD_REPLY;
+ //}
+ sw.returnRoleReply(expectedRole, receivedRole);
- if (pendingXid != xid) {
- log.debug("Received older role reply from " +
- "switch {} ({}). Ignoring. " +
- "Waiting for {}, xid={}",
- new Object[] {sw.getStringId(), rri,
- pendingRole, pendingXid });
- return RoleRecvStatus.OLD_REPLY;
- }
-
- if (pendingRole == role) {
+ if (expectedRole == receivedRole) {
log.debug("Received role reply message from {} that matched "
+ "expected role-reply {} with expectations {}",
- new Object[] {sw.getStringId(), role, expectation});
+ new Object[] {sw.getStringId(), receivedRole, expectation});
+ // Done with this RoleReply; Invalidate
+ pendingReplies.invalidate(xid);
if (expectation == RoleRecvStatus.MATCHED_CURRENT_ROLE ||
expectation == RoleRecvStatus.MATCHED_SET_ROLE) {
return expectation;
} else {
return RoleRecvStatus.OTHER_EXPECTATION;
}
- } else {
- sw.returnRoleAssertFailure(pendingRole);
}
+ pendingReplies.invalidate(xid);
// if xids match but role's don't, perhaps its a query (OF1.3)
if (expectation == RoleRecvStatus.REPLY_QUERY) {
return expectation;
@@ -270,18 +266,17 @@
@Override
public synchronized RoleRecvStatus deliverError(OFErrorMsg error)
throws SwitchStateException {
- if (!requestPending) {
- log.debug("Received an error msg from sw {}, but no pending "
- + "requests in role-changer; not handling ...",
- sw.getStringId());
- return RoleRecvStatus.OTHER_EXPECTATION;
- }
- if (pendingXid != error.getXid()) {
+ RoleState errorRole = pendingReplies.getIfPresent(error.getXid());
+ if (errorRole == null) {
if (error.getErrType() == OFErrorType.ROLE_REQUEST_FAILED) {
log.debug("Received an error msg from sw {} for a role request,"
+ " but not for pending request in role-changer; "
+ " ignoring error {} ...",
sw.getStringId(), error);
+ } else {
+ log.debug("Received an error msg from sw {}, but no pending "
+ + "requests in role-changer; not handling ...",
+ sw.getStringId());
}
return RoleRecvStatus.OTHER_EXPECTATION;
}
@@ -292,7 +287,7 @@
+ "role-messaging is supported. Possible issues in "
+ "switch driver configuration?", new Object[] {
((OFBadRequestErrorMsg) error).toString(),
- sw.getStringId(), pendingRole
+ sw.getStringId(), errorRole
});
return RoleRecvStatus.UNSUPPORTED;
}
@@ -316,7 +311,7 @@
+ "received Error to for pending role request [%s]. "
+ "Error:[%s]. Disconnecting switch ... ",
sw.getStringId(),
- pendingRole, rrerr);
+ errorRole, rrerr);
throw new SwitchStateException(msgx);
default:
break;
diff --git a/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java b/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java
index aa23995..7260ddd 100644
--- a/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java
+++ b/openflow/ctl/src/test/java/org/onlab/onos/openflow/controller/impl/RoleManagerTest.java
@@ -175,11 +175,6 @@
}
@Override
- public void returnRoleAssertFailure(RoleState role) {
- failed = role;
- }
-
- @Override
public boolean isOptical() {
return false;
}
@@ -300,5 +295,10 @@
public void write(List<OFMessage> msgs) {
}
+ @Override
+ public void returnRoleReply(RoleState requested, RoleState response) {
+ failed = requested;
+ }
+
}
}
diff --git a/pom.xml b/pom.xml
index 83ed0f4..deefb48 100644
--- a/pom.xml
+++ b/pom.xml
@@ -318,6 +318,7 @@
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty4.version}</version>
+ <classifier>${os.detected.classifier}</classifier>
</dependency>
<dependency>
<groupId>joda-time</groupId>
@@ -351,6 +352,13 @@
</dependencies>
<build>
+ <extensions>
+ <extension>
+ <groupId>kr.motd.maven</groupId>
+ <artifactId>os-maven-plugin</artifactId>
+ <version>1.2.3.Final</version>
+ </extension>
+ </extensions>
<pluginManagement>
<plugins>
<plugin>
diff --git a/providers/host/src/main/java/org/onlab/onos/provider/host/impl/HostLocationProvider.java b/providers/host/src/main/java/org/onlab/onos/provider/host/impl/HostLocationProvider.java
index 36d67b2..48762bb 100644
--- a/providers/host/src/main/java/org/onlab/onos/provider/host/impl/HostLocationProvider.java
+++ b/providers/host/src/main/java/org/onlab/onos/provider/host/impl/HostLocationProvider.java
@@ -120,7 +120,8 @@
if (eth.getEtherType() == Ethernet.TYPE_ARP) {
ARP arp = (ARP) eth.getPayload();
IpAddress ip =
- IpAddress.valueOf(arp.getSenderProtocolAddress());
+ IpAddress.valueOf(IpAddress.Version.INET,
+ arp.getSenderProtocolAddress());
HostDescription hdescr =
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
providerService.hostDetected(hid, hdescr);
diff --git a/providers/host/src/test/java/org/onlab/onos/provider/host/impl/HostLocationProviderTest.java b/providers/host/src/test/java/org/onlab/onos/provider/host/impl/HostLocationProviderTest.java
index b226fff..e42d657 100644
--- a/providers/host/src/test/java/org/onlab/onos/provider/host/impl/HostLocationProviderTest.java
+++ b/providers/host/src/test/java/org/onlab/onos/provider/host/impl/HostLocationProviderTest.java
@@ -216,7 +216,7 @@
eth.setEtherType(Ethernet.TYPE_ARP)
.setVlanID(VLAN.toShort())
.setSourceMACAddress(MAC.toBytes())
- .setDestinationMACAddress(BCMAC.getAddress())
+ .setDestinationMACAddress(BCMAC)
.setPayload(arp);
ConnectPoint receivedFrom = new ConnectPoint(DeviceId.deviceId(deviceId),
PortNumber.portNumber(INPORT));
diff --git a/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LLDPLinkProvider.java b/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LLDPLinkProvider.java
index 24336aa..6dc464e 100644
--- a/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LLDPLinkProvider.java
+++ b/providers/lldp/src/main/java/org/onlab/onos/provider/lldp/impl/LLDPLinkProvider.java
@@ -127,18 +127,19 @@
return;
}
log.trace("{} {} {}", event.type(), event.subject(), event);
+ final DeviceId deviceId = device.id();
switch (event.type()) {
case DEVICE_ADDED:
case DEVICE_UPDATED:
- ld = discoverers.get(device.id());
+ ld = discoverers.get(deviceId);
if (ld == null) {
- log.debug("Device added ({}) {}", event.type(), device.id());
- discoverers.put(device.id(),
+ log.debug("Device added ({}) {}", event.type(), deviceId);
+ discoverers.put(deviceId,
new LinkDiscovery(device, packetSevice, masterService,
providerService, useBDDP));
} else {
if (ld.isStopped()) {
- log.debug("Device restarted ({}) {}", event.type(), device.id());
+ log.debug("Device restarted ({}) {}", event.type(), deviceId);
ld.start();
}
}
@@ -146,7 +147,7 @@
case PORT_ADDED:
case PORT_UPDATED:
if (port.isEnabled()) {
- ld = discoverers.get(device.id());
+ ld = discoverers.get(deviceId);
if (ld == null) {
return;
}
@@ -156,47 +157,47 @@
}
} else {
log.debug("Port down {}", port);
- ConnectPoint point = new ConnectPoint(device.id(),
+ ConnectPoint point = new ConnectPoint(deviceId,
port.number());
providerService.linksVanished(point);
}
break;
case PORT_REMOVED:
log.debug("Port removed {}", port);
- ConnectPoint point = new ConnectPoint(device.id(),
+ ConnectPoint point = new ConnectPoint(deviceId,
port.number());
providerService.linksVanished(point);
// TODO: Don't we need to removePort from ld?
break;
case DEVICE_REMOVED:
case DEVICE_SUSPENDED:
- log.debug("Device removed {}", device.id());
- ld = discoverers.get(device.id());
+ log.debug("Device removed {}", deviceId);
+ ld = discoverers.get(deviceId);
if (ld == null) {
return;
}
ld.stop();
- providerService.linksVanished(device.id());
+ providerService.linksVanished(deviceId);
break;
case DEVICE_AVAILABILITY_CHANGED:
- ld = discoverers.get(device.id());
+ ld = discoverers.get(deviceId);
if (ld == null) {
return;
}
- if (deviceService.isAvailable(device.id())) {
- log.debug("Device up {}", device.id());
+ if (deviceService.isAvailable(deviceId)) {
+ log.debug("Device up {}", deviceId);
ld.start();
} else {
- providerService.linksVanished(device.id());
- log.debug("Device down {}", device.id());
+ providerService.linksVanished(deviceId);
+ log.debug("Device down {}", deviceId);
ld.stop();
}
break;
case DEVICE_MASTERSHIP_CHANGED:
- if (!discoverers.containsKey(device.id())) {
+ if (!discoverers.containsKey(deviceId)) {
// TODO: ideally, should never reach here
- log.debug("Device mastership changed ({}) {}", event.type(), device.id());
- discoverers.put(device.id(),
+ log.debug("Device mastership changed ({}) {}", event.type(), deviceId);
+ discoverers.put(deviceId,
new LinkDiscovery(device, packetSevice, masterService,
providerService, useBDDP));
}
diff --git a/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
index 8aa3d77..c0cc416 100644
--- a/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -39,7 +39,6 @@
import org.onlab.onos.openflow.controller.OpenFlowSwitch;
import org.onlab.onos.openflow.controller.OpenFlowSwitchListener;
import org.onlab.onos.openflow.controller.RoleState;
-import org.onlab.onos.openflow.controller.driver.OpenFlowSwitchDriver;
import org.onlab.packet.ChassisId;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
@@ -112,27 +111,39 @@
@Override
- public boolean isReachable(Device device) {
- // FIXME if possible, we might want this to be part of
- // OpenFlowSwitch interface so the driver interface isn't misused.
- OpenFlowSwitch sw = controller.getSwitch(dpid(device.id().uri()));
- if (sw == null || !((OpenFlowSwitchDriver) sw).isConnected()) {
+ public boolean isReachable(DeviceId deviceId) {
+ OpenFlowSwitch sw = controller.getSwitch(dpid(deviceId.uri()));
+ if (sw == null || !sw.isConnected()) {
return false;
}
return true;
- //return checkChannel(device, sw);
}
@Override
public void triggerProbe(Device device) {
- LOG.info("Triggering probe on device {}", device.id());
+ final DeviceId deviceId = device.id();
+ LOG.info("Triggering probe on device {}", deviceId);
- OpenFlowSwitch sw = controller.getSwitch(dpid(device.id().uri()));
- //if (!checkChannel(device, sw)) {
- // LOG.error("Failed to probe device {} on sw={}", device, sw);
- // providerService.deviceDisconnected(device.id());
- //return;
- //}
+ final Dpid dpid = dpid(deviceId.uri());
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
+ if (sw == null || !sw.isConnected()) {
+ LOG.error("Failed to probe device {} on sw={}", device, sw);
+ providerService.deviceDisconnected(deviceId);
+ } else {
+ LOG.trace("Confirmed device {} connection", device);
+ // FIXME require something like below to match javadoc description
+ // but this starts infinite loop with current DeviceManager
+// final ChassisId cId = new ChassisId(dpid.value());
+// final Type deviceType = device.type();
+// DeviceDescription description =
+// new DefaultDeviceDescription(deviceId.uri(), deviceType,
+// sw.manfacturerDescription(),
+// sw.hardwareDescription(),
+// sw.softwareDescription(),
+// sw.serialNumber(),
+// cId);
+// providerService.deviceConnected(deviceId, description);
+ }
// Prompt an update of port information. We can use any XID for this.
OFFactory fact = sw.factory();
@@ -159,22 +170,22 @@
// }
@Override
- public void roleChanged(Device device, MastershipRole newRole) {
+ public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
switch (newRole) {
case MASTER:
- controller.setRole(dpid(device.id().uri()), RoleState.MASTER);
+ controller.setRole(dpid(deviceId.uri()), RoleState.MASTER);
break;
case STANDBY:
- controller.setRole(dpid(device.id().uri()), RoleState.EQUAL);
+ controller.setRole(dpid(deviceId.uri()), RoleState.EQUAL);
break;
case NONE:
- controller.setRole(dpid(device.id().uri()), RoleState.SLAVE);
+ controller.setRole(dpid(deviceId.uri()), RoleState.SLAVE);
break;
default:
LOG.error("Unknown Mastership state : {}", newRole);
}
- LOG.info("Accepting mastership role change for device {}", device.id());
+ LOG.info("Accepting mastership role change for device {}", deviceId);
}
private class InternalDeviceProvider implements OpenFlowSwitchListener {
@@ -226,23 +237,31 @@
}
@Override
- public void roleAssertFailed(Dpid dpid, RoleState role) {
- MastershipRole failed;
- switch (role) {
+ public void receivedRoleReply(Dpid dpid, RoleState requested, RoleState response) {
+ MastershipRole request = roleOf(requested);
+ MastershipRole reply = roleOf(response);
+
+ providerService.receivedRoleReply(deviceId(uri(dpid)), request, reply);
+ }
+
+ /**
+ * Translates a RoleState to the corresponding MastershipRole.
+ *
+ * @param response
+ * @return a MastershipRole
+ */
+ private MastershipRole roleOf(RoleState response) {
+ switch (response) {
case MASTER:
- failed = MastershipRole.MASTER;
- break;
+ return MastershipRole.MASTER;
case EQUAL:
- failed = MastershipRole.STANDBY;
- break;
+ return MastershipRole.STANDBY;
case SLAVE:
- failed = MastershipRole.NONE;
- break;
+ return MastershipRole.NONE;
default:
- LOG.warn("unknown role {}", role);
- return;
+ LOG.warn("unknown role {}", response);
+ return null;
}
- providerService.unableToAssertRole(deviceId(uri(dpid)), failed);
}
/**
diff --git a/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java b/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java
index e7e57b2..88c68a9 100644
--- a/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java
+++ b/providers/openflow/device/src/test/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProviderTest.java
@@ -105,11 +105,11 @@
@Test
public void roleChanged() {
- provider.roleChanged(DEV1, MASTER);
+ provider.roleChanged(DID1, MASTER);
assertEquals("Should be MASTER", RoleState.MASTER, controller.roleMap.get(DPID1));
- provider.roleChanged(DEV1, STANDBY);
+ provider.roleChanged(DID1, STANDBY);
assertEquals("Should be EQUAL", RoleState.EQUAL, controller.roleMap.get(DPID1));
- provider.roleChanged(DEV1, NONE);
+ provider.roleChanged(DID1, NONE);
assertEquals("Should be SLAVE", RoleState.SLAVE, controller.roleMap.get(DPID1));
}
@@ -136,12 +136,13 @@
}
@Test
- public void roleAssertFailed() {
- controller.listener.roleAssertFailed(DPID1, RoleState.MASTER);
+ public void receivedRoleReply() {
+ // check translation capabilities
+ controller.listener.receivedRoleReply(DPID1, RoleState.MASTER, RoleState.MASTER);
assertEquals("wrong role reported", DPID1, registry.roles.get(MASTER));
- controller.listener.roleAssertFailed(DPID1, RoleState.EQUAL);
+ controller.listener.receivedRoleReply(DPID1, RoleState.EQUAL, RoleState.MASTER);
assertEquals("wrong role reported", DPID1, registry.roles.get(STANDBY));
- controller.listener.roleAssertFailed(DPID1, RoleState.SLAVE);
+ controller.listener.receivedRoleReply(DPID1, RoleState.SLAVE, RoleState.MASTER);
assertEquals("wrong role reported", DPID1, registry.roles.get(NONE));
}
@@ -210,8 +211,9 @@
}
@Override
- public void unableToAssertRole(DeviceId deviceId, MastershipRole role) {
- roles.put(role, Dpid.dpid(deviceId.uri()));
+ public void receivedRoleReply(DeviceId deviceId,
+ MastershipRole requested, MastershipRole response) {
+ roles.put(requested, Dpid.dpid(deviceId.uri()));
}
}
@@ -368,11 +370,12 @@
}
@Override
- public void disconnectSwitch() {
+ public boolean isConnected() {
+ return true;
}
@Override
- public void returnRoleAssertFailure(RoleState role) {
+ public void disconnectSwitch() {
}
@Override
@@ -380,6 +383,10 @@
return false;
}
+ @Override
+ public void returnRoleReply(RoleState requested, RoleState reponse) {
+ }
+
}
}
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
index 0a0c0c7..0caf06b 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/FlowModBuilder.java
@@ -147,7 +147,8 @@
ip = (IPCriterion) c;
if (ip.ip().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH) {
IpAddress maskAddr =
- IpAddress.makeMaskPrefix(ip.ip().prefixLength());
+ IpAddress.makeMaskPrefix(ip.ip().address().version(),
+ ip.ip().prefixLength());
Masked<IPv4Address> maskedIp =
Masked.of(IPv4Address.of(ip.ip().address().toInt()),
IPv4Address.of(maskAddr.toInt()));
@@ -161,7 +162,8 @@
ip = (IPCriterion) c;
if (ip.ip().prefixLength() != IpPrefix.MAX_INET_MASK_LENGTH) {
IpAddress maskAddr =
- IpAddress.makeMaskPrefix(ip.ip().prefixLength());
+ IpAddress.makeMaskPrefix(ip.ip().address().version(),
+ ip.ip().prefixLength());
Masked<IPv4Address> maskedIp =
Masked.of(IPv4Address.of(ip.ip().address().toInt()),
IPv4Address.of(maskAddr.toInt()));
diff --git a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
index 53a49b6..018d6f3 100644
--- a/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onlab/onos/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -302,7 +302,10 @@
}
@Override
- public void roleAssertFailed(Dpid dpid, RoleState role) {}
+ public void receivedRoleReply(Dpid dpid, RoleState requested,
+ RoleState response) {
+ // Do nothing here for now.
+ }
private synchronized void pushFlowMetrics(Dpid dpid, OFStatsReply stats) {
if (stats.getStatsType() != OFStatsType.FLOW) {
diff --git a/providers/openflow/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java b/providers/openflow/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
index e563c34..3c08a2f 100644
--- a/providers/openflow/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
+++ b/providers/openflow/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
@@ -126,7 +126,8 @@
if (eth.getEtherType() == Ethernet.TYPE_ARP) {
ARP arp = (ARP) eth.getPayload();
IpAddress ip =
- IpAddress.valueOf(arp.getSenderProtocolAddress());
+ IpAddress.valueOf(IpAddress.Version.INET,
+ arp.getSenderProtocolAddress());
HostDescription hdescr =
new DefaultHostDescription(eth.getSourceMAC(), vlan, hloc, ip);
providerService.hostDetected(hid, hdescr);
diff --git a/providers/openflow/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java b/providers/openflow/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java
index 9205517..d227116 100644
--- a/providers/openflow/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java
+++ b/providers/openflow/host/src/test/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProviderTest.java
@@ -213,8 +213,8 @@
Ethernet eth = new Ethernet();
eth.setEtherType(Ethernet.TYPE_ARP)
.setVlanID(VLAN.toShort())
- .setSourceMACAddress(MAC.toBytes())
- .setDestinationMACAddress(BCMAC.getAddress())
+ .setSourceMACAddress(MAC)
+ .setDestinationMACAddress(BCMAC)
.setPayload(arp);
return eth;
diff --git a/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java b/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
index 02ba907..f32ca55 100644
--- a/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
+++ b/providers/openflow/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
@@ -160,7 +160,8 @@
}
@Override
- public void roleAssertFailed(Dpid dpid, RoleState role) {
+ public void receivedRoleReply(Dpid dpid, RoleState requested,
+ RoleState response) {
// do nothing for this.
}
diff --git a/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java b/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
index 32339f2..a6b0ac3 100644
--- a/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
+++ b/providers/openflow/link/src/test/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProviderTest.java
@@ -475,11 +475,12 @@
}
@Override
- public void disconnectSwitch() {
+ public boolean isConnected() {
+ return true;
}
@Override
- public void returnRoleAssertFailure(RoleState role) {
+ public void disconnectSwitch() {
}
@Override
@@ -487,5 +488,9 @@
return false;
}
+ @Override
+ public void returnRoleReply(RoleState requested, RoleState reponse) {
+ }
+
}
}
diff --git a/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java b/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
index ed682d6..c27e084 100644
--- a/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
+++ b/providers/openflow/packet/src/test/java/org/onlab/onos/provider/of/packet/impl/OpenFlowPacketProviderTest.java
@@ -406,11 +406,12 @@
}
@Override
- public void disconnectSwitch() {
+ public boolean isConnected() {
+ return true;
}
@Override
- public void returnRoleAssertFailure(RoleState role) {
+ public void disconnectSwitch() {
}
@Override
@@ -418,6 +419,10 @@
return false;
}
+ @Override
+ public void returnRoleReply(RoleState requested, RoleState reponse) {
+ }
+
}
}
diff --git a/tools/test/bin/find-node.sh b/tools/test/bin/find-node.sh
new file mode 100644
index 0000000..e76a84a
--- /dev/null
+++ b/tools/test/bin/find-node.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+validate_number () {
+ local re="^[0-9]+$"
+ if [[ ! $1 =~ $re ]] ; then
+ return 1
+ fi
+
+ return 0
+}
+
+find_node () {
+ if validate_number $1 ; then
+ # input is a number, try to find if an OC node is defined
+
+ oc_try="OC$1"
+ node=${!oc_try}
+
+ if [ -n "$node" ]; then
+ # node lookup succeeded, return node
+ echo $node
+ else
+ # node lookup failed, return original input
+ echo $1
+ fi
+
+ else
+ echo $1
+ fi
+
+ return 0
+}
diff --git a/tools/test/bin/onos b/tools/test/bin/onos
index 653b7f3c..a0c126c 100755
--- a/tools/test/bin/onos
+++ b/tools/test/bin/onos
@@ -5,8 +5,9 @@
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
[ "$1" = "-w" ] && shift && onos-wait-for-start $1
-[ -n "$1" ] && OCI=$1 && shift
+[ -n "$1" ] && OCI=$(find_node $1) && shift
client -h $OCI -u karaf "$@" 2>/dev/null
diff --git a/tools/test/bin/onos-log b/tools/test/bin/onos-log
index a336462..ff52eee 100755
--- a/tools/test/bin/onos-log
+++ b/tools/test/bin/onos-log
@@ -5,12 +5,14 @@
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
+. $ONOS_ROOT/tools/test/bin/find-node.sh
less=0
-
[ "$1" = "-l" ] && shift && less=1
-remote=$ONOS_USER@${1:-$OCI}
+remote=$(find_node $1)
+
+remote=$ONOS_USER@${remote:-$OCI}
instance=$2
[ -n "$instance" ] && \
diff --git a/utils/misc/src/main/java/org/onlab/packet/Ethernet.java b/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
index 70a52e2..96ec021 100644
--- a/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
+++ b/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
@@ -18,6 +18,8 @@
package org.onlab.packet;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
@@ -86,6 +88,17 @@
* @param destMac the destination MAC to set
* @return the Ethernet frame
*/
+ public Ethernet setDestinationMACAddress(final MacAddress destMac) {
+ this.destinationMACAddress = checkNotNull(destMac);
+ return this;
+ }
+
+ /**
+ * Sets the destination MAC address.
+ *
+ * @param destMac the destination MAC to set
+ * @return the Ethernet frame
+ */
public Ethernet setDestinationMACAddress(final byte[] destMac) {
this.destinationMACAddress = MacAddress.valueOf(destMac);
return this;
@@ -126,6 +139,17 @@
* @param sourceMac the source MAC to set
* @return the Ethernet frame
*/
+ public Ethernet setSourceMACAddress(final MacAddress sourceMac) {
+ this.sourceMACAddress = checkNotNull(sourceMac);
+ return this;
+ }
+
+ /**
+ * Sets the source MAC address.
+ *
+ * @param sourceMac the source MAC to set
+ * @return the Ethernet frame
+ */
public Ethernet setSourceMACAddress(final byte[] sourceMac) {
this.sourceMACAddress = MacAddress.valueOf(sourceMac);
return this;
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
index 33be226..77ba9b0 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpAddress.java
@@ -15,10 +15,18 @@
*/
package org.onlab.packet;
+import java.net.InetAddress;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Objects;
-import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.net.InetAddresses;
+import com.google.common.primitives.UnsignedBytes;
+
+import static com.google.common.base.Preconditions.checkState;
/**
* A class representing an IP address.
@@ -40,87 +48,26 @@
/**
* Constructor for given IP address version and address octets.
*
+ * @param version the IP address version
* @param value the IP address value stored in network byte order
* (i.e., the most significant byte first)
- * @param value the IP address value
+ * @throws IllegalArgumentException if the arguments are invalid
*/
private IpAddress(Version version, byte[] value) {
+ checkArguments(version, value, 0);
this.version = version;
- this.octets = Arrays.copyOf(value, INET_BYTE_LENGTH);
- }
-
- /**
- * Converts an integer into an IPv4 address.
- *
- * @param value an integer representing an IPv4 address value
- * @return an IP address
- */
- public static IpAddress valueOf(int value) {
- byte[] bytes =
- ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(value).array();
- return new IpAddress(Version.INET, bytes);
- }
-
- /**
- * Converts a byte array into an IP address.
- *
- * @param value the IP address value stored in network byte order
- * (i.e., the most significant byte first)
- * @return an IP address
- */
- public static IpAddress valueOf(byte[] value) {
- checkNotNull(value);
- return new IpAddress(Version.INET, value);
- }
-
- /**
- * Converts a byte array and a given offset from the beginning of the
- * array into an IP address.
- * <p>
- * The IP address is stored in network byte order (i.e., the most
- * significant byte first).
- * </p>
- * @param value the value to use
- * @param offset the offset in bytes from the beginning of the byte array
- * @return an IP address
- */
- public static IpAddress valueOf(byte[] value, int offset) {
- // Verify the arguments
- if ((offset < 0) || (offset + INET_BYTE_LENGTH > value.length)) {
- String msg;
- if (value.length < INET_BYTE_LENGTH) {
- msg = "Invalid IPv4 address array: array length: " +
- value.length + ". Must be at least " + INET_BYTE_LENGTH;
- } else {
- msg = "Invalid IPv4 address array: array offset: " +
- offset + ". Must be in the interval [0, " +
- (value.length - INET_BYTE_LENGTH) + "]";
- }
- throw new IllegalArgumentException(msg);
+ switch (version) {
+ case INET:
+ this.octets = Arrays.copyOf(value, INET_BYTE_LENGTH);
+ break;
+ case INET6:
+ this.octets = Arrays.copyOf(value, INET6_BYTE_LENGTH);
+ break;
+ default:
+ // Should not be reached
+ this.octets = null;
+ break;
}
-
- byte[] bc = Arrays.copyOfRange(value, offset, value.length);
- return IpAddress.valueOf(bc);
- }
-
- /**
- * Converts a dotted-decimal string (x.x.x.x) into an IPv4 address.
- *
- * @param address an IP address in string form, e.g. "10.0.0.1"
- * @return an IP address
- */
- public static IpAddress valueOf(String address) {
- final String[] net = address.split("\\.");
- if (net.length != INET_BYTE_LENGTH) {
- String msg = "Malformed IPv4 address string: " + address + "." +
- "Address must have four decimal values separated by dots (.)";
- throw new IllegalArgumentException(msg);
- }
- final byte[] bytes = new byte[INET_BYTE_LENGTH];
- for (int i = 0; i < INET_BYTE_LENGTH; i++) {
- bytes[i] = (byte) Short.parseShort(net[i], 10);
- }
- return new IpAddress(Version.INET, bytes);
}
/**
@@ -138,11 +85,12 @@
* @return a byte array
*/
public byte[] toOctets() {
- return Arrays.copyOf(this.octets, INET_BYTE_LENGTH);
+ return Arrays.copyOf(octets, octets.length);
}
/**
* Returns the integral value of this IP address.
+ * TODO: This method should be moved to Ip4Address.
*
* @return the IP address's value as an integer
*/
@@ -152,24 +100,152 @@
}
/**
+ * Computes the IP address byte length for a given IP version.
+ *
+ * @param version the IP version
+ * @return the IP address byte length for the IP version
+ * @throws IllegalArgumentException if the IP version is invalid
+ */
+ public static int byteLength(Version version) {
+ switch (version) {
+ case INET:
+ return INET_BYTE_LENGTH;
+ case INET6:
+ return INET6_BYTE_LENGTH;
+ default:
+ String msg = "Invalid IP version " + version;
+ throw new IllegalArgumentException(msg);
+ }
+ }
+
+ /**
+ * Converts an integer into an IPv4 address.
+ *
+ * @param value an integer representing an IPv4 address value
+ * @return an IP address
+ */
+ public static IpAddress valueOf(int value) {
+ byte[] bytes =
+ ByteBuffer.allocate(INET_BYTE_LENGTH).putInt(value).array();
+ return new IpAddress(Version.INET, bytes);
+ }
+
+ /**
+ * Converts a byte array into an IP address.
+ *
+ * @param version the IP address version
+ * @param value the IP address value stored in network byte order
+ * (i.e., the most significant byte first)
+ * @return an IP address
+ * @throws IllegalArgumentException if the arguments are invalid
+ */
+ public static IpAddress valueOf(Version version, byte[] value) {
+ return new IpAddress(version, value);
+ }
+
+ /**
+ * Converts a byte array and a given offset from the beginning of the
+ * array into an IP address.
+ * <p>
+ * The IP address is stored in network byte order (i.e., the most
+ * significant byte first).
+ * </p>
+ * @param version the IP address version
+ * @param value the value to use
+ * @param offset the offset in bytes from the beginning of the byte array
+ * @return an IP address
+ * @throws IllegalArgumentException if the arguments are invalid
+ */
+ public static IpAddress valueOf(Version version, byte[] value,
+ int offset) {
+ checkArguments(version, value, offset);
+ byte[] bc = Arrays.copyOfRange(value, offset, value.length);
+ return IpAddress.valueOf(version, bc);
+ }
+
+ /**
+ * Converts an InetAddress into an IP address.
+ *
+ * @param inetAddress the InetAddress value to use
+ * @return an IP address
+ * @throws IllegalArgumentException if the argument is invalid
+ */
+ public static IpAddress valueOf(InetAddress inetAddress) {
+ byte[] bytes = inetAddress.getAddress();
+ if (inetAddress instanceof Inet4Address) {
+ return new IpAddress(Version.INET, bytes);
+ }
+ if (inetAddress instanceof Inet6Address) {
+ return new IpAddress(Version.INET6, bytes);
+ }
+ // Use the number of bytes as a hint
+ if (bytes.length == INET_BYTE_LENGTH) {
+ return new IpAddress(Version.INET, bytes);
+ }
+ if (bytes.length == INET6_BYTE_LENGTH) {
+ return new IpAddress(Version.INET6, bytes);
+ }
+ final String msg = "Unrecognized IP version address string: " +
+ inetAddress.toString();
+ throw new IllegalArgumentException(msg);
+ }
+
+ /**
+ * Converts an IPv4 or IPv6 string literal (e.g., "10.2.3.4" or
+ * "1111:2222::8888") into an IP address.
+ *
+ * @param value an IP address value in string form
+ * @return an IP address
+ * @throws IllegalArgumentException if the argument is invalid
+ */
+ public static IpAddress valueOf(String value) {
+ InetAddress inetAddress = null;
+ try {
+ inetAddress = InetAddresses.forString(value);
+ } catch (IllegalArgumentException e) {
+ final String msg = "Invalid IP address string: " + value;
+ throw new IllegalArgumentException(msg);
+ }
+ return valueOf(inetAddress);
+ }
+
+ /**
* Creates an IP network mask prefix.
*
+ * @param version the IP address version
* @param prefixLength the length of the mask prefix. Must be in the
- * interval [0, 32] for IPv4
+ * interval [0, 32] for IPv4, or [0, 128] for IPv6
* @return a new IP address that contains a mask prefix of the
* specified length
+ * @throws IllegalArgumentException if the arguments are invalid
*/
- public static IpAddress makeMaskPrefix(int prefixLength) {
+ public static IpAddress makeMaskPrefix(Version version, int prefixLength) {
+ int addrByteLength = byteLength(version);
+ int addrBitLength = addrByteLength * Byte.SIZE;
+
// Verify the prefix length
- if ((prefixLength < 0) || (prefixLength > INET_BIT_LENGTH)) {
- final String msg = "Invalid IPv4 prefix length: " + prefixLength +
- ". Must be in the interval [0, 32].";
+ if ((prefixLength < 0) || (prefixLength > addrBitLength)) {
+ final String msg = "Invalid IP prefix length: " + prefixLength +
+ ". Must be in the interval [0, " + addrBitLength + "].";
throw new IllegalArgumentException(msg);
}
- long v =
- (0xffffffffL << (INET_BIT_LENGTH - prefixLength)) & 0xffffffffL;
- return IpAddress.valueOf((int) v);
+ // Number of bytes and extra bits that should be all 1s
+ int maskBytes = prefixLength / Byte.SIZE;
+ int maskBits = prefixLength % Byte.SIZE;
+ byte[] mask = new byte[addrByteLength];
+
+ // Set the bytes and extra bits to 1s
+ for (int i = 0; i < maskBytes; i++) {
+ mask[i] = (byte) 0xff; // Set mask bytes to 1s
+ }
+ for (int i = maskBytes; i < addrByteLength; i++) {
+ mask[i] = 0; // Set remaining bytes to 0s
+ }
+ if (maskBits > 0) {
+ mask[maskBytes] = (byte) (0xff << (Byte.SIZE - maskBits));
+ }
+ return new IpAddress(version, mask);
}
/**
@@ -178,27 +254,38 @@
*
* @param addr the address to mask
* @param prefixLength the length of the mask prefix. Must be in the
- * interval [0, 32] for IPv4
+ * interval [0, 32] for IPv4, or [0, 128] for IPv6
* @return a new IP address that is masked with a mask prefix of the
* specified length
+ * @throws IllegalArgumentException if the prefix length is invalid
*/
public static IpAddress makeMaskedAddress(final IpAddress addr,
int prefixLength) {
- IpAddress mask = IpAddress.makeMaskPrefix(prefixLength);
- byte[] net = new byte[INET_BYTE_LENGTH];
+ IpAddress mask = IpAddress.makeMaskPrefix(addr.version(),
+ prefixLength);
+ byte[] net = new byte[mask.octets.length];
// Mask each byte
- for (int i = 0; i < INET_BYTE_LENGTH; i++) {
+ for (int i = 0; i < net.length; i++) {
net[i] = (byte) (addr.octets[i] & mask.octets[i]);
}
- return IpAddress.valueOf(net);
+ return IpAddress.valueOf(addr.version(), net);
}
@Override
public int compareTo(IpAddress o) {
- Long lv = ((long) this.toInt()) & 0xffffffffL;
- Long rv = ((long) o.toInt()) & 0xffffffffL;
- return lv.compareTo(rv);
+ // Compare first the version
+ if (this.version != o.version) {
+ return this.version.compareTo(o.version);
+ }
+
+ // Compare the bytes, one-by-one
+ for (int i = 0; i < this.octets.length; i++) {
+ if (this.octets[i] != o.octets[i]) {
+ return UnsignedBytes.compare(this.octets[i], o.octets[i]);
+ }
+ }
+ return 0; // Equal
}
@Override
@@ -222,18 +309,67 @@
@Override
/*
* (non-Javadoc)
- * The format is "x.x.x.x" for IPv4 addresses.
+ * The string representation of the IP address: "x.x.x.x" for IPv4
+ * addresses, or ':' separated string for IPv6 addresses.
*
* @see java.lang.Object#toString()
*/
public String toString() {
- final StringBuilder builder = new StringBuilder();
- for (final byte b : this.octets) {
- if (builder.length() > 0) {
- builder.append(".");
- }
- builder.append(String.format("%d", b & 0xff));
+ InetAddress inetAddr = null;
+ try {
+ inetAddr = InetAddress.getByAddress(octets);
+ } catch (UnknownHostException e) {
+ // Should never happen
+ checkState(false, "Internal error: Ip6Address.toString()");
+ return "[Invalid IP Address]";
}
- return builder.toString();
+ return InetAddresses.toAddrString(inetAddr);
+ }
+
+ /**
+ * Gets the IP address name for the IP address version.
+ *
+ * @param version the IP address version
+ * @return the IP address name for the IP address version
+ */
+ private static String addressName(Version version) {
+ switch (version) {
+ case INET:
+ return "IPv4";
+ case INET6:
+ return "IPv6";
+ default:
+ break;
+ }
+ return "UnknownIP(" + version + ")";
+ }
+
+ /**
+ * Checks whether the arguments are valid.
+ *
+ * @param version the IP address version
+ * @param value the IP address value stored in a byte array
+ * @param offset the offset in bytes from the beginning of the byte
+ * array with the address
+ * @throws IllegalArgumentException if any of the arguments is invalid
+ */
+ private static void checkArguments(Version version, byte[] value,
+ int offset) {
+ // Check the offset and byte array length
+ int addrByteLength = byteLength(version);
+ if ((offset < 0) || (offset + addrByteLength > value.length)) {
+ String msg;
+ if (value.length < addrByteLength) {
+ msg = "Invalid " + addressName(version) +
+ " address array: array length: " + value.length +
+ ". Must be at least " + addrByteLength;
+ } else {
+ msg = "Invalid " + addressName(version) +
+ " address array: array offset: " + offset +
+ ". Must be in the interval [0, " +
+ (value.length - addrByteLength) + "]";
+ }
+ throw new IllegalArgumentException(msg);
+ }
}
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java b/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
index 180b771..3cde79d 100644
--- a/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
+++ b/utils/misc/src/main/java/org/onlab/packet/IpPrefix.java
@@ -76,12 +76,15 @@
/**
* Converts a byte array and a prefix length into an IP prefix.
*
+ * @param version the IP address version
* @param address the IP address value stored in network byte order
* @param prefixLength the prefix length
* @return an IP prefix
*/
- public static IpPrefix valueOf(byte[] address, int prefixLength) {
- return new IpPrefix(IpAddress.valueOf(address), prefixLength);
+ public static IpPrefix valueOf(IpAddress.Version version, byte[] address,
+ int prefixLength) {
+ return new IpPrefix(IpAddress.valueOf(version, address),
+ prefixLength);
}
/**
diff --git a/utils/misc/src/main/java/org/onlab/packet/MacAddress.java b/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
index 5675a31..5c59d22 100644
--- a/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
+++ b/utils/misc/src/main/java/org/onlab/packet/MacAddress.java
@@ -25,9 +25,6 @@
public static final MacAddress ZERO = valueOf("00:00:00:00:00:00");
public static final MacAddress BROADCAST = valueOf("ff:ff:ff:ff:ff:ff");
- public static final byte[] ZERO_MAC_ADDRESS = ZERO.getAddress();
- public static final byte[] BROADCAST_MAC = BROADCAST.getAddress();
-
private static final byte[] LL = new byte[]{
0x01, (byte) 0x80, (byte) 0xc2, 0x00, 0x00,
0x00, 0x0e, 0x03
@@ -217,8 +214,4 @@
}
return builder.toString();
}
-
- public byte[] getAddress() {
- return this.address;
- }
}
diff --git a/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java b/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
index df3880f..0b33c45 100644
--- a/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
+++ b/utils/misc/src/main/java/org/onlab/packet/ONOSLLDP.java
@@ -64,7 +64,7 @@
setName(DEFAULT_NAME);
setDevice(DEFAULT_DEVICE);
setOptionalTLVList(Lists.<LLDPTLV>newArrayList(nameTLV, deviceTLV));
- setTtl(new LLDPTLV().setType((byte) TTL_TLV_TYPE)
+ setTtl(new LLDPTLV().setType(TTL_TLV_TYPE)
.setLength((short) ttlValue.length)
.setValue(ttlValue));
@@ -94,7 +94,7 @@
public void setChassisId(final ChassisId chassisId) {
MacAddress chassisMac = MacAddress.valueOf(chassisId.value());
byte[] chassis = ArrayUtils.addAll(new byte[] {CHASSIS_TLV_SUBTYPE},
- chassisMac.getAddress());
+ chassisMac.toBytes());
LLDPTLV chassisTLV = new LLDPTLV();
chassisTLV.setLength(CHASSIS_TLV_SIZE);
diff --git a/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java b/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java
new file mode 100644
index 0000000..4237829
--- /dev/null
+++ b/utils/misc/src/test/java/org/onlab/packet/IpAddressTest.java
@@ -0,0 +1,810 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onlab.packet;
+
+import com.google.common.net.InetAddresses;
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+
+import java.net.InetAddress;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Tests for class {@link IpAddress}.
+ */
+public class IpAddressTest {
+ /**
+ * Tests the immutability of {@link IpAddress}.
+ */
+ @Test
+ public void testImmutable() {
+ assertThatClassIsImmutable(IpAddress.class);
+ }
+
+ /**
+ * Tests the length of the address in bytes (octets).
+ */
+ @Test
+ public void testAddrByteLength() {
+ assertThat(IpAddress.INET_BYTE_LENGTH, is(4));
+ assertThat(IpAddress.INET6_BYTE_LENGTH, is(16));
+ assertThat(IpAddress.byteLength(IpAddress.Version.INET), is(4));
+ assertThat(IpAddress.byteLength(IpAddress.Version.INET6), is(16));
+ }
+
+ /**
+ * Tests the length of the address in bits.
+ */
+ @Test
+ public void testAddrBitLength() {
+ assertThat(IpAddress.INET_BIT_LENGTH, is(32));
+ assertThat(IpAddress.INET6_BIT_LENGTH, is(128));
+ }
+
+ /**
+ * Tests returning the IP address version.
+ */
+ @Test
+ public void testVersion() {
+ IpAddress ipAddress;
+
+ // IPv4
+ ipAddress = IpAddress.valueOf("0.0.0.0");
+ assertThat(ipAddress.version(), is(IpAddress.Version.INET));
+
+ // IPv6
+ ipAddress = IpAddress.valueOf("::");
+ assertThat(ipAddress.version(), is(IpAddress.Version.INET6));
+ }
+
+ /**
+ * Tests returning an IPv4 address as a byte array.
+ */
+ @Test
+ public void testAddressToOctetsIPv4() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {1, 2, 3, 4};
+ ipAddress = IpAddress.valueOf("1.2.3.4");
+ assertThat(ipAddress.toOctets(), is(value1));
+
+ final byte[] value2 = new byte[] {0, 0, 0, 0};
+ ipAddress = IpAddress.valueOf("0.0.0.0");
+ assertThat(ipAddress.toOctets(), is(value2));
+
+ final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff};
+ ipAddress = IpAddress.valueOf("255.255.255.255");
+ assertThat(ipAddress.toOctets(), is(value3));
+ }
+
+ /**
+ * Tests returning an IPv6 address as a byte array.
+ */
+ @Test
+ public void testAddressToOctetsIPv6() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22,
+ 0x33, 0x33, 0x44, 0x44,
+ 0x55, 0x55, 0x66, 0x66,
+ 0x77, 0x77,
+ (byte) 0x88, (byte) 0x88};
+ ipAddress =
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+ assertThat(ipAddress.toOctets(), is(value1));
+
+ final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
+ ipAddress = IpAddress.valueOf("::");
+ assertThat(ipAddress.toOctets(), is(value2));
+
+ final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff};
+ ipAddress =
+ IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ assertThat(ipAddress.toOctets(), is(value3));
+ }
+
+ /**
+ * Tests returning an IPv4 address asn an integer.
+ */
+ @Test
+ public void testToint() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.valueOf("1.2.3.4");
+ assertThat(ipAddress.toInt(), is(0x01020304));
+
+ ipAddress = IpAddress.valueOf("0.0.0.0");
+ assertThat(ipAddress.toInt(), is(0));
+
+ ipAddress = IpAddress.valueOf("255.255.255.255");
+ assertThat(ipAddress.toInt(), is(-1));
+ }
+
+ /**
+ * Tests valueOf() converter for an integer value.
+ */
+ @Test
+ public void testValueOfForInteger() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.valueOf(0x01020304);
+ assertThat(ipAddress.toString(), is("1.2.3.4"));
+
+ ipAddress = IpAddress.valueOf(0);
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ ipAddress = IpAddress.valueOf(0xffffffff);
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests valueOf() converter for IPv4 byte array.
+ */
+ @Test
+ public void testValueOfByteArrayIPv4() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {1, 2, 3, 4};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value1);
+ assertThat(ipAddress.toString(), is("1.2.3.4"));
+
+ final byte[] value2 = new byte[] {0, 0, 0, 0};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value2);
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value3);
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests valueOf() converter for IPv6 byte array.
+ */
+ @Test
+ public void testValueOfByteArrayIPv6() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {0x11, 0x11, 0x22, 0x22,
+ 0x33, 0x33, 0x44, 0x44,
+ 0x55, 0x55, 0x66, 0x66,
+ 0x77, 0x77,
+ (byte) 0x88, (byte) 0x88};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value1);
+ assertThat(ipAddress.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+ final byte[] value2 = new byte[] {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value2);
+ assertThat(ipAddress.toString(), is("::"));
+
+ final byte[] value3 = new byte[] {(byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value3);
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+ }
+
+ /**
+ * Tests invalid valueOf() converter for a null array for IPv4.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testInvalidValueOfNullArrayIPv4() {
+ IpAddress ipAddress;
+
+ final byte[] fromArray = null;
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, fromArray);
+ }
+
+ /**
+ * Tests invalid valueOf() converter for a null array for IPv6.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testInvalidValueOfNullArrayIPv6() {
+ IpAddress ipAddress;
+
+ final byte[] fromArray = null;
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, fromArray);
+ }
+
+ /**
+ * Tests invalid valueOf() converger for an array that is too short for
+ * IPv4.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidValueOfShortArrayIPv4() {
+ IpAddress ipAddress;
+
+ final byte[] fromArray = new byte[] {1, 2, 3};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, fromArray);
+ }
+
+ /**
+ * Tests invalid valueOf() converger for an array that is too short for
+ * IPv6.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidValueOfShortArrayIPv6() {
+ IpAddress ipAddress;
+
+ final byte[] fromArray = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, fromArray);
+ }
+
+ /**
+ * Tests valueOf() converter for IPv4 byte array and an offset.
+ */
+ @Test
+ public void testValueOfByteArrayOffsetIPv4() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {11, 22, 33, // Preamble
+ 1, 2, 3, 4,
+ 44, 55}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value1, 3);
+ assertThat(ipAddress.toString(), is("1.2.3.4"));
+
+ final byte[] value2 = new byte[] {11, 22, // Preamble
+ 0, 0, 0, 0,
+ 33}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value2, 2);
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ final byte[] value3 = new byte[] {11, 22, // Preamble
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ 33}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value3, 2);
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests valueOf() converter for IPv6 byte array and an offset.
+ */
+ @Test
+ public void testValueOfByteArrayOffsetIPv6() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {11, 22, 33, // Preamble
+ 0x11, 0x11, 0x22, 0x22,
+ 0x33, 0x33, 0x44, 0x44,
+ 0x55, 0x55, 0x66, 0x66,
+ 0x77, 0x77,
+ (byte) 0x88, (byte) 0x88,
+ 44, 55}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value1, 3);
+ assertThat(ipAddress.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+ final byte[] value2 = new byte[] {11, 22, // Preamble
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 33}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value2, 2);
+ assertThat(ipAddress.toString(), is("::"));
+
+ final byte[] value3 = new byte[] {11, 22, // Preamble
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ 33}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value3, 2);
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+ }
+
+ /**
+ * Tests invalid valueOf() converger for an array and an invalid offset
+ * for IPv4.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidValueOfArrayInvalidOffsetIPv4() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {11, 22, 33, // Preamble
+ 1, 2, 3, 4,
+ 44, 55}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET, value1, 6);
+ }
+
+ /**
+ * Tests invalid valueOf() converger for an array and an invalid offset
+ * for IPv6.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidValueOfArrayInvalidOffsetIPv6() {
+ IpAddress ipAddress;
+
+ final byte[] value1 = new byte[] {11, 22, 33, // Preamble
+ 0x11, 0x11, 0x22, 0x22,
+ 0x33, 0x33, 0x44, 0x44,
+ 0x55, 0x55, 0x66, 0x66,
+ 0x77, 0x77,
+ (byte) 0x88, (byte) 0x88,
+ 44, 55}; // Extra bytes
+ ipAddress = IpAddress.valueOf(IpAddress.Version.INET6, value1, 6);
+ }
+
+ /**
+ * Tests valueOf() converter for IPv4 InetAddress.
+ */
+ @Test
+ public void testValueOfInetAddressIPv4() {
+ IpAddress ipAddress;
+ InetAddress inetAddress;
+
+ inetAddress = InetAddresses.forString("1.2.3.4");
+ ipAddress = IpAddress.valueOf(inetAddress);
+ assertThat(ipAddress.toString(), is("1.2.3.4"));
+
+ inetAddress = InetAddresses.forString("0.0.0.0");
+ ipAddress = IpAddress.valueOf(inetAddress);
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ inetAddress = InetAddresses.forString("255.255.255.255");
+ ipAddress = IpAddress.valueOf(inetAddress);
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests valueOf() converter for IPv6 InetAddress.
+ */
+ @Test
+ public void testValueOfInetAddressIPv6() {
+ IpAddress ipAddress;
+ InetAddress inetAddress;
+
+ inetAddress =
+ InetAddresses.forString("1111:2222:3333:4444:5555:6666:7777:8888");
+ ipAddress = IpAddress.valueOf(inetAddress);
+ assertThat(ipAddress.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+ inetAddress = InetAddresses.forString("::");
+ ipAddress = IpAddress.valueOf(inetAddress);
+ assertThat(ipAddress.toString(), is("::"));
+
+ inetAddress =
+ InetAddresses.forString("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ ipAddress = IpAddress.valueOf(inetAddress);
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+ }
+
+ /**
+ * Tests valueOf() converter for IPv4 string.
+ */
+ @Test
+ public void testValueOfStringIPv4() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.valueOf("1.2.3.4");
+ assertThat(ipAddress.toString(), is("1.2.3.4"));
+
+ ipAddress = IpAddress.valueOf("0.0.0.0");
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ ipAddress = IpAddress.valueOf("255.255.255.255");
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests valueOf() converter for IPv6 string.
+ */
+ @Test
+ public void testValueOfStringIPv6() {
+ IpAddress ipAddress;
+
+ ipAddress =
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+ assertThat(ipAddress.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+ ipAddress = IpAddress.valueOf("::");
+ assertThat(ipAddress.toString(), is("::"));
+
+ ipAddress =
+ IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+ }
+
+ /**
+ * Tests invalid valueOf() converter for a null string.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testInvalidValueOfNullString() {
+ IpAddress ipAddress;
+
+ String fromString = null;
+ ipAddress = IpAddress.valueOf(fromString);
+ }
+
+ /**
+ * Tests invalid valueOf() converter for an empty string.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidValueOfEmptyString() {
+ IpAddress ipAddress;
+
+ String fromString = "";
+ ipAddress = IpAddress.valueOf(fromString);
+ }
+
+ /**
+ * Tests invalid valueOf() converter for an incorrect string.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidValueOfIncorrectString() {
+ IpAddress ipAddress;
+
+ String fromString = "NoSuchIpAddress";
+ ipAddress = IpAddress.valueOf(fromString);
+ }
+
+ /**
+ * Tests making a mask prefix for a given prefix length for IPv4.
+ */
+ @Test
+ public void testMakeMaskPrefixIPv4() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 25);
+ assertThat(ipAddress.toString(), is("255.255.255.128"));
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 0);
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 32);
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests making a mask prefix for a given prefix length for IPv6.
+ */
+ @Test
+ public void testMakeMaskPrefixIPv6() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 8);
+ assertThat(ipAddress.toString(), is("ff00::"));
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 120);
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ff00"));
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 0);
+ assertThat(ipAddress.toString(), is("::"));
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 128);
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 64);
+ assertThat(ipAddress.toString(), is("ffff:ffff:ffff:ffff::"));
+ }
+
+ /**
+ * Tests making a mask prefix for an invalid prefix length for IPv4:
+ * negative prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeNegativeMaskPrefixIPv4() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, -1);
+ }
+
+ /**
+ * Tests making a mask prefix for an invalid prefix length for IPv6:
+ * negative prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeNegativeMaskPrefixIPv6() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, -1);
+ }
+
+ /**
+ * Tests making a mask prefix for an invalid prefix length for IPv4:
+ * too long prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeTooLongMaskPrefixIPv4() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET, 33);
+ }
+
+ /**
+ * Tests making a mask prefix for an invalid prefix length for IPv6:
+ * too long prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeTooLongMaskPrefixIPv6() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.makeMaskPrefix(IpAddress.Version.INET6, 129);
+ }
+
+ /**
+ * Tests making of a masked address for IPv4.
+ */
+ @Test
+ public void testMakeMaskedAddressIPv4() {
+ IpAddress ipAddress = IpAddress.valueOf("1.2.3.5");
+ IpAddress ipAddressMasked;
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 24);
+ assertThat(ipAddressMasked.toString(), is("1.2.3.0"));
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 0);
+ assertThat(ipAddressMasked.toString(), is("0.0.0.0"));
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 32);
+ assertThat(ipAddressMasked.toString(), is("1.2.3.5"));
+ }
+
+ /**
+ * Tests making of a masked address for IPv6.
+ */
+ @Test
+ public void testMakeMaskedAddressIPv6() {
+ IpAddress ipAddress =
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8885");
+ IpAddress ipAddressMasked;
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 8);
+ assertThat(ipAddressMasked.toString(), is("1100::"));
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 120);
+ assertThat(ipAddressMasked.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8800"));
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 0);
+ assertThat(ipAddressMasked.toString(), is("::"));
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 128);
+ assertThat(ipAddressMasked.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8885"));
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 64);
+ assertThat(ipAddressMasked.toString(), is("1111:2222:3333:4444::"));
+ }
+
+ /**
+ * Tests making of a masked address for invalid prefix length for IPv4:
+ * negative prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeNegativeMaskedAddressIPv4() {
+ IpAddress ipAddress = IpAddress.valueOf("1.2.3.5");
+ IpAddress ipAddressMasked;
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, -1);
+ }
+
+ /**
+ * Tests making of a masked address for invalid prefix length for IPv6:
+ * negative prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeNegativeMaskedAddressIPv6() {
+ IpAddress ipAddress =
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8885");
+ IpAddress ipAddressMasked;
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, -1);
+ }
+
+ /**
+ * Tests making of a masked address for an invalid prefix length for IPv4:
+ * too long prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeTooLongMaskedAddressIPv4() {
+ IpAddress ipAddress = IpAddress.valueOf("1.2.3.5");
+ IpAddress ipAddressMasked;
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 33);
+ }
+
+ /**
+ * Tests making of a masked address for an invalid prefix length for IPv6:
+ * too long prefix length.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvalidMakeTooLongMaskedAddressIPv6() {
+ IpAddress ipAddress =
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8885");
+ IpAddress ipAddressMasked;
+
+ ipAddressMasked = IpAddress.makeMaskedAddress(ipAddress, 129);
+ }
+
+ /**
+ * Tests comparison of {@link IpAddress} for IPv4.
+ */
+ @Test
+ public void testComparisonIPv4() {
+ IpAddress addr1, addr2, addr3, addr4;
+
+ addr1 = IpAddress.valueOf("1.2.3.4");
+ addr2 = IpAddress.valueOf("1.2.3.4");
+ addr3 = IpAddress.valueOf("1.2.3.3");
+ addr4 = IpAddress.valueOf("1.2.3.5");
+ assertTrue(addr1.compareTo(addr2) == 0);
+ assertTrue(addr1.compareTo(addr3) > 0);
+ assertTrue(addr1.compareTo(addr4) < 0);
+
+ addr1 = IpAddress.valueOf("255.2.3.4");
+ addr2 = IpAddress.valueOf("255.2.3.4");
+ addr3 = IpAddress.valueOf("255.2.3.3");
+ addr4 = IpAddress.valueOf("255.2.3.5");
+ assertTrue(addr1.compareTo(addr2) == 0);
+ assertTrue(addr1.compareTo(addr3) > 0);
+ assertTrue(addr1.compareTo(addr4) < 0);
+ }
+
+ /**
+ * Tests comparison of {@link IpAddress} for IPv6.
+ */
+ @Test
+ public void testComparisonIPv6() {
+ IpAddress addr1, addr2, addr3, addr4;
+
+ addr1 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+ addr2 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+ addr3 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8887");
+ addr4 = IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8889");
+ assertTrue(addr1.compareTo(addr2) == 0);
+ assertTrue(addr1.compareTo(addr3) > 0);
+ assertTrue(addr1.compareTo(addr4) < 0);
+
+ addr1 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888");
+ addr2 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888");
+ addr3 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8887");
+ addr4 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8889");
+ assertTrue(addr1.compareTo(addr2) == 0);
+ assertTrue(addr1.compareTo(addr3) > 0);
+ assertTrue(addr1.compareTo(addr4) < 0);
+
+ addr1 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888");
+ addr2 = IpAddress.valueOf("ffff:2222:3333:4444:5555:6666:7777:8888");
+ addr3 = IpAddress.valueOf("ffff:2222:3333:4443:5555:6666:7777:8888");
+ addr4 = IpAddress.valueOf("ffff:2222:3333:4445:5555:6666:7777:8888");
+ assertTrue(addr1.compareTo(addr2) == 0);
+ assertTrue(addr1.compareTo(addr3) > 0);
+ assertTrue(addr1.compareTo(addr4) < 0);
+ }
+
+ /**
+ * Tests equality of {@link IpAddress} for IPv4.
+ */
+ @Test
+ public void testEqualityIPv4() {
+ new EqualsTester()
+ .addEqualityGroup(IpAddress.valueOf("1.2.3.4"),
+ IpAddress.valueOf("1.2.3.4"))
+ .addEqualityGroup(IpAddress.valueOf("1.2.3.5"),
+ IpAddress.valueOf("1.2.3.5"))
+ .addEqualityGroup(IpAddress.valueOf("0.0.0.0"),
+ IpAddress.valueOf("0.0.0.0"))
+ .addEqualityGroup(IpAddress.valueOf("255.255.255.255"),
+ IpAddress.valueOf("255.255.255.255"))
+ .testEquals();
+ }
+
+ /**
+ * Tests equality of {@link IpAddress} for IPv6.
+ */
+ @Test
+ public void testEqualityIPv6() {
+ new EqualsTester()
+ .addEqualityGroup(
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"),
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888"))
+ .addEqualityGroup(
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:888a"),
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:888a"))
+ .addEqualityGroup(
+ IpAddress.valueOf("::"),
+ IpAddress.valueOf("::"))
+ .addEqualityGroup(
+ IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"),
+ IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"))
+ .testEquals();
+ }
+
+ /**
+ * Tests object string representation for IPv4.
+ */
+ @Test
+ public void testToStringIPv4() {
+ IpAddress ipAddress;
+
+ ipAddress = IpAddress.valueOf("1.2.3.4");
+ assertThat(ipAddress.toString(), is("1.2.3.4"));
+
+ ipAddress = IpAddress.valueOf("0.0.0.0");
+ assertThat(ipAddress.toString(), is("0.0.0.0"));
+
+ ipAddress = IpAddress.valueOf("255.255.255.255");
+ assertThat(ipAddress.toString(), is("255.255.255.255"));
+ }
+
+ /**
+ * Tests object string representation for IPv6.
+ */
+ @Test
+ public void testToStringIPv6() {
+ IpAddress ipAddress;
+
+ ipAddress =
+ IpAddress.valueOf("1111:2222:3333:4444:5555:6666:7777:8888");
+ assertThat(ipAddress.toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+ ipAddress = IpAddress.valueOf("1111::8888");
+ assertThat(ipAddress.toString(), is("1111::8888"));
+
+ ipAddress = IpAddress.valueOf("1111::");
+ assertThat(ipAddress.toString(), is("1111::"));
+
+ ipAddress = IpAddress.valueOf("::8888");
+ assertThat(ipAddress.toString(), is("::8888"));
+
+ ipAddress = IpAddress.valueOf("::");
+ assertThat(ipAddress.toString(), is("::"));
+
+ ipAddress =
+ IpAddress.valueOf("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
+ assertThat(ipAddress.toString(),
+ is("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"));
+ }
+}
diff --git a/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java b/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java
index ce6a1e3..f5ad88b 100644
--- a/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java
+++ b/utils/misc/src/test/java/org/onlab/packet/IpPrefixTest.java
@@ -38,9 +38,11 @@
@Test
public void testEquality() {
- IpPrefix ip1 = IpPrefix.valueOf(BYTES1, IpPrefix.MAX_INET_MASK_LENGTH);
+ IpPrefix ip1 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, IpPrefix.MAX_INET_MASK_LENGTH);
IpPrefix ip2 = IpPrefix.valueOf(INTVAL1, IpPrefix.MAX_INET_MASK_LENGTH);
- IpPrefix ip3 = IpPrefix.valueOf(BYTES2, IpPrefix.MAX_INET_MASK_LENGTH);
+ IpPrefix ip3 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES2, IpPrefix.MAX_INET_MASK_LENGTH);
IpPrefix ip4 = IpPrefix.valueOf(INTVAL2, IpPrefix.MAX_INET_MASK_LENGTH);
IpPrefix ip5 = IpPrefix.valueOf(STRVAL);
@@ -50,16 +52,19 @@
.testEquals();
// string conversions
- IpPrefix ip6 = IpPrefix.valueOf(BYTES1, MASK_LENGTH);
+ IpPrefix ip6 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, MASK_LENGTH);
IpPrefix ip7 = IpPrefix.valueOf("10.0.0.10/16");
- IpPrefix ip8 = IpPrefix.valueOf(new byte [] {0xa, 0x0, 0x0, 0xc}, 16);
+ IpPrefix ip8 = IpPrefix.valueOf(IpAddress.Version.INET,
+ new byte [] {0xa, 0x0, 0x0, 0xc}, 16);
assertEquals("incorrect address conversion", ip6, ip7);
assertEquals("incorrect address conversion", ip5, ip8);
}
@Test
public void basics() {
- IpPrefix ip1 = IpPrefix.valueOf(BYTES1, MASK_LENGTH);
+ IpPrefix ip1 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, MASK_LENGTH);
final byte [] bytes = new byte [] {0xa, 0x0, 0x0, 0x0};
// check fields
@@ -74,7 +79,8 @@
@Test
public void netmasks() {
// masked
- IpPrefix ip1 = IpPrefix.valueOf(BYTES1, MASK_LENGTH);
+ IpPrefix ip1 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, MASK_LENGTH);
IpPrefix ip2 = IpPrefix.valueOf("10.0.0.10/16");
IpPrefix ip3 = IpPrefix.valueOf("10.0.0.0/16");
assertEquals("incorrect binary masked address",
@@ -87,9 +93,12 @@
@Test
public void testContainsIpPrefix() {
- IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31);
- IpPrefix slash32 = IpPrefix.valueOf(BYTES1, 32);
- IpPrefix differentSlash32 = IpPrefix.valueOf(BYTES2, 32);
+ IpPrefix slash31 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, 31);
+ IpPrefix slash32 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, 32);
+ IpPrefix differentSlash32 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES2, 32);
assertTrue(slash31.contains(differentSlash32));
assertFalse(differentSlash32.contains(slash31));
@@ -109,8 +118,9 @@
@Test
public void testContainsIpAddress() {
- IpPrefix slash31 = IpPrefix.valueOf(BYTES1, 31);
- IpAddress addr32 = IpAddress.valueOf(BYTES1);
+ IpPrefix slash31 = IpPrefix.valueOf(IpAddress.Version.INET,
+ BYTES1, 31);
+ IpAddress addr32 = IpAddress.valueOf(IpAddress.Version.INET, BYTES1);
assertTrue(slash31.contains(addr32));
diff --git a/utils/netty/pom.xml b/utils/netty/pom.xml
index fd0e8e0..436214f 100644
--- a/utils/netty/pom.xml
+++ b/utils/netty/pom.xml
@@ -73,6 +73,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
+ <version>${netty4.version}</version>
</dependency>
</dependencies>
diff --git a/web/api/src/main/java/org/onlab/onos/rest/ConfigProvider.java b/web/api/src/main/java/org/onlab/onos/rest/ConfigProvider.java
index 57e247f..e4a0763 100644
--- a/web/api/src/main/java/org/onlab/onos/rest/ConfigProvider.java
+++ b/web/api/src/main/java/org/onlab/onos/rest/ConfigProvider.java
@@ -244,7 +244,7 @@
}
@Override
- public void roleChanged(Device device, MastershipRole newRole) {
+ public void roleChanged(DeviceId device, MastershipRole newRole) {
}
@Override
@@ -257,7 +257,7 @@
}
@Override
- public boolean isReachable(Device device) {
+ public boolean isReachable(DeviceId device) {
return false;
}
}
diff --git a/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java b/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java
index 14795b2..b63e3e0 100644
--- a/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java
+++ b/web/gui/src/main/java/org/onlab/onos/gui/TopologyResource.java
@@ -101,7 +101,7 @@
new Prop("Vendor", device.manufacturer()),
new Prop("H/W Version", device.hwVersion()),
new Prop("S/W Version", device.swVersion()),
- new Prop("S/W Version", device.serialNumber()),
+ new Prop("Serial Number", device.serialNumber()),
new Separator(),
new Prop("Latitude", annot.value("latitude")),
new Prop("Longitude", annot.value("longitude")),