Praseed Balakrishnan

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

Showing 80 changed files with 2086 additions and 568 deletions
......@@ -368,12 +368,12 @@ public class OpticalConfigProvider extends AbstractProvider implements DevicePro
}
@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;
}
}
......
......@@ -246,11 +246,13 @@ public class BgpSession extends SimpleChannelHandler {
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 {}",
......
......@@ -105,7 +105,8 @@ public class BgpSessionManager {
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;
......
......@@ -74,7 +74,7 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand {
* @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 @@ public class AddPointToPointIntentCommand extends ConnectivityIntentCommand {
* @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 "";
......
......@@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
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 @@ import java.util.Set;
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 @@ public class IntentsListCommand extends AbstractShellCommand {
}
List<Intent> installable = service.getInstallableIntents(intent.id());
if (installable != null && !installable.isEmpty()) {
if (showInstallable && installable != null && !installable.isEmpty()) {
print(" installable=%s", installable);
}
}
......
/*
* 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);
}
}
}
}
/*
* 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());
}
}
}
......@@ -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>
......
......@@ -40,7 +40,9 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI
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 @@ public class MastershipEvent extends AbstractEvent<MastershipEvent.Type, DeviceI
* 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);
......
......@@ -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 {
}
......
/*
* 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();
}
......@@ -25,6 +25,14 @@ import org.onlab.onos.net.DeviceId;
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.
......
......@@ -24,7 +24,16 @@ import org.onlab.onos.store.Timestamp;
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.
*/
......
......@@ -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 @@ public interface DeviceProvider extends Provider {
* 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);
}
......
......@@ -61,12 +61,12 @@ public interface DeviceProviderService extends ProviderService<DeviceProvider> {
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);
}
......
......@@ -27,11 +27,14 @@ public final class FlowRuleBatchEvent extends AbstractEvent<FlowRuleBatchEvent.T
*/
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.
*/
......
......@@ -25,29 +25,29 @@ import com.google.common.collect.Lists;
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);
......
......@@ -200,7 +200,7 @@ public final class Instructions {
}
if (obj instanceof OutputInstruction) {
OutputInstruction that = (OutputInstruction) obj;
Objects.equals(port, that.port);
return Objects.equals(port, that.port);
}
return false;
......
......@@ -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 class BandwidthResourceAllocation extends BandwidthResourceRequest
public BandwidthResourceAllocation(Bandwidth bandwidth) {
super(bandwidth);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("bandwidth", bandwidth())
.toString();
}
}
......
......@@ -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 class BandwidthResourceRequest implements ResourceRequest {
public ResourceType type() {
return ResourceType.BANDWIDTH;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("bandwidth", bandwidth)
.toString();
}
}
......
......@@ -15,6 +15,8 @@
*/
package org.onlab.onos.net.resource;
import com.google.common.base.MoreObjects;
import java.util.Objects;
/**
......@@ -64,4 +66,11 @@ public class LambdaResourceAllocation extends LambdaResourceRequest
final LambdaResourceAllocation other = (LambdaResourceAllocation) obj;
return Objects.equals(this.lambda, other.lambda);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("lambda", lambda)
.toString();
}
}
......
......@@ -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 @@ public class LambdaResourceRequest implements ResourceRequest {
return ResourceType.LAMBDA;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.toString();
}
}
......
......@@ -17,6 +17,7 @@ package org.onlab.onos.net.device.impl;
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.ReferenceCardinality;
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.AbstractProviderRegistry;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
import com.google.common.collect.HashMultimap;
/**
* Provides implementation of the device SB &amp; NB APIs.
*/
......@@ -160,39 +158,15 @@ public class DeviceManager
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 @@ public class DeviceManager
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 @@ public class DeviceManager
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 @@ public class DeviceManager
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 @@ public class DeviceManager
checkNotNull(deviceId, DEVICE_ID_NULL);
checkValidity();
log.info("Device {} disconnected from this node", deviceId);
DeviceEvent event = null;
try {
......@@ -318,18 +303,18 @@ public class DeviceManager
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 @@ public class DeviceManager
"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 @@ public class DeviceManager
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 @@ public class DeviceManager
}
@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 @@ public class DeviceManager
// 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;
final boolean iHaveControl = myNodeId.equals(term.master());
if (iHaveControl) {
deviceClockProviderService.setMastershipTerm(did, term);
myNextRole = MASTER;
} else {
myNextRole = STANDBY;
}
} else if (event.roleInfo().backups().contains(myNodeId)) {
myNextRole = STANDBY;
} else {
myNextRole = NONE;
}
// 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);
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);
return;
// FIXME disconnect?
}
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");
return;
}
// device is connected to this node:
if (myNextRole == NONE) {
mastershipService.requestRoleFor(did);
final MastershipTerm term = termService.getMastershipTerm(did);
MastershipTerm term = termService.getMastershipTerm(did);
if (myNodeId.equals(term.master())) {
// became MASTER
// TODO: consider slicing out method for applying MASTER role
deviceClockProviderService.setMastershipTerm(did, term);
myNextRole = MASTER;
} else {
myNextRole = STANDBY;
}
}
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,
new DefaultDeviceDescription(
did.uri(), device.type(), device.manufacturer(),
device.hwVersion(), device.swVersion(),
device.serialNumber(), device.chassisId()));
applyRole(did, MastershipRole.MASTER);
deviceDescription);
post(devEvent);
} else {
applyRole(did, MastershipRole.STANDBY);
}
// 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;
}
}
// 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;
// }
// }
}
}
// Store delegate to re-post events emitted from the store.
......
......@@ -371,10 +371,11 @@ public class FlowRuleManager
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 @@ public class FlowRuleManager
Futures.getUnchecked(result)));
}
}, futureListeners);
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;
}
......
......@@ -67,6 +67,7 @@ public class HostMonitor implements TimerTask {
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 @@ public class HostMonitor implements TimerTask {
.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;
......
......@@ -132,7 +132,8 @@ public class ProxyArpManager implements ProxyArpService {
// 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 @@ public class ProxyArpManager implements ProxyArpService {
// 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 @@ public class ProxyArpManager implements ProxyArpService {
// 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 @@ public class ProxyArpManager implements ProxyArpService {
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 @@ public class ProxyArpManager implements ProxyArpService {
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())
......
......@@ -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.ResourceAllocation;
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 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
/**
* 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 @@ public class DefaultLinkResourceAllocations implements LinkResourceAllocations {
return result;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("allocations", allocations)
.toString();
}
}
......
......@@ -19,7 +19,6 @@ import com.google.common.collect.Sets;
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 @@ public class DeviceManagerTest {
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 @@ public class DeviceManagerTest {
private class TestProvider extends AbstractProvider implements DeviceProvider {
private Device deviceReceived;
private DeviceId deviceReceived;
private MastershipRole roleReceived;
public TestProvider() {
......@@ -274,13 +263,13 @@ public class DeviceManagerTest {
}
@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 @@ public class DeviceManagerTest {
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);
}
}
}
......
......@@ -148,7 +148,7 @@ public class FlowRuleManagerTest {
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 @@ public class FlowRuleManagerTest {
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 @@ public class FlowRuleManagerTest {
@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 class FlowRuleManagerTest {
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);
}
}
}
......
......@@ -20,11 +20,9 @@ import static org.easymock.EasyMock.expect;
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 @@ public class HostMonitorTest {
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 {
......
......@@ -19,12 +19,9 @@ import static org.easymock.EasyMock.anyObject;
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 @@ public class ProxyArpManagerTest {
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 @@ public class ProxyArpManagerTest {
*/
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 @@ public class ProxyArpManagerTest {
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 @@ public class ProxyArpManagerTest {
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());
......
......@@ -147,8 +147,7 @@ public class DistributedClusterStore
}
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.
......
......@@ -85,7 +85,6 @@ public class ClusterCommunicationManager
try {
netty.activate();
} catch (Exception e) {
// TODO Auto-generated catch block
log.error("NettyMessagingService#activate", e);
}
messagingService = netty;
......@@ -95,6 +94,12 @@ public class ClusterCommunicationManager
@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");
}
......
......@@ -72,4 +72,9 @@ public class DeviceClockManager implements DeviceClockService, DeviceClockProvid
log.info("adding term info {} {}", deviceId, term.master());
deviceMastershipTerms.put(deviceId, term);
}
@Override
public boolean isTimestampAvailable(DeviceId deviceId) {
return deviceMastershipTerms.containsKey(deviceId);
}
}
......
......@@ -1216,7 +1216,7 @@ public class GossipDeviceStore
@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 @@ public class GossipDeviceStore
@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 @@ public class GossipDeviceStore
@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 @@ public class GossipDeviceStore
@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 @@ public class GossipDeviceStore
@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));
}
}
......
......@@ -36,7 +36,7 @@ public class ReplicaInfoEvent extends AbstractEvent<ReplicaInfoEvent.Type, Devic
*/
MASTER_CHANGED,
//
// BACKUPS_CHANGED?
BACKUPS_CHANGED,
}
......
......@@ -284,9 +284,10 @@ public class DistributedFlowRuleStore
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())) {
......
......@@ -18,10 +18,9 @@ package org.onlab.onos.store.flow.impl;
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 @@ public class ReplicaInfoManager implements ReplicaInfoService {
@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;
}
}
}
......
......@@ -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.KryoNamespaces;
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 @@ implements MastershipStore {
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 @@ implements MastershipStore {
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 @@ implements MastershipStore {
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 @@ implements MastershipStore {
@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
......
......@@ -55,6 +55,13 @@ final class RoleValue {
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);
}
......
......@@ -214,11 +214,11 @@ public class DistributedMastershipStoreTest {
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));
}
......
......@@ -46,7 +46,13 @@ public class IpAddressSerializer extends Serializer<IpAddress> {
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
}
}
......
......@@ -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 @@ public final class IpPrefixSerializer extends Serializer<IpPrefix> {
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
}
}
......
......@@ -36,7 +36,7 @@ public class MacAddressSerializer extends Serializer<MacAddress> {
@Override
public void write(Kryo kryo, Output output, MacAddress object) {
output.writeBytes(object.getAddress());
output.writeBytes(object.toBytes());
}
@Override
......
......@@ -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 @@ import org.onlab.onos.net.device.DeviceClockProviderService;
@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);
}
}
......
......@@ -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.onos.store.AbstractStore;
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 @@ public class SimpleFlowRuleStore
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 @@ public class SimpleFlowRuleStore
}
// 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 @@ public class SimpleFlowRuleStore
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 @@ public class SimpleFlowRuleStore
@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);
}
}
......
......@@ -115,17 +115,25 @@ public interface OpenFlowSwitch {
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.
......
......@@ -53,5 +53,5 @@ public interface OpenFlowSwitchListener {
* @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);
}
......
......@@ -217,8 +217,8 @@ public abstract class AbstractOpenFlowSwitch implements OpenFlowSwitchDriver {
}
@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
......
......@@ -97,5 +97,5 @@ public interface OpenFlowAgent {
* @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);
}
......
......@@ -187,13 +187,6 @@ public interface OpenFlowSwitchDriver extends OpenFlowSwitch {
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.
*
......
......@@ -374,9 +374,9 @@ public class OpenFlowControllerImpl implements OpenFlowController {
}
@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);
}
}
}
......
......@@ -17,6 +17,7 @@ package org.onlab.onos.openflow.controller.impl;
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.projectfloodlight.openflow.types.U64;
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 @@ class RoleManager implements RoleHandler {
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 @@ class RoleManager implements RoleHandler {
}
// 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 @@ class RoleManager implements RoleHandler {
@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 @@ class RoleManager implements RoleHandler {
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
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) {
// 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 (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 @@ class RoleManager implements RoleHandler {
@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 @@ class RoleManager implements RoleHandler {
+ "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 @@ class RoleManager implements RoleHandler {
+ "received Error to for pending role request [%s]. "
+ "Error:[%s]. Disconnecting switch ... ",
sw.getStringId(),
pendingRole, rrerr);
errorRole, rrerr);
throw new SwitchStateException(msgx);
default:
break;
......
......@@ -175,11 +175,6 @@ public class RoleManagerTest {
}
@Override
public void returnRoleAssertFailure(RoleState role) {
failed = role;
}
@Override
public boolean isOptical() {
return false;
}
......@@ -300,5 +295,10 @@ public class RoleManagerTest {
public void write(List<OFMessage> msgs) {
}
@Override
public void returnRoleReply(RoleState requested, RoleState response) {
failed = requested;
}
}
}
......
......@@ -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>
......
......@@ -120,7 +120,8 @@ public class HostLocationProvider extends AbstractProvider implements HostProvid
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);
......
......@@ -216,7 +216,7 @@ public class HostLocationProviderTest {
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));
......
......@@ -127,18 +127,19 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
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 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
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 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
}
} 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));
}
......
......@@ -39,7 +39,6 @@ import org.onlab.onos.openflow.controller.OpenFlowController;
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 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
@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());
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 DeviceId deviceId = device.id();
LOG.info("Triggering probe on device {}", deviceId);
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 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
// }
@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 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
}
@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);
}
/**
......
......@@ -105,11 +105,11 @@ public class OpenFlowDeviceProviderTest {
@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 @@ public class OpenFlowDeviceProviderTest {
}
@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 @@ public class OpenFlowDeviceProviderTest {
}
@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 @@ public class OpenFlowDeviceProviderTest {
}
@Override
public void disconnectSwitch() {
public boolean isConnected() {
return true;
}
@Override
public void returnRoleAssertFailure(RoleState role) {
public void disconnectSwitch() {
}
@Override
......@@ -380,6 +383,10 @@ public class OpenFlowDeviceProviderTest {
return false;
}
@Override
public void returnRoleReply(RoleState requested, RoleState reponse) {
}
}
}
......
......@@ -147,7 +147,8 @@ public abstract class FlowModBuilder {
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 @@ public abstract class FlowModBuilder {
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()));
......
......@@ -302,7 +302,10 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
}
@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) {
......
......@@ -126,7 +126,8 @@ public class OpenFlowHostProvider extends AbstractProvider implements HostProvid
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);
......
......@@ -213,8 +213,8 @@ public class OpenFlowHostProviderTest {
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;
......
......@@ -160,7 +160,8 @@ public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvid
}
@Override
public void roleAssertFailed(Dpid dpid, RoleState role) {
public void receivedRoleReply(Dpid dpid, RoleState requested,
RoleState response) {
// do nothing for this.
}
......
......@@ -475,11 +475,12 @@ public class OpenFlowLinkProviderTest {
}
@Override
public void disconnectSwitch() {
public boolean isConnected() {
return true;
}
@Override
public void returnRoleAssertFailure(RoleState role) {
public void disconnectSwitch() {
}
@Override
......@@ -487,5 +488,9 @@ public class OpenFlowLinkProviderTest {
return false;
}
@Override
public void returnRoleReply(RoleState requested, RoleState reponse) {
}
}
}
......
......@@ -406,11 +406,12 @@ public class OpenFlowPacketProviderTest {
}
@Override
public void disconnectSwitch() {
public boolean isConnected() {
return true;
}
@Override
public void returnRoleAssertFailure(RoleState role) {
public void disconnectSwitch() {
}
@Override
......@@ -418,6 +419,10 @@ public class OpenFlowPacketProviderTest {
return false;
}
@Override
public void returnRoleReply(RoleState requested, RoleState reponse) {
}
}
}
......
#!/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
}
......@@ -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
......
......@@ -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" ] && \
......
......@@ -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 @@ public class Ethernet extends BasePacket {
* @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 @@ public class Ethernet extends BasePacket {
* @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;
......
......@@ -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,13 +48,74 @@ public final class IpAddress implements Comparable<IpAddress> {
/**
* 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);
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;
}
}
/**
* Returns the IP version of this address.
*
* @return the version
*/
public Version version() {
return this.version;
}
/**
* Returns the IP address as a byte array.
*
* @return a byte array
*/
public byte[] toOctets() {
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
*/
public int toInt() {
ByteBuffer bb = ByteBuffer.wrap(octets);
return bb.getInt();
}
/**
* 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);
}
}
/**
......@@ -64,13 +133,14 @@ public final class IpAddress implements Comparable<IpAddress> {
/**
* 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(byte[] value) {
checkNotNull(value);
return new IpAddress(Version.INET, value);
public static IpAddress valueOf(Version version, byte[] value) {
return new IpAddress(version, value);
}
/**
......@@ -80,96 +150,102 @@ public final class IpAddress implements Comparable<IpAddress> {
* 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(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);
}
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(bc);
return IpAddress.valueOf(version, bc);
}
/**
* Converts a dotted-decimal string (x.x.x.x) into an IPv4 address.
* Converts an InetAddress into an IP address.
*
* @param address an IP address in string form, e.g. "10.0.0.1"
* @param inetAddress the InetAddress value to use
* @return an IP address
* @throws IllegalArgumentException if the argument is invalid
*/
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);
public static IpAddress valueOf(InetAddress inetAddress) {
byte[] bytes = inetAddress.getAddress();
if (inetAddress instanceof Inet4Address) {
return new IpAddress(Version.INET, bytes);
}
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);
if (inetAddress instanceof Inet6Address) {
return new IpAddress(Version.INET6, bytes);
}
return new IpAddress(Version.INET, bytes);
}
/**
* Returns the IP version of this address.
*
* @return the version
*/
public Version version() {
return this.version;
}
/**
* Returns the IP address as a byte array.
*
* @return a byte array
*/
public byte[] toOctets() {
return Arrays.copyOf(this.octets, INET_BYTE_LENGTH);
// 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);
}
/**
* Returns the integral value of this IP address.
* Converts an IPv4 or IPv6 string literal (e.g., "10.2.3.4" or
* "1111:2222::8888") into an IP address.
*
* @return the IP address's value as an integer
* @param value an IP address value in string form
* @return an IP address
* @throws IllegalArgumentException if the argument is invalid
*/
public int toInt() {
ByteBuffer bb = ByteBuffer.wrap(octets);
return bb.getInt();
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 @@ public final class IpAddress implements Comparable<IpAddress> {
*
* @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 @@ public final class IpAddress implements Comparable<IpAddress> {
@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(".");
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 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) + "]";
}
builder.append(String.format("%d", b & 0xff));
throw new IllegalArgumentException(msg);
}
return builder.toString();
}
}
......
......@@ -76,12 +76,15 @@ public final class IpPrefix {
/**
* 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);
}
/**
......
......@@ -25,9 +25,6 @@ public class MacAddress {
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 @@ public class MacAddress {
}
return builder.toString();
}
public byte[] getAddress() {
return this.address;
}
}
......
......@@ -64,7 +64,7 @@ public class ONOSLLDP extends LLDP {
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 class ONOSLLDP extends LLDP {
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);
......
/*
* 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"));
}
}
......@@ -38,9 +38,11 @@ public class IpPrefixTest {
@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 @@ public class IpPrefixTest {
.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 @@ public class IpPrefixTest {
@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 @@ public class IpPrefixTest {
@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 @@ public class IpPrefixTest {
@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));
......
......@@ -73,6 +73,7 @@
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>${netty4.version}</version>
</dependency>
</dependencies>
......
......@@ -244,7 +244,7 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider {
}
@Override
public void roleChanged(Device device, MastershipRole newRole) {
public void roleChanged(DeviceId device, MastershipRole newRole) {
}
@Override
......@@ -257,7 +257,7 @@ class ConfigProvider implements DeviceProvider, LinkProvider, HostProvider {
}
@Override
public boolean isReachable(Device device) {
public boolean isReachable(DeviceId device) {
return false;
}
}
......
......@@ -101,7 +101,7 @@ public class TopologyResource extends BaseResource {
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")),
......