alshabib

lldp discovery independent of OF

Change-Id: I720f727f6628e30e5d732e6d7bf742d1b7050812
Showing 42 changed files with 967 additions and 92 deletions
......@@ -90,11 +90,15 @@ public class IntentPushTestCommand extends AbstractShellCommand
service.submit(intent);
}
try {
latch.await(5, TimeUnit.SECONDS);
printResults(count);
if (latch.await(10, TimeUnit.SECONDS)) {
printResults(count);
} else {
print("I FAIL MISERABLY -> %d", latch.getCount());
}
} catch (InterruptedException e) {
print(e.toString());
}
service.removeListener(this);
}
......@@ -140,6 +144,8 @@ public class IntentPushTestCommand extends AbstractShellCommand
} else {
log.warn("install event latch is null");
}
} else {
log.info("I FAIL -> {}", event);
}
}
}
......
package org.onlab.onos.net;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import java.util.Objects;
......@@ -16,6 +17,7 @@ public class DefaultDevice extends AbstractElement implements Device {
private final String serialNumber;
private final String hwVersion;
private final String swVersion;
private final ChassisId chassisId;
// For serialization
private DefaultDevice() {
......@@ -24,6 +26,7 @@ public class DefaultDevice extends AbstractElement implements Device {
this.hwVersion = null;
this.swVersion = null;
this.serialNumber = null;
this.chassisId = null;
}
/**
......@@ -40,13 +43,15 @@ public class DefaultDevice extends AbstractElement implements Device {
*/
public DefaultDevice(ProviderId providerId, DeviceId id, Type type,
String manufacturer, String hwVersion, String swVersion,
String serialNumber, Annotations... annotations) {
String serialNumber, ChassisId chassisId,
Annotations... annotations) {
super(providerId, id, annotations);
this.type = type;
this.manufacturer = manufacturer;
this.hwVersion = hwVersion;
this.swVersion = swVersion;
this.serialNumber = serialNumber;
this.chassisId = chassisId;
}
@Override
......@@ -80,6 +85,11 @@ public class DefaultDevice extends AbstractElement implements Device {
}
@Override
public ChassisId chassisId() {
return chassisId;
}
@Override
public int hashCode() {
return Objects.hash(id, type, manufacturer, hwVersion, swVersion, serialNumber);
}
......
package org.onlab.onos.net;
import org.onlab.packet.ChassisId;
/**
* Representation of a network infrastructure device.
*/
......@@ -54,6 +56,13 @@ public interface Device extends Element {
*/
String serialNumber();
/**
* Returns the device chassis id.
*
* @return chassis id
*/
ChassisId chassisId();
// Device realizedBy(); ?
// ports are not provided directly, but rather via DeviceService.getPorts(Device device);
......
......@@ -2,6 +2,7 @@ package org.onlab.onos.net.device;
import org.onlab.onos.net.AbstractDescription;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.packet.ChassisId;
import java.net.URI;
......@@ -20,6 +21,7 @@ public class DefaultDeviceDescription extends AbstractDescription
private final String hwVersion;
private final String swVersion;
private final String serialNumber;
private final ChassisId chassisId;
/**
* Creates a device description using the supplied information.
......@@ -34,7 +36,7 @@ public class DefaultDeviceDescription extends AbstractDescription
*/
public DefaultDeviceDescription(URI uri, Type type, String manufacturer,
String hwVersion, String swVersion,
String serialNumber,
String serialNumber, ChassisId chassis,
SparseAnnotations... annotations) {
super(annotations);
this.uri = checkNotNull(uri, "Device URI cannot be null");
......@@ -43,6 +45,7 @@ public class DefaultDeviceDescription extends AbstractDescription
this.hwVersion = hwVersion;
this.swVersion = swVersion;
this.serialNumber = serialNumber;
this.chassisId = chassis;
}
/**
......@@ -54,7 +57,7 @@ public class DefaultDeviceDescription extends AbstractDescription
SparseAnnotations... annotations) {
this(base.deviceURI(), base.type(), base.manufacturer(),
base.hwVersion(), base.swVersion(), base.serialNumber(),
annotations);
base.chassisId(), annotations);
}
@Override
......@@ -88,6 +91,11 @@ public class DefaultDeviceDescription extends AbstractDescription
}
@Override
public ChassisId chassisId() {
return chassisId;
}
@Override
public String toString() {
return toStringHelper(this)
.add("uri", uri).add("type", type).add("mfr", manufacturer)
......@@ -104,5 +112,6 @@ public class DefaultDeviceDescription extends AbstractDescription
this.hwVersion = null;
this.swVersion = null;
this.serialNumber = null;
this.chassisId = null;
}
}
......
......@@ -2,6 +2,7 @@ package org.onlab.onos.net.device;
import org.onlab.onos.net.Description;
import org.onlab.onos.net.Device;
import org.onlab.packet.ChassisId;
import java.net.URI;
......@@ -54,4 +55,11 @@ public interface DeviceDescription extends Description {
*/
String serialNumber();
/**
* Returns a device chassis id.
*
* @return chassis id
*/
ChassisId chassisId();
}
......
......@@ -3,6 +3,7 @@ package org.onlab.onos.net;
import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import static org.junit.Assert.assertEquals;
import static org.onlab.onos.net.Device.Type.SWITCH;
......@@ -21,14 +22,15 @@ public class DefaultDeviceTest {
static final String SW = "3.9.1";
static final String SN1 = "43311-12345";
static final String SN2 = "42346-43512";
static final ChassisId CID = new ChassisId();
@Test
public void testEquality() {
Device d1 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
Device d2 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
Device d3 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2);
Device d4 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2);
Device d5 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN1);
Device d1 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID);
Device d2 = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID);
Device d3 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2, CID);
Device d4 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN2, CID);
Device d5 = new DefaultDevice(PID, DID2, SWITCH, MFR, HW, SW, SN1, CID);
new EqualsTester().addEqualityGroup(d1, d2)
.addEqualityGroup(d3, d4)
......@@ -38,13 +40,13 @@ public class DefaultDeviceTest {
@Test
public void basics() {
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1);
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID);
validate(device);
}
@Test
public void annotations() {
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1,
Device device = new DefaultDevice(PID, DID1, SWITCH, MFR, HW, SW, SN1, CID,
DefaultAnnotations.builder().set("foo", "bar").build());
validate(device);
assertEquals("incorrect provider", "bar", device.annotations().value("foo"));
......
......@@ -3,6 +3,7 @@ package org.onlab.onos.net;
import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import static org.junit.Assert.assertEquals;
import static org.onlab.onos.net.Device.Type.SWITCH;
......@@ -22,7 +23,8 @@ public class DefaultPortTest {
@Test
public void testEquality() {
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n");
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n",
new ChassisId());
Port p1 = new DefaultPort(device, portNumber(1), true);
Port p2 = new DefaultPort(device, portNumber(1), true);
Port p3 = new DefaultPort(device, portNumber(2), true);
......@@ -37,7 +39,8 @@ public class DefaultPortTest {
@Test
public void basics() {
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n");
Device device = new DefaultDevice(PID, DID1, SWITCH, "m", "h", "s", "n",
new ChassisId());
Port port = new DefaultPort(device, portNumber(1), true);
assertEquals("incorrect element", device, port.element());
assertEquals("incorrect number", portNumber(1), port.number());
......
package org.onlab.onos.net;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpPrefix;
import java.util.ArrayList;
......@@ -37,7 +38,7 @@ public final class NetTestTools {
// Crates a new device with the specified id
public static Device device(String id) {
return new DefaultDevice(PID, did(id), Device.Type.SWITCH,
"mfg", "1.0", "1.1", "1234");
"mfg", "1.0", "1.1", "1234", new ChassisId());
}
// Crates a new host with the specified id
......
package org.onlab.onos.net.device;
import org.junit.Test;
import org.onlab.packet.ChassisId;
import java.net.URI;
......@@ -18,12 +19,13 @@ public class DefaultDeviceDescriptionTest {
private static final String HW = "1.1.x";
private static final String SW = "3.9.1";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
@Test
public void basics() {
DeviceDescription device =
new DefaultDeviceDescription(DURI, SWITCH, MFR, HW, SW, SN);
new DefaultDeviceDescription(DURI, SWITCH, MFR, HW, SW, SN, CID);
assertEquals("incorrect uri", DURI, device.deviceURI());
assertEquals("incorrect type", SWITCH, device.type());
assertEquals("incorrect manufacturer", MFR, device.manufacturer());
......@@ -31,6 +33,7 @@ public class DefaultDeviceDescriptionTest {
assertEquals("incorrect sw", SW, device.swVersion());
assertEquals("incorrect serial", SN, device.serialNumber());
assertTrue("incorrect toString", device.toString().contains("uri=of:foo"));
assertTrue("Incorrect chassis", device.chassisId().value() == 0);
}
}
......
......@@ -11,6 +11,7 @@ import org.onlab.onos.net.Device;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
/**
* Tests of the device event.
......@@ -19,7 +20,7 @@ public class DeviceEventTest extends AbstractEventTest {
private Device createDevice() {
return new DefaultDevice(new ProviderId("of", "foo"), deviceId("of:foo"),
Device.Type.SWITCH, "box", "hw", "sw", "sn");
Device.Type.SWITCH, "box", "hw", "sw", "sn", new ChassisId());
}
@Override
......
......@@ -18,9 +18,9 @@ public class DefaultGraphDescriptionTest {
private static final DeviceId D3 = deviceId("3");
static final Device DEV1 = new DefaultDevice(PID, D1, SWITCH, "", "", "", "");
static final Device DEV2 = new DefaultDevice(PID, D2, SWITCH, "", "", "", "");
static final Device DEV3 = new DefaultDevice(PID, D3, SWITCH, "", "", "", "");
static final Device DEV1 = new DefaultDevice(PID, D1, SWITCH, "", "", "", "", null);
static final Device DEV2 = new DefaultDevice(PID, D2, SWITCH, "", "", "", "", null);
static final Device DEV3 = new DefaultDevice(PID, D3, SWITCH, "", "", "", "", null);
@Test
public void basics() {
......
......@@ -346,7 +346,7 @@ public class DeviceManager
new DefaultDeviceDescription(
did.uri(), device.type(), device.manufacturer(),
device.hwVersion(), device.swVersion(),
device.serialNumber()));
device.serialNumber(), device.chassisId()));
}
applyRole(did, MastershipRole.MASTER);
......
......@@ -96,7 +96,7 @@ public class PathIntentInstaller implements IntentInstaller<PathIntent> {
FlowRule rule = new DefaultFlowRule(link.src().deviceId(),
builder.build(), treatment,
123, appId, 600);
123, appId, 15);
rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, rule));
prev = link.dst();
}
......
......@@ -37,6 +37,7 @@ import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.trivial.impl.SimpleDeviceStore;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpPrefix;
import java.util.ArrayList;
......@@ -62,6 +63,7 @@ public class DeviceManagerTest {
private static final String SW1 = "3.8.1";
private static final String SW2 = "3.9.5";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
private static final PortNumber P1 = PortNumber.portNumber(1);
private static final PortNumber P2 = PortNumber.portNumber(2);
......@@ -111,7 +113,7 @@ public class DeviceManagerTest {
private void connectDevice(DeviceId deviceId, String swVersion) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN);
HW, swVersion, SN, CID);
providerService.deviceConnected(deviceId, description);
assertNotNull("device should be found", service.getDevice(DID1));
}
......
......@@ -68,7 +68,7 @@ public class FlowRuleManagerTest {
private static final DeviceId DID = DeviceId.deviceId("of:001");
private static final int TIMEOUT = 10;
private static final Device DEV = new DefaultDevice(
PID, DID, Type.SWITCH, "", "", "", "");
PID, DID, Type.SWITCH, "", "", "", "", null);
private FlowRuleManager mgr;
......@@ -407,7 +407,6 @@ public class FlowRuleManagerTest {
FlowEntryState.PENDING_ADD));
}
......
......@@ -41,6 +41,7 @@ import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.onos.store.common.impl.Timestamped;
import org.onlab.onos.store.serializers.KryoSerializer;
import org.onlab.onos.store.serializers.DistributedStoreSerializers;
import org.onlab.packet.ChassisId;
import org.onlab.util.KryoPool;
import org.onlab.util.NewConcurrentHashMap;
import org.slf4j.Logger;
......@@ -745,6 +746,7 @@ public class GossipDeviceStore
String hwVersion = base.hwVersion();
String swVersion = base.swVersion();
String serialNumber = base.serialNumber();
ChassisId chassisId = base.chassisId();
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
annotations = merge(annotations, base.annotations());
......@@ -762,7 +764,8 @@ public class GossipDeviceStore
}
return new DefaultDevice(primary, deviceId , type, manufacturer,
hwVersion, swVersion, serialNumber, annotations);
hwVersion, swVersion, serialNumber,
chassisId, annotations);
}
/**
......
......@@ -53,6 +53,7 @@ import org.onlab.onos.store.cluster.messaging.ClusterCommunicationService;
import org.onlab.onos.store.cluster.messaging.ClusterMessage;
import org.onlab.onos.store.cluster.messaging.ClusterMessageHandler;
import org.onlab.onos.store.cluster.messaging.MessageSubject;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpPrefix;
import com.google.common.collect.Iterables;
......@@ -74,6 +75,7 @@ public class GossipDeviceStoreTest {
private static final String SW1 = "3.8.1";
private static final String SW2 = "3.9.5";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
private static final PortNumber P1 = PortNumber.portNumber(1);
private static final PortNumber P2 = PortNumber.portNumber(2);
......@@ -158,7 +160,7 @@ public class GossipDeviceStoreTest {
SparseAnnotations... annotations) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN, annotations);
HW, swVersion, SN, CID, annotations);
reset(clusterCommunicator);
try {
expect(clusterCommunicator.broadcast(anyObject(ClusterMessage.class)))
......@@ -175,7 +177,7 @@ public class GossipDeviceStoreTest {
SparseAnnotations... annotations) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN, annotations);
HW, swVersion, SN, CID, annotations);
deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
}
......@@ -315,7 +317,7 @@ public class GossipDeviceStoreTest {
public final void testCreateOrUpdateDevice() throws IOException {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
HW, SW1, SN, CID);
Capture<ClusterMessage> bcast = new Capture<>();
resetCommunicatorExpectingSingleBroadcast(bcast);
......@@ -328,7 +330,7 @@ public class GossipDeviceStoreTest {
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
HW, SW2, SN, CID);
resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
assertEquals(DEVICE_UPDATED, event2.type());
......@@ -346,7 +348,7 @@ public class GossipDeviceStoreTest {
// add
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN, A2);
HW, SW1, SN, CID, A2);
Capture<ClusterMessage> bcast = new Capture<>();
resetCommunicatorExpectingSingleBroadcast(bcast);
......@@ -362,7 +364,7 @@ public class GossipDeviceStoreTest {
// update from primary
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN, A1);
HW, SW2, SN, CID, A1);
resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
......@@ -392,7 +394,7 @@ public class GossipDeviceStoreTest {
// But, Ancillary annotations will be in effect
DeviceDescription description3 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN, A2_2);
HW, SW1, SN, CID, A2_2);
resetCommunicatorExpectingSingleBroadcast(bcast);
DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
......@@ -775,7 +777,7 @@ public class GossipDeviceStoreTest {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
HW, SW1, SN, CID);
deviceStore.setDelegate(checkAdd);
deviceStore.createOrUpdateDevice(PID, DID1, description);
assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
......@@ -783,7 +785,7 @@ public class GossipDeviceStoreTest {
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
HW, SW2, SN, CID);
deviceStore.unsetDelegate(checkAdd);
deviceStore.setDelegate(checkUpdate);
deviceStore.createOrUpdateDevice(PID, DID1, description2);
......
......@@ -169,7 +169,7 @@ public class DistributedDeviceStore
DefaultDevice device = new DefaultDevice(providerId, deviceId, desc.type(),
desc.manufacturer(),
desc.hwVersion(), desc.swVersion(),
desc.serialNumber());
desc.serialNumber(), desc.chassisId());
synchronized (this) {
final byte[] deviceIdBytes = serialize(deviceId);
......@@ -193,7 +193,8 @@ public class DistributedDeviceStore
desc.manufacturer(),
desc.hwVersion(),
desc.swVersion(),
desc.serialNumber());
desc.serialNumber(),
desc.chassisId());
synchronized (this) {
final byte[] deviceIdBytes = serialize(device.id());
rawDevices.put(deviceIdBytes, serialize(updated));
......
......@@ -40,6 +40,7 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import org.onlab.packet.ChassisId;
/**
* Test of the Hazelcast based distributed DeviceStore implementation.
......@@ -54,6 +55,7 @@ public class DistributedDeviceStoreTest {
private static final String SW1 = "3.8.1";
private static final String SW2 = "3.9.5";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
private static final PortNumber P1 = PortNumber.portNumber(1);
private static final PortNumber P2 = PortNumber.portNumber(2);
......@@ -95,7 +97,7 @@ public class DistributedDeviceStoreTest {
private void putDevice(DeviceId deviceId, String swVersion) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN);
HW, swVersion, SN, CID);
deviceStore.createOrUpdateDevice(PID, deviceId, description);
}
......@@ -154,14 +156,14 @@ public class DistributedDeviceStoreTest {
public final void testCreateOrUpdateDevice() {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
HW, SW1, SN, CID);
DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
assertEquals(DEVICE_ADDED, event.type());
assertDevice(DID1, SW1, event.subject());
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
HW, SW2, SN, CID);
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
assertEquals(DEVICE_UPDATED, event2.type());
assertDevice(DID1, SW2, event2.subject());
......@@ -362,7 +364,7 @@ public class DistributedDeviceStoreTest {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
HW, SW1, SN, CID);
deviceStore.setDelegate(checkAdd);
deviceStore.createOrUpdateDevice(PID, DID1, description);
assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
......@@ -370,7 +372,7 @@ public class DistributedDeviceStoreTest {
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
HW, SW2, SN, CID);
deviceStore.unsetDelegate(checkAdd);
deviceStore.setDelegate(checkUpdate);
deviceStore.createOrUpdateDevice(PID, DID1, description2);
......
......@@ -27,6 +27,7 @@ import org.onlab.onos.net.device.DefaultPortDescription;
import org.onlab.onos.net.link.DefaultLinkDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.Timestamp;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.util.KryoPool;
......@@ -61,6 +62,7 @@ public final class KryoPoolUtil {
//
ControllerNode.State.class,
Device.Type.class,
ChassisId.class,
DefaultAnnotations.class,
DefaultControllerNode.class,
DefaultDevice.class,
......
......@@ -26,6 +26,7 @@ import org.onlab.onos.net.MastershipRole;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.SparseAnnotations;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.packet.ChassisId;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.util.KryoPool;
......@@ -49,7 +50,9 @@ public class KryoSerializerTest {
private static final String SW1 = "3.8.1";
private static final String SW2 = "3.9.5";
private static final String SN = "43311-12345";
private static final Device DEV1 = new DefaultDevice(PID, DID1, Device.Type.SWITCH, MFR, HW, SW1, SN);
private static final ChassisId CID = new ChassisId();
private static final Device DEV1 = new DefaultDevice(PID, DID1, Device.Type.SWITCH, MFR, HW,
SW1, SN, CID);
private static final SparseAnnotations A1 = DefaultAnnotations.builder()
.set("A1", "a1")
.set("B1", "b1")
......
......@@ -30,6 +30,7 @@ import org.onlab.onos.net.device.DeviceStoreDelegate;
import org.onlab.onos.net.device.PortDescription;
import org.onlab.onos.net.provider.ProviderId;
import org.onlab.onos.store.AbstractStore;
import org.onlab.packet.ChassisId;
import org.onlab.util.NewConcurrentHashMap;
import org.slf4j.Logger;
......@@ -404,6 +405,7 @@ public class SimpleDeviceStore
String hwVersion = base.hwVersion();
String swVersion = base.swVersion();
String serialNumber = base.serialNumber();
ChassisId chassisId = base.chassisId();
DefaultAnnotations annotations = DefaultAnnotations.builder().build();
annotations = merge(annotations, base.annotations());
......@@ -421,7 +423,8 @@ public class SimpleDeviceStore
}
return new DefaultDevice(primary, deviceId , type, manufacturer,
hwVersion, swVersion, serialNumber, annotations);
hwVersion, swVersion, serialNumber,
chassisId, annotations);
}
/**
......
......@@ -17,6 +17,7 @@ import org.onlab.onos.net.topology.GraphDescription;
import org.onlab.onos.net.topology.LinkWeight;
import org.onlab.onos.net.topology.TopologyCluster;
import org.onlab.onos.net.topology.TopologyEdge;
import org.onlab.packet.ChassisId;
import java.util.Set;
......@@ -119,7 +120,7 @@ public class DefaultTopologyTest {
// Crates a new device with the specified id
public static Device device(String id) {
return new DefaultDevice(PID, did(id), Device.Type.SWITCH,
"mfg", "1.0", "1.1", "1234");
"mfg", "1.0", "1.1", "1234", new ChassisId());
}
// Short-hand for producing a device id from a string
......
......@@ -40,6 +40,7 @@ import org.onlab.onos.net.provider.ProviderId;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.onlab.packet.ChassisId;
/**
* Test of the simple DeviceStore implementation.
......@@ -55,6 +56,7 @@ public class SimpleDeviceStoreTest {
private static final String SW1 = "3.8.1";
private static final String SW2 = "3.9.5";
private static final String SN = "43311-12345";
private static final ChassisId CID = new ChassisId();
private static final PortNumber P1 = PortNumber.portNumber(1);
private static final PortNumber P2 = PortNumber.portNumber(2);
......@@ -107,7 +109,7 @@ public class SimpleDeviceStoreTest {
SparseAnnotations... annotations) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN, annotations);
HW, swVersion, SN, CID, annotations);
deviceStore.createOrUpdateDevice(PID, deviceId, description);
}
......@@ -115,7 +117,7 @@ public class SimpleDeviceStoreTest {
SparseAnnotations... annotations) {
DeviceDescription description =
new DefaultDeviceDescription(deviceId.uri(), SWITCH, MFR,
HW, swVersion, SN, annotations);
HW, swVersion, SN, CID, annotations);
deviceStore.createOrUpdateDevice(PIDA, deviceId, description);
}
......@@ -193,14 +195,14 @@ public class SimpleDeviceStoreTest {
public final void testCreateOrUpdateDevice() {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
HW, SW1, SN, CID);
DeviceEvent event = deviceStore.createOrUpdateDevice(PID, DID1, description);
assertEquals(DEVICE_ADDED, event.type());
assertDevice(DID1, SW1, event.subject());
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
HW, SW2, SN, CID);
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
assertEquals(DEVICE_UPDATED, event2.type());
assertDevice(DID1, SW2, event2.subject());
......@@ -212,7 +214,7 @@ public class SimpleDeviceStoreTest {
public final void testCreateOrUpdateDeviceAncillary() {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN, A2);
HW, SW1, SN, CID, A2);
DeviceEvent event = deviceStore.createOrUpdateDevice(PIDA, DID1, description);
assertEquals(DEVICE_ADDED, event.type());
assertDevice(DID1, SW1, event.subject());
......@@ -222,7 +224,7 @@ public class SimpleDeviceStoreTest {
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN, A1);
HW, SW2, SN, CID, A1);
DeviceEvent event2 = deviceStore.createOrUpdateDevice(PID, DID1, description2);
assertEquals(DEVICE_UPDATED, event2.type());
assertDevice(DID1, SW2, event2.subject());
......@@ -238,7 +240,7 @@ public class SimpleDeviceStoreTest {
// But, Ancillary annotations will be in effect
DeviceDescription description3 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN, A2_2);
HW, SW1, SN, CID, A2_2);
DeviceEvent event3 = deviceStore.createOrUpdateDevice(PIDA, DID1, description3);
assertEquals(DEVICE_UPDATED, event3.type());
// basic information will be the one from Primary
......@@ -508,7 +510,7 @@ public class SimpleDeviceStoreTest {
DeviceDescription description =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW1, SN);
HW, SW1, SN, CID);
deviceStore.setDelegate(checkAdd);
deviceStore.createOrUpdateDevice(PID, DID1, description);
assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
......@@ -516,7 +518,7 @@ public class SimpleDeviceStoreTest {
DeviceDescription description2 =
new DefaultDeviceDescription(DID1.uri(), SWITCH, MFR,
HW, SW2, SN);
HW, SW2, SN, CID);
deviceStore.unsetDelegate(checkAdd);
deviceStore.setDelegate(checkUpdate);
deviceStore.createOrUpdateDevice(PID, DID1, description2);
......
......@@ -101,8 +101,8 @@
<bundle>mvn:org.onlab.onos/onos-of-api/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-ctl/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-lldp-provider/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-device/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-link/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-host/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-packet/1.0.0-SNAPSHOT</bundle>
<bundle>mvn:org.onlab.onos/onos-of-provider-flow/1.0.0-SNAPSHOT</bundle>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-providers</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>onos-lldp-provider</artifactId>
<packaging>bundle</packaging>
<description>ONOS LLDP Link Discovery</description>
</project>
package org.onlab.onos.provider.lldp.impl;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.device.DeviceEvent;
import org.onlab.onos.net.device.DeviceListener;
import org.onlab.onos.net.device.DeviceService;
import org.onlab.onos.net.link.LinkProvider;
import org.onlab.onos.net.link.LinkProviderRegistry;
import org.onlab.onos.net.link.LinkProviderService;
import org.onlab.onos.net.packet.PacketContext;
import org.onlab.onos.net.packet.PacketProcessor;
import org.onlab.onos.net.packet.PacketService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
import org.slf4j.Logger;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which uses an OpenFlow controller to detect network
* infrastructure links.
*/
@Component(immediate = true)
public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkProviderRegistry providerRegistry;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetSevice;
private LinkProviderService providerService;
private final boolean useBDDP = true;
private final InternalLinkProvider listener = new InternalLinkProvider();
protected final Map<DeviceId, LinkDiscovery> discoverers = new ConcurrentHashMap<>();
/**
* Creates an OpenFlow link provider.
*/
public LLDPLinkProvider() {
super(new ProviderId("lldp", "org.onlab.onos.provider.lldp"));
}
@Activate
public void activate() {
providerService = providerRegistry.register(this);
deviceService.addListener(listener);
packetSevice.addProcessor(listener, 0);
log.info("Started");
}
@Deactivate
public void deactivate() {
for (LinkDiscovery ld : discoverers.values()) {
ld.stop();
}
providerRegistry.unregister(this);
deviceService.removeListener(listener);
packetSevice.removeProcessor(listener);
providerService = null;
log.info("Stopped");
}
private class InternalLinkProvider implements PacketProcessor, DeviceListener {
@Override
public void event(DeviceEvent event) {
LinkDiscovery ld = null;
Device device = event.subject();
// it's not a switch so leave.
if (device.type() != Device.Type.SWITCH) {
return;
}
switch (event.type()) {
case DEVICE_ADDED:
discoverers.put(event.subject().id(),
new LinkDiscovery(event.subject(), packetSevice,
providerService, useBDDP));
break;
case PORT_ADDED:
case PORT_UPDATED:
if (event.port().isEnabled()) {
ld = discoverers.get(event.subject().id());
if (ld == null) {
return;
}
ld.addPort(event.port());
} else {
ConnectPoint point = new ConnectPoint(event.subject().id(),
event.port().number());
providerService.linksVanished(point);
}
break;
case PORT_REMOVED:
ConnectPoint point = new ConnectPoint(event.subject().id(),
event.port().number());
providerService.linksVanished(point);
break;
case DEVICE_REMOVED:
case DEVICE_SUSPENDED:
ld = discoverers.get(event.subject().id());
if (ld == null) {
return;
}
ld.stop();
providerService.linksVanished(event.subject().id());
break;
case DEVICE_AVAILABILITY_CHANGED:
ld = discoverers.get(event.subject().id());
if (ld == null) {
return;
}
if (deviceService.isAvailable(event.subject().id())) {
ld.start();
} else {
providerService.linksVanished(event.subject().id());
ld.stop();
}
break;
case DEVICE_UPDATED:
case DEVICE_MASTERSHIP_CHANGED:
break;
default:
log.debug("Unknown event {}", event);
}
}
@Override
public void process(PacketContext context) {
LinkDiscovery ld = discoverers.get(
context.inPacket().receivedFrom().deviceId());
if (ld == null) {
return;
}
if (ld.handleLLDP(context)) {
context.block();
}
}
}
}
/*******************************************************************************
* 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.provider.lldp.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.TimerTask;
import org.onlab.onos.net.ConnectPoint;
import org.onlab.onos.net.Device;
import org.onlab.onos.net.DeviceId;
import org.onlab.onos.net.Link.Type;
import org.onlab.onos.net.Port;
import org.onlab.onos.net.PortNumber;
import org.onlab.onos.net.flow.DefaultTrafficTreatment;
import org.onlab.onos.net.link.DefaultLinkDescription;
import org.onlab.onos.net.link.LinkDescription;
import org.onlab.onos.net.link.LinkProviderService;
import org.onlab.onos.net.packet.DefaultOutboundPacket;
import org.onlab.onos.net.packet.OutboundPacket;
import org.onlab.onos.net.packet.PacketContext;
import org.onlab.onos.net.packet.PacketService;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ONOSLLDP;
import org.onlab.util.Timer;
import org.slf4j.Logger;
/**
* Run discovery process from a physical switch. Ports are initially labeled as
* slow ports. When an LLDP is successfully received, label the remote port as
* fast. Every probeRate milliseconds, loop over all fast ports and send an
* LLDP, send an LLDP for a single slow port. Based on FlowVisor topology
* discovery implementation.
*
* TODO: add 'fast discovery' mode: drop LLDPs in destination switch but listen
* for flow_removed messages
*/
public class LinkDiscovery implements TimerTask {
private final Device device;
// send 1 probe every probeRate milliseconds
private final long probeRate;
private final Set<Long> slowPorts;
private final Set<Long> fastPorts;
// number of unacknowledged probes per port
private final Map<Long, AtomicInteger> portProbeCount;
// number of probes to send before link is removed
private static final short MAX_PROBE_COUNT = 3;
private final Logger log = getLogger(getClass());
private final ONOSLLDP lldpPacket;
private final Ethernet ethPacket;
private Ethernet bddpEth;
private final boolean useBDDP;
private final LinkProviderService linkProvider;
private final PacketService pktService;
private Timeout timeout;
/**
* Instantiates discovery manager for the given physical switch. Creates a
* generic LLDP packet that will be customized for the port it is sent out on.
* Starts the the timer for the discovery process.
*
* @param device the physical switch
* @param useBDDP flag to also use BDDP for discovery
*/
public LinkDiscovery(Device device, PacketService pktService,
LinkProviderService providerService, Boolean... useBDDP) {
this.device = device;
this.probeRate = 3000;
this.linkProvider = providerService;
this.pktService = pktService;
this.slowPorts = Collections.synchronizedSet(new HashSet<Long>());
this.fastPorts = Collections.synchronizedSet(new HashSet<Long>());
this.portProbeCount = new HashMap<>();
this.lldpPacket = new ONOSLLDP();
this.lldpPacket.setChassisId(device.chassisId());
this.lldpPacket.setDevice(device.id().toString());
this.ethPacket = new Ethernet();
this.ethPacket.setEtherType(Ethernet.TYPE_LLDP);
this.ethPacket.setDestinationMACAddress(ONOSLLDP.LLDP_NICIRA);
this.ethPacket.setPayload(this.lldpPacket);
this.ethPacket.setPad(true);
this.useBDDP = useBDDP.length > 0 ? useBDDP[0] : false;
if (this.useBDDP) {
this.bddpEth = new Ethernet();
this.bddpEth.setPayload(this.lldpPacket);
this.bddpEth.setEtherType(Ethernet.TYPE_BSN);
this.bddpEth.setDestinationMACAddress(ONOSLLDP.BDDP_MULTICAST);
this.bddpEth.setPad(true);
log.info("Using BDDP to discover network");
}
start();
this.log.debug("Started discovery manager for switch {}",
device.id());
}
/**
* Add physical port port to discovery process.
* Send out initial LLDP and label it as slow port.
*
* @param port the port
*/
public void addPort(final Port port) {
this.log.debug("sending init probe to port {}",
port.number().toLong());
sendProbes(port.number().toLong());
synchronized (this) {
this.slowPorts.add(port.number().toLong());
}
}
/**
* Removes physical port from discovery process.
*
* @param port the port
*/
public void removePort(final Port port) {
// Ignore ports that are not on this switch
long portnum = port.number().toLong();
synchronized (this) {
if (this.slowPorts.contains(portnum)) {
this.slowPorts.remove(portnum);
} else if (this.fastPorts.contains(portnum)) {
this.fastPorts.remove(portnum);
this.portProbeCount.remove(portnum);
// no iterator to update
} else {
this.log.warn(
"tried to dynamically remove non-existing port {}",
portnum);
}
}
}
/**
* Method called by remote port to acknowledge receipt of LLDP sent by
* this port. If slow port, updates label to fast. If fast port, decrements
* number of unacknowledged probes.
*
* @param portNumber the port
*/
public void ackProbe(final Long portNumber) {
synchronized (this) {
if (this.slowPorts.contains(portNumber)) {
this.log.debug("Setting slow port to fast: {}:{}",
this.device.id(), portNumber);
this.slowPorts.remove(portNumber);
this.fastPorts.add(portNumber);
this.portProbeCount.put(portNumber, new AtomicInteger(0));
} else {
if (this.fastPorts.contains(portNumber)) {
this.portProbeCount.get(portNumber).set(0);
} else {
this.log.debug(
"Got ackProbe for non-existing port: {}",
portNumber);
}
}
}
}
/**
* Handles an incoming LLDP packet. Creates link in topology and sends ACK
* to port where LLDP originated.
*/
public boolean handleLLDP(PacketContext context) {
Ethernet eth = context.inPacket().parsed();
ONOSLLDP onoslldp = ONOSLLDP.parseONOSLLDP(eth);
if (onoslldp != null) {
final PortNumber dstPort =
context.inPacket().receivedFrom().port();
final PortNumber srcPort = PortNumber.portNumber(onoslldp.getPort());
final DeviceId srcDeviceId = DeviceId.deviceId(onoslldp.getDeviceString());
final DeviceId dstDeviceId = context.inPacket().receivedFrom().deviceId();
this.ackProbe(srcPort.toLong());
ConnectPoint src = new ConnectPoint(srcDeviceId, srcPort);
ConnectPoint dst = new ConnectPoint(dstDeviceId, dstPort);
LinkDescription ld;
if (eth.getEtherType() == Ethernet.TYPE_BSN) {
ld = new DefaultLinkDescription(src, dst, Type.INDIRECT);
} else {
ld = new DefaultLinkDescription(src, dst, Type.DIRECT);
}
linkProvider.linkDetected(ld);
return true;
}
return false;
}
/**
* Execute this method every t milliseconds. Loops over all ports
* labeled as fast and sends out an LLDP. Send out an LLDP on a single slow
* port.
*
* @param t timeout
* @throws Exception
*/
@Override
public void run(final Timeout t) {
this.log.debug("sending probes");
synchronized (this) {
final Iterator<Long> fastIterator = this.fastPorts.iterator();
Long portNumber;
Integer probeCount;
while (fastIterator.hasNext()) {
portNumber = fastIterator.next();
probeCount = this.portProbeCount.get(portNumber)
.getAndIncrement();
if (probeCount < LinkDiscovery.MAX_PROBE_COUNT) {
this.log.debug("sending fast probe to port");
sendProbes(portNumber);
} else {
// Update fast and slow ports
//fastIterator.remove();
//this.slowPorts.add(portNumber);
//this.portProbeCount.remove(portNumber);
ConnectPoint cp = new ConnectPoint(
device.id(),
PortNumber.portNumber(portNumber));
log.debug("Link down -> {}", cp);
linkProvider.linksVanished(cp);
}
}
// send a probe for the next slow port
if (!this.slowPorts.isEmpty()) {
Iterator<Long> slowIterator = this.slowPorts.iterator();
while (slowIterator.hasNext()) {
portNumber = slowIterator.next();
this.log.debug("sending slow probe to port {}", portNumber);
sendProbes(portNumber);
}
}
}
// reschedule timer
timeout = Timer.getTimer().newTimeout(this, this.probeRate,
TimeUnit.MILLISECONDS);
}
public void stop() {
timeout.cancel();
}
public void start() {
timeout = Timer.getTimer().newTimeout(this, 0,
TimeUnit.MILLISECONDS);
}
/**
* Creates packet_out LLDP for specified output port.
*
* @param port the port
* @return Packet_out message with LLDP data
*/
private OutboundPacket createOutBoundLLDP(final Long port) {
if (port == null) {
return null;
}
this.lldpPacket.setPortId(port.intValue());
this.ethPacket.setSourceMACAddress("DE:AD:BE:EF:BA:11");
final byte[] lldp = this.ethPacket.serialize();
OutboundPacket outboundPacket = new DefaultOutboundPacket(
this.device.id(),
DefaultTrafficTreatment.builder().setOutput(
PortNumber.portNumber(port)).build(),
ByteBuffer.wrap(lldp));
return outboundPacket;
}
/**
* Creates packet_out BDDP for specified output port.
*
* @param port the port
* @return Packet_out message with LLDP data
*/
private OutboundPacket createOutBoundBDDP(final Long port) {
if (port == null) {
return null;
}
this.lldpPacket.setPortId(port.intValue());
this.bddpEth.setSourceMACAddress("DE:AD:BE:EF:BA:11");
final byte[] bddp = this.bddpEth.serialize();
OutboundPacket outboundPacket = new DefaultOutboundPacket(
this.device.id(),
DefaultTrafficTreatment.builder()
.setOutput(PortNumber.portNumber(port)).build(),
ByteBuffer.wrap(bddp));
return outboundPacket;
}
private void sendProbes(Long portNumber) {
OutboundPacket pkt = this.createOutBoundLLDP(portNumber);
pktService.emit(pkt);
if (useBDDP) {
OutboundPacket bpkt = this.createOutBoundBDDP(portNumber);
pktService.emit(bpkt);
}
}
}
/**
* Provider that uses the core as a means of infrastructure link inference.
*/
package org.onlab.onos.provider.lldp.impl;
......@@ -23,6 +23,7 @@ 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.packet.ChassisId;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.OFPortState;
......@@ -117,13 +118,14 @@ public class OpenFlowDeviceProvider extends AbstractProvider implements DevicePr
}
DeviceId did = deviceId(uri(dpid));
OpenFlowSwitch sw = controller.getSwitch(dpid);
ChassisId cId = new ChassisId(dpid.value());
DeviceDescription description =
new DefaultDeviceDescription(did.uri(), Device.Type.SWITCH,
sw.manfacturerDescription(),
sw.hardwareDescription(),
sw.softwareDescription(),
sw.serialNumber());
sw.serialNumber(),
cId);
providerService.deviceConnected(did, description);
providerService.updatePorts(did, buildPortDescriptions(sw.getPorts()));
}
......
......@@ -59,7 +59,7 @@ public class OpenFlowDeviceProviderTest {
private static final List<OFPortDesc> PLIST = Lists.newArrayList(PD1, PD2);
private static final Device DEV1 =
new DefaultDevice(PID, DID1, SWITCH, "", "", "", "");
new DefaultDevice(PID, DID1, SWITCH, "", "", "", "", null);
private static final TestOpenFlowSwitch SW1 = new TestOpenFlowSwitch();
......
package org.onlab.onos.provider.of.flow.impl;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
......@@ -68,10 +57,20 @@ import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U32;
import org.slf4j.Logger;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which uses an OpenFlow controller to detect network
......@@ -166,6 +165,9 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
for (FlowRuleBatchEntry fbe : batch.getOperations()) {
FlowRule flowRule = fbe.getTarget();
OpenFlowSwitch sw = controller.getSwitch(Dpid.dpid(flowRule.deviceId().uri()));
if (sw == null) {
log.warn("WTF {}", flowRule.deviceId());
}
sws.add(new Dpid(sw.getId()));
FlowModBuilder builder = new FlowModBuilder(flowRule, sw.factory());
switch (fbe.getOperator()) {
......@@ -322,6 +324,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
public void fail(OFErrorMsg msg, Dpid dpid) {
ok.set(false);
removeRequirement(dpid);
FlowEntry fe = null;
FlowRuleBatchEntry fbe = fms.get(msg.getXid());
FlowRule offending = fbe.getTarget();
......@@ -375,10 +378,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
public void satisfyRequirement(Dpid dpid) {
log.warn("Satisfaction from switch {}", dpid);
sws.remove(dpid);
countDownLatch.countDown();
cleanUp();
removeRequirement(dpid);
}
......@@ -395,6 +395,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
ok.set(false);
this.state = BatchState.CANCELLED;
cleanUp();
for (FlowRuleBatchEntry fbe : fms.values()) {
......@@ -431,6 +432,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
throws InterruptedException, ExecutionException,
TimeoutException {
if (countDownLatch.await(timeout, unit)) {
this.state = BatchState.FINISHED;
return new CompletedBatchOperation(ok.get(), offendingFlowMods);
}
......@@ -438,7 +440,7 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
}
private void cleanUp() {
if (sws.isEmpty()) {
if (isDone() || isCancelled()) {
pendingFutures.remove(pendingXid);
for (Long xid : fms.keySet()) {
pendingFMs.remove(xid);
......@@ -446,6 +448,12 @@ public class OpenFlowRuleProvider extends AbstractProvider implements FlowRulePr
}
}
private void removeRequirement(Dpid dpid) {
countDownLatch.countDown();
sws.remove(dpid);
cleanUp();
}
}
}
......
......@@ -28,7 +28,6 @@ import org.onlab.onos.openflow.controller.OpenFlowController;
import org.onlab.onos.openflow.controller.OpenFlowPacketContext;
import org.onlab.onos.openflow.controller.OpenFlowSwitch;
import org.onlab.onos.openflow.controller.PacketListener;
import org.onlab.packet.Ethernet;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
import org.projectfloodlight.openflow.protocol.action.OFAction;
......@@ -96,13 +95,13 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr
return;
}
Ethernet eth = new Ethernet();
eth.deserialize(packet.data().array(), 0, packet.data().array().length);
//Ethernet eth = new Ethernet();
//eth.deserialize(packet.data().array(), 0, packet.data().array().length);
OFPortDesc p = null;
for (Instruction inst : packet.treatment().instructions()) {
if (inst.type().equals(Instruction.Type.OUTPUT)) {
p = portDesc(((OutputInstruction) inst).port());
OFPacketOut po = packetOut(sw, eth, p.getPortNo());
OFPacketOut po = packetOut(sw, packet.data().array(), p.getPortNo());
sw.sendMsg(po);
}
}
......@@ -116,7 +115,7 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr
return builder.build();
}
private OFPacketOut packetOut(OpenFlowSwitch sw, Ethernet eth, OFPort out) {
private OFPacketOut packetOut(OpenFlowSwitch sw, byte[] eth, OFPort out) {
OFPacketOut.Builder builder = sw.factory().buildPacketOut();
OFAction act = sw.factory().actions()
.buildOutput()
......@@ -126,7 +125,7 @@ public class OpenFlowPacketProvider extends AbstractProvider implements PacketPr
.setBufferId(OFBufferId.NO_BUFFER)
.setInPort(OFPort.NO_MASK)
.setActions(Collections.singletonList(act))
.setData(eth.serialize())
.setData(eth)
.build();
}
......
......@@ -18,6 +18,7 @@
<modules>
<module>openflow</module>
<module>lldp</module>
</modules>
<dependencies>
......
......@@ -2,5 +2,5 @@
export ONOS_FEATURES="webconsole,onos-api,onos-core-trivial,onos-cli,onos-openflow,onos-app-fwd,onos-app-mobility,onos-app-tvue,onos-app-proxyarp"
export ONOS_NIC="10.128.4.*"
export OC1="10.128.4.60"
export ONOS_NIC="10.1.10.*"
export OC1="10.1.10.223"
......
package org.onlab.packet;
/**
* The class representing a network device chassisId.
* This class is immutable.
*/
// TODO: Move this to a reasonable place.
public final class ChassisId {
private static final long UNKNOWN = 0;
private final long value;
/**
* Default constructor.
*/
public ChassisId() {
this.value = ChassisId.UNKNOWN;
}
/**
* Constructor from a long value.
*
* @param value the value to use.
*/
public ChassisId(long value) {
this.value = value;
}
/**
* Constructor from a string.
*
* @param value the value to use.
*/
public ChassisId(String value) {
this.value = Long.valueOf(value);
}
/**
* Get the value of the chassis id.
*
* @return the value of the chassis id.
*/
public long value() {
return value;
}
/**
* Convert the Chassis Id value to a ':' separated hexadecimal string.
*
* @return the Chassis Id value as a ':' separated hexadecimal string.
*/
@Override
public String toString() {
return Long.toHexString(this.value);
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ChassisId)) {
return false;
}
ChassisId otherChassisId = (ChassisId) other;
return value == otherChassisId.value;
}
@Override
public int hashCode() {
int hash = 17;
hash += 31 * hash + (int) (value ^ value >>> 32);
return hash;
}
}
......@@ -58,6 +58,7 @@ public class Ethernet extends BasePacket {
Ethernet.etherTypeClassMap.put(Ethernet.TYPE_RARP, ARP.class);
Ethernet.etherTypeClassMap.put(Ethernet.TYPE_IPV4, IPv4.class);
Ethernet.etherTypeClassMap.put(Ethernet.TYPE_LLDP, LLDP.class);
Ethernet.etherTypeClassMap.put(Ethernet.TYPE_BSN, LLDP.class);
}
protected MacAddress destinationMACAddress;
......
......@@ -150,7 +150,7 @@ public class LLDP extends BasePacket {
final ByteBuffer bb = ByteBuffer.wrap(data, offset, length);
LLDPTLV tlv;
do {
tlv = new LLDPTLV().deserialize(bb);
tlv = new LLDPOrganizationalTLV().deserialize(bb);
// if there was a failure to deserialize stop processing TLVs
if (tlv == null) {
......@@ -169,6 +169,7 @@ public class LLDP extends BasePacket {
case 0x3:
this.ttl = tlv;
break;
default:
this.optionalTLVList.add(tlv);
break;
......
......@@ -140,6 +140,9 @@ public class LLDPOrganizationalTLV extends LLDPTLV {
@Override
public byte[] serialize() {
if (this.type != LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
return super.serialize();
}
final int valueLength = LLDPOrganizationalTLV.OUI_LENGTH
+ LLDPOrganizationalTLV.SUBTYPE_LENGTH + this.infoString.length;
this.value = new byte[valueLength];
......@@ -152,7 +155,11 @@ public class LLDPOrganizationalTLV extends LLDPTLV {
@Override
public LLDPTLV deserialize(final ByteBuffer bb) {
super.deserialize(bb);
LLDPTLV tlv = super.deserialize(bb);
if (tlv.getType() != LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
return tlv;
}
final ByteBuffer optionalField = ByteBuffer.wrap(this.value);
final byte[] oui = new byte[LLDPOrganizationalTLV.OUI_LENGTH];
......
......@@ -111,6 +111,7 @@ public class LLDPTLV {
sscratch = bb.getShort();
this.type = (byte) (sscratch >> 9 & 0x7f);
this.length = (short) (sscratch & 0x1ff);
if (this.length > 0) {
this.value = new byte[this.length];
......@@ -120,6 +121,7 @@ public class LLDPTLV {
}
bb.get(this.value);
}
return this;
}
......
......@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
* Refer to IEEE Std 802.1ABTM-2009 for more information.
*
*/
@Deprecated
public class ONLabLddp extends LLDP {
private static final Logger LOG = LoggerFactory.getLogger(ONLabLddp.class);
......
package org.onlab.packet;
import com.google.common.collect.Lists;
import org.apache.commons.lang.ArrayUtils;
import java.nio.ByteBuffer;
/**
* ONOS LLDP containing organizational TLV for ONOS device dicovery.
*/
public class ONOSLLDP extends LLDP {
public static final byte[] ONLAB_OUI = {(byte) 0xa4, 0x23, 0x05};
public static final String DEFAULT_DEVICE = "INVALID";
public static final String DEFAULT_NAME = "ONOS Discovery";
public static final byte[] LLDP_NICIRA = {0x01, 0x23, 0x20, 0x00, 0x00,
0x01};
public static final byte[] LLDP_MULTICAST = {0x01, (byte) 0x80,
(byte) 0xc2, 0x00, 0x00, 0x0e};
public static final byte[] BDDP_MULTICAST = {(byte) 0xff, (byte) 0xff,
(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff};
private static final byte NAME_SUBTYPE = 1;
private static final byte DEVICE_SUBTYPE = 2;
private static final short NAME_LENGTH = 4; //1 for subtype + 3 for OUI
private static final short DEVICE_LENGTH = 4; //1 for subtype + 3 for OUI
private final LLDPOrganizationalTLV nameTLV = new LLDPOrganizationalTLV();
private final LLDPOrganizationalTLV deviceTLV = new LLDPOrganizationalTLV();
// TLV constants: type, size and subtype
// Organizationally specific TLV also have packet offset and contents of TLV
// header
private static final byte CHASSIS_TLV_TYPE = 1;
private static final byte CHASSIS_TLV_SIZE = 7;
private static final byte CHASSIS_TLV_SUBTYPE = 4;
private static final byte PORT_TLV_TYPE = 2;
private static final byte PORT_TLV_SIZE = 5;
private static final byte PORT_TLV_SUBTYPE = 2;
private static final byte TTL_TLV_TYPE = 3;
private final byte[] ttlValue = new byte[] {0, 0x78};
public ONOSLLDP() {
super();
setName(DEFAULT_NAME);
setDevice(DEFAULT_DEVICE);
setOptionalTLVList(Lists.<LLDPTLV>newArrayList(nameTLV, deviceTLV));
setTtl(new LLDPTLV().setType((byte) TTL_TLV_TYPE)
.setLength((short) ttlValue.length)
.setValue(ttlValue));
}
private ONOSLLDP(LLDP lldp) {
this.portId = lldp.getPortId();
this.chassisId = lldp.getChassisId();
this.ttl = lldp.getTtl();
this.optionalTLVList = lldp.getOptionalTLVList();
}
public void setName(String name) {
nameTLV.setLength((short) (name.length() + NAME_LENGTH));
nameTLV.setInfoString(name);
nameTLV.setSubType(NAME_SUBTYPE);
nameTLV.setOUI(ONLAB_OUI);
}
public void setDevice(String device) {
deviceTLV.setInfoString(device);
deviceTLV.setLength((short) (device.length() + DEVICE_LENGTH));
deviceTLV.setSubType(DEVICE_SUBTYPE);
deviceTLV.setOUI(ONLAB_OUI);
}
public void setChassisId(final ChassisId chassisId) {
MacAddress chassisMac = MacAddress.valueOf(chassisId.value());
byte[] chassis = ArrayUtils.addAll(new byte[] {CHASSIS_TLV_SUBTYPE},
chassisMac.getAddress());
LLDPTLV chassisTLV = new LLDPTLV();
chassisTLV.setLength(CHASSIS_TLV_SIZE);
chassisTLV.setType(CHASSIS_TLV_TYPE);
chassisTLV.setValue(chassis);
this.setChassisId(chassisTLV);
}
public void setPortId(final int portNumber) {
byte[] port = ArrayUtils.addAll(new byte[] {PORT_TLV_SUBTYPE},
ByteBuffer.allocate(4).putInt(portNumber).array());
LLDPTLV portTLV = new LLDPTLV();
portTLV.setLength(PORT_TLV_SIZE);
portTLV.setType(PORT_TLV_TYPE);
portTLV.setValue(port);
this.setPortId(portTLV);
}
public LLDPOrganizationalTLV getNameTLV() {
for (LLDPTLV tlv : this.getOptionalTLVList()) {
if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
if (orgTLV.getSubType() == NAME_SUBTYPE) {
return orgTLV;
}
}
}
return null;
}
public LLDPOrganizationalTLV getDeviceTLV() {
for (LLDPTLV tlv : this.getOptionalTLVList()) {
if (tlv.getType() == LLDPOrganizationalTLV.ORGANIZATIONAL_TLV_TYPE) {
LLDPOrganizationalTLV orgTLV = (LLDPOrganizationalTLV) tlv;
if (orgTLV.getSubType() == DEVICE_SUBTYPE) {
return orgTLV;
}
}
}
return null;
}
public String getNameString() {
LLDPOrganizationalTLV tlv = getNameTLV();
if (tlv != null) {
return new String(tlv.getInfoString());
}
return null;
}
public String getDeviceString() {
LLDPOrganizationalTLV tlv = getDeviceTLV();
if (tlv != null) {
return new String(tlv.getInfoString());
}
return null;
}
public Integer getPort() {
ByteBuffer portBB = ByteBuffer.wrap(this.getPortId().getValue());
portBB.position(1);
return portBB.getInt();
}
/**
* Given an ethernet packet, determines if this is an LLDP from
* ONOS and returns the device the LLDP came from.
* @param eth an ethernet packet
* @return a the lldp packet or null
*/
public static ONOSLLDP parseONOSLLDP(Ethernet eth) {
if (eth.getEtherType() == Ethernet.TYPE_LLDP ||
eth.getEtherType() == Ethernet.TYPE_BSN) {
ONOSLLDP onosLldp = new ONOSLLDP((LLDP) eth.getPayload()); //(ONOSLLDP) eth.getPayload();
if (ONOSLLDP.DEFAULT_NAME.equals(onosLldp.getNameString())) {
return onosLldp;
}
}
return null;
}
}