Brian Stanke
Committed by Gerrit Code Review

ONOS-3633 - Adding intent event listener to PointToPointIntent virtual network

provider. Intent events will either set the virtual link state to ACTIVE or
INACTIVE.

Change-Id: I34b65b2bfff29b791e7b2eb4d7cefb2ec4e88672
......@@ -34,7 +34,7 @@ import java.util.List;
public class VirtualLinkListCommand extends AbstractShellCommand {
private static final String FMT_VIRTUAL_LINK =
"src=%s, dst=%s, tunnelId=%s";
"src=%s, dst=%s, state=%s, tunnelId=%s";
@Argument(index = 0, name = "networkId", description = "Network ID",
required = true, multiValued = false)
......@@ -66,6 +66,7 @@ public class VirtualLinkListCommand extends AbstractShellCommand {
*/
private void printVirtualLink(VirtualLink virtualLink) {
print(FMT_VIRTUAL_LINK, virtualLink.src().toString(), virtualLink.dst().toString(),
virtualLink.state(),
virtualLink.tunnelId() == null ? null : virtualLink.tunnelId().toString());
}
}
......
......@@ -42,7 +42,7 @@ public class DefaultEdgeLink extends DefaultLink implements EdgeLink {
HostLocation hostLocation, boolean isIngress,
Annotations... annotations) {
super(providerId, isIngress ? hostPoint : hostLocation,
isIngress ? hostLocation : hostPoint, Type.EDGE, annotations);
isIngress ? hostLocation : hostPoint, Type.EDGE, State.ACTIVE, annotations);
checkArgument(hostPoint.elementId() instanceof HostId,
"Host point does not refer to a host ID");
this.hostId = (HostId) hostPoint.elementId();
......
......@@ -36,17 +36,18 @@ public class DefaultLink extends AbstractProjectableModel implements Link {
private final boolean isExpected;
/**
* Creates an active infrastructure link using the supplied information.
* Creates an infrastructure link using the supplied information.
*
* @param providerId provider identity
* @param src link source
* @param dst link destination
* @param type link type
* @param state link state
* @param annotations optional key/value annotations
*/
protected DefaultLink(ProviderId providerId, ConnectPoint src, ConnectPoint dst,
Type type, Annotations... annotations) {
this(providerId, src, dst, type, ACTIVE, false, annotations);
Type type, State state, Annotations... annotations) {
this(providerId, src, dst, type, state, false, annotations);
}
/**
......
......@@ -44,7 +44,7 @@ public class DefaultPath extends DefaultLink implements Path {
*/
public DefaultPath(ProviderId providerId, List<Link> links, double cost,
Annotations... annotations) {
super(providerId, source(links), destination(links), Type.INDIRECT, annotations);
super(providerId, source(links), destination(links), Type.INDIRECT, State.ACTIVE, annotations);
this.links = ImmutableList.copyOf(links);
this.cost = cost;
}
......
......@@ -42,11 +42,11 @@ public class DefaultLinkTest {
@Test
public void testEquality() {
Link l1 = new DefaultLink(PID, cp(DID1, P1), cp(DID2, P2), DIRECT);
Link l2 = new DefaultLink(PID, cp(DID1, P1), cp(DID2, P2), DIRECT);
Link l3 = new DefaultLink(PID, cp(DID1, P2), cp(DID2, P2), DIRECT);
Link l4 = new DefaultLink(PID, cp(DID1, P2), cp(DID2, P2), DIRECT);
Link l5 = new DefaultLink(PID, cp(DID1, P2), cp(DID2, P2), INDIRECT);
Link l1 = new DefaultLink(PID, cp(DID1, P1), cp(DID2, P2), DIRECT, Link.State.ACTIVE);
Link l2 = new DefaultLink(PID, cp(DID1, P1), cp(DID2, P2), DIRECT, Link.State.ACTIVE);
Link l3 = new DefaultLink(PID, cp(DID1, P2), cp(DID2, P2), DIRECT, Link.State.ACTIVE);
Link l4 = new DefaultLink(PID, cp(DID1, P2), cp(DID2, P2), DIRECT, Link.State.ACTIVE);
Link l5 = new DefaultLink(PID, cp(DID1, P2), cp(DID2, P2), INDIRECT, Link.State.ACTIVE);
new EqualsTester().addEqualityGroup(l1, l2)
.addEqualityGroup(l3, l4)
......@@ -56,7 +56,7 @@ public class DefaultLinkTest {
@Test
public void basics() {
Link link = new DefaultLink(PID, cp(DID1, P1), cp(DID2, P2), DIRECT);
Link link = new DefaultLink(PID, cp(DID1, P1), cp(DID2, P2), DIRECT, Link.State.ACTIVE);
assertEquals("incorrect src", cp(DID1, P1), link.src());
assertEquals("incorrect dst", cp(DID2, P2), link.dst());
assertEquals("incorrect type", DIRECT, link.type());
......
......@@ -81,7 +81,7 @@ public final class NetTestTools {
return new DefaultLink(PID,
connectPoint(src, sp),
connectPoint(dst, dp),
Link.Type.DIRECT);
Link.Type.DIRECT, Link.State.ACTIVE);
}
// Creates a path that leads through the given devices.
......
......@@ -44,10 +44,12 @@ public final class DefaultVirtualLink extends DefaultLink implements VirtualLink
* @param networkId network identifier
* @param src source connection point
* @param dst destination connection point
* @param state link state
* @param tunnelId tunnel identifier
*/
private DefaultVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
super(PID, src, dst, Type.VIRTUAL, DefaultAnnotations.builder().build());
private DefaultVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
State state, TunnelId tunnelId) {
super(PID, src, dst, Type.VIRTUAL, state, DefaultAnnotations.builder().build());
this.networkId = networkId;
this.tunnelId = tunnelId;
}
......@@ -107,6 +109,7 @@ public final class DefaultVirtualLink extends DefaultLink implements VirtualLink
private ConnectPoint src;
private ConnectPoint dst;
private TunnelId tunnelId;
private State state;
private Builder() {
// Hide constructor
......@@ -157,6 +160,17 @@ public final class DefaultVirtualLink extends DefaultLink implements VirtualLink
}
/**
* Sets the link state to be used by the builder.
*
* @param state link state
* @return self
*/
public Builder state(State state) {
this.state = state;
return this;
}
/**
* Builds a default virtual link object from the accumulated parameters.
*
* @return default virtual link object
......@@ -166,7 +180,7 @@ public final class DefaultVirtualLink extends DefaultLink implements VirtualLink
checkNotNull(dst, "Destination connect point cannot be null");
checkNotNull(networkId, "Network Id cannot be null");
return new DefaultVirtualLink(networkId, src, dst, tunnelId);
return new DefaultVirtualLink(networkId, src, dst, state, tunnelId);
}
}
}
......
......@@ -15,6 +15,7 @@
*/
package org.onosproject.incubator.net.virtual;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.provider.ProviderService;
......@@ -30,8 +31,9 @@ public interface VirtualNetworkProviderService extends ProviderService<VirtualNe
* @param networkId network identifier
* @param src source connection point
* @param dst destination connection point
* @param tunnelId tunnel identifier
*/
void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId);
/**
* This method is used to notify the VirtualNetwork service that a tunnel is now
......@@ -40,7 +42,8 @@ public interface VirtualNetworkProviderService extends ProviderService<VirtualNe
* @param networkId network identifier
* @param src source connection point
* @param dst destination connection point
* @param tunnelId tunnel identifier
*/
void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId);
}
......
......@@ -60,7 +60,9 @@ public interface VirtualNetworkService {
Set<VirtualLink> getVirtualLinks(NetworkId networkId);
/**
* Returns list of all virtual ports of the specified device.
* Returns list of all virtual ports of the specified device. If the
* device identifier is null then all of the virtual ports in the specified
* network will be returned.
*
* @param networkId network identifier
* @param deviceId device identifier
......
......@@ -18,6 +18,7 @@ package org.onosproject.incubator.net.virtual;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.store.Store;
......@@ -89,18 +90,20 @@ public interface VirtualNetworkStore
* @param networkId network identifier
* @param src source end-point of the link
* @param dst destination end-point of the link
* @param state link state
* @param realizedBy underlying tunnel identifier using which this link is realized
* @return the virtual link
*/
VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy);
VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, Link.State state, TunnelId realizedBy);
/**
* Updates the tunnelId in the virtual link.
*
* @param virtualLink virtual link
* @param tunnelId tunnel identifier
* @param state link state
*/
void updateLink(VirtualLink virtualLink, TunnelId tunnelId);
void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state);
/**
* Removes the specified link from the store.
......@@ -158,6 +161,17 @@ public interface VirtualNetworkStore
Set<VirtualLink> getLinks(NetworkId networkId);
/**
* Returns the virtual link matching the network identifier, source connect point,
* and destination connect point.
*
* @param networkId network identifier
* @param src source connect point
* @param dst destination connect point
* @return virtual link
*/
VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst);
/**
* Returns the list of ports of the specified virtual device.
*
* @param networkId network identifier
......
......@@ -35,8 +35,9 @@ import org.onosproject.net.ConnectPoint;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
......@@ -45,9 +46,9 @@ import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.Thread.sleep;
import static org.slf4j.LoggerFactory.getLogger;
/**
......@@ -55,13 +56,15 @@ import static org.slf4j.LoggerFactory.getLogger;
*/
@Component(immediate = true)
@Service
public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider implements VirtualNetworkProvider {
public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider
implements VirtualNetworkProvider {
private final Logger log = getLogger(PtToPtIntentVirtualNetworkProvider.class);
private static final String NETWORK_ID_NULL = "Network ID cannot be null";
private static final String CONNECT_POINT_NULL = "Connect Point cannot be null";
private static final String INTENT_NULL = "Intent cannot be null";
protected static final String KEY_FORMAT = "networkId=%s src=%s dst=%s";
private static final String NETWORK_ID = "networkId=";
protected static final String KEY_FORMAT = NETWORK_ID + "%s, src=%s, dst=%s";
private static final int MAX_WAIT_COUNT = 30;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
......@@ -72,6 +75,8 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider impleme
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
private final InternalPtPtIntentListener intentListener = new InternalPtPtIntentListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
......@@ -90,11 +95,13 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider impleme
providerService = providerRegistry.register(this);
appId = coreService.registerApplication(PTPT_INTENT_APPID);
intentService.addListener(intentListener);
log.info("Started");
}
@Deactivate
public void deactivate() {
intentService.removeListener(intentListener);
providerRegistry.unregister(this);
providerService = null;
log.info("Stopped");
......@@ -105,8 +112,7 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider impleme
checkNotNull(networkId, NETWORK_ID_NULL);
checkNotNull(src, CONNECT_POINT_NULL);
checkNotNull(dst, CONNECT_POINT_NULL);
String key = String.format(KEY_FORMAT, networkId.toString(), src.toString(), dst.toString());
Key intentKey = Key.of(key, appId);
Key intentKey = encodeKey(networkId, src, dst);
List<Constraint> constraints = new ArrayList<>();
constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
......@@ -123,7 +129,7 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider impleme
intentService.submit(intent);
// construct tunnelId from the key
return TunnelId.valueOf(key);
return TunnelId.valueOf(intentKey.toString());
}
@Override
......@@ -133,20 +139,64 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider impleme
Intent intent = intentService.getIntent(intentKey);
checkNotNull(intent, INTENT_NULL);
intentService.withdraw(intent);
try {
int count = 0;
// Loop waiting for the intent to go into a withdrawn or failed state
// before attempting to purge it.
while (++count <= MAX_WAIT_COUNT) {
IntentState state = intentService.getIntentState(intentKey);
if ((state == IntentState.FAILED) || (state == IntentState.WITHDRAWN)) {
}
private NetworkId decodeNetworkIdFromKey(Key intentKey) {
// Extract the network identifier from the intent key
StringTokenizer tokenizer = new StringTokenizer(intentKey.toString(), ",");
String networkIdString = tokenizer.nextToken().substring(NETWORK_ID.length());
return NetworkId.networkId(Integer.valueOf(networkIdString));
}
private Key encodeKey(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
String key = String.format(KEY_FORMAT, networkId, src, dst);
return Key.of(key, appId);
}
private class InternalPtPtIntentListener implements IntentListener {
@Override
public void event(IntentEvent event) {
PointToPointIntent intent = (PointToPointIntent) event.subject();
Key intentKey = intent.key();
// Ignore intent events that are not relevant.
if (!isRelevant(event)) {
return;
}
NetworkId networkId = decodeNetworkIdFromKey(intentKey);
ConnectPoint src = intent.ingressPoint();
ConnectPoint dst = intent.egressPoint();
switch (event.type()) {
case INSTALLED:
providerService.tunnelUp(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
break;
case WITHDRAWN:
intentService.purge(intent);
// Fall through and notify the provider service that the tunnel is down
// for both WITHDRAWN and FAILED intent event types.
case FAILED:
providerService.tunnelDown(networkId, src, dst, TunnelId.valueOf(intentKey.toString()));
break;
case INSTALL_REQ:
case CORRUPT:
case PURGED:
break; // Not sure what do with these events, ignore for now.
default:
break;
}
sleep(1000);
}
} catch (Exception e) {
log.error("Exception: " + e);
@Override
public boolean isRelevant(IntentEvent event) {
PointToPointIntent intent = (PointToPointIntent) event.subject();
// Only events that are for this appId are relevent.
if (intent.appId().equals(appId)) {
return true;
}
return false;
}
}
}
......
......@@ -39,6 +39,7 @@ import org.onosproject.incubator.net.virtual.VirtualNetworkStoreDelegate;
import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
......@@ -140,7 +141,7 @@ public class VirtualNetworkManager
checkNotNull(networkId, NETWORK_NULL);
checkNotNull(src, LINK_POINT_NULL);
checkNotNull(dst, LINK_POINT_NULL);
VirtualLink virtualLink = store.addLink(networkId, src, dst, null);
VirtualLink virtualLink = store.addLink(networkId, src, dst, Link.State.INACTIVE, null);
checkNotNull(virtualLink, VIRTUAL_LINK_NULL);
if (virtualLink.providerId() != null) {
......@@ -148,7 +149,7 @@ public class VirtualNetworkManager
if (provider != null) {
TunnelId tunnelId = provider.createTunnel(networkId, mapVirtualToPhysicalPort(networkId, src),
mapVirtualToPhysicalPort(networkId, dst));
store.updateLink(virtualLink, tunnelId);
store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
}
}
return virtualLink;
......@@ -173,6 +174,25 @@ public class VirtualNetworkManager
return null;
}
/**
* Maps the physical connect point to a virtual connect point.
*
* @param networkId network identifier
* @param physicalCp physical connect point
* @return virtual connect point
*/
private ConnectPoint mapPhysicalToVirtualToPort(NetworkId networkId,
ConnectPoint physicalCp) {
Set<VirtualPort> ports = store.getPorts(networkId, null);
for (VirtualPort port : ports) {
if (port.realizedBy().element().id().equals(physicalCp.elementId()) &&
port.realizedBy().number().equals(physicalCp.port())) {
return new ConnectPoint(port.element().id(), port.number());
}
}
return null;
}
@Override
public void removeVirtualLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
checkNotNull(networkId, NETWORK_NULL);
......@@ -226,7 +246,6 @@ public class VirtualNetworkManager
@Override
public Set<VirtualPort> getVirtualPorts(NetworkId networkId, DeviceId deviceId) {
checkNotNull(networkId, NETWORK_NULL);
checkNotNull(deviceId, DEVICE_NULL);
return store.getPorts(networkId, deviceId);
}
......@@ -251,13 +270,32 @@ public class VirtualNetworkManager
}
@Override
public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
log.error("Src or dst virtual connection point was not found.");
}
VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
if (virtualLink != null) {
store.updateLink(virtualLink, tunnelId, Link.State.ACTIVE);
}
}
@Override
public void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
public void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
ConnectPoint dstVirtualCp = mapPhysicalToVirtualToPort(networkId, dst);
if ((srcVirtualCp == null) || (dstVirtualCp == null)) {
log.error("Src or dst virtual connection point was not found.");
}
VirtualLink virtualLink = store.getLink(networkId, srcVirtualCp, dstVirtualCp);
if (virtualLink != null) {
store.updateLink(virtualLink, tunnelId, Link.State.INACTIVE);
}
}
}
......
......@@ -16,7 +16,7 @@
package org.onosproject.incubator.net.virtual.impl;
import com.google.common.collect.Sets;
import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
......@@ -33,21 +33,29 @@ import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.intent.FakeIntentManager;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentServiceAdapter;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentTestsMocks;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.PointToPointIntent;
import org.onosproject.net.intent.TestableIntentService;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.net.provider.ProviderId;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
/**
* Junit tests for PtToPtIntentVirtualNetworkProvider.
......@@ -58,12 +66,19 @@ public class PtToPtIntentVirtualNetworkProviderTest {
private VirtualNetworkProviderRegistry providerRegistry;
private final VirtualNetworkRegistryAdapter virtualNetworkRegistry = new VirtualNetworkRegistryAdapter();
private IntentService intentService;
private TestableIntentService intentService = new FakeIntentManager();
private TestListener listener = new TestListener();
protected TestIntentCompiler compiler = new TestIntentCompiler();
private IntentExtensionService intentExtensionService;
private static final ApplicationId APP_ID =
TestApplicationId.create(PtToPtIntentVirtualNetworkProvider.PTPT_INTENT_APPID);
private IdGenerator idGenerator = new MockIdGenerator();
private static final int MAX_WAIT_TIME = 5;
private static final int MAX_PERMITS = 2;
private static Semaphore created;
private static Semaphore removed;
@Before
public void setUp() {
......@@ -77,18 +92,28 @@ public class PtToPtIntentVirtualNetworkProviderTest {
Intent.unbindIdGenerator(idGenerator);
Intent.bindIdGenerator(idGenerator);
intentService = new TestIntentService();
intentService.addListener(listener);
provider.intentService = intentService;
// Register a compiler and an installer both setup for success.
intentExtensionService = intentService;
intentExtensionService.registerCompiler(PointToPointIntent.class, compiler);
provider.activate();
created = new Semaphore(0, true);
removed = new Semaphore(0, true);
}
@After
public void tearDown() {
Intent.unbindIdGenerator(idGenerator);
intentService.removeListener(listener);
provider.deactivate();
provider.providerRegistry = null;
provider.coreService = null;
provider.intentService = null;
Intent.unbindIdGenerator(idGenerator);
created = null;
removed = null;
}
@Test
......@@ -134,11 +159,30 @@ public class PtToPtIntentVirtualNetworkProviderTest {
ConnectPoint dst = new ConnectPoint(DeviceId.deviceId("device2"), PortNumber.portNumber(2));
TunnelId tunnelId = provider.createTunnel(networkId, src, dst);
// Wait for the tunnel to go into an INSTALLED state, and that the tunnelUp method was called.
try {
if (!created.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
fail("Failed to wait for tunnel to get installed.");
}
} catch (InterruptedException e) {
fail("Semaphore exception during tunnel installation." + e.getMessage());
}
String key = String.format(PtToPtIntentVirtualNetworkProvider.KEY_FORMAT,
networkId.toString(), src.toString(), dst.toString());
assertEquals("TunnelId does not match as expected.", key, tunnelId.toString());
provider.destroyTunnel(networkId, tunnelId);
// Wait for the tunnel to go into a WITHDRAWN state, and that the tunnelDown method was called.
try {
if (!removed.tryAcquire(MAX_PERMITS, MAX_WAIT_TIME, TimeUnit.SECONDS)) {
fail("Failed to wait for tunnel to get removed.");
}
} catch (InterruptedException e) {
fail("Semaphore exception during tunnel removal." + e.getMessage());
}
}
/**
......@@ -176,16 +220,36 @@ public class PtToPtIntentVirtualNetworkProviderTest {
}
@Override
public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
// Release one permit on the created semaphore since the tunnelUp method was called.
created.release();
}
@Override
public void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
public void tunnelDown(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
// Release one permit on the removed semaphore since the tunnelDown method was called.
removed.release();
}
}
private static class TestListener implements IntentListener {
@Override
public void event(IntentEvent event) {
switch (event.type()) {
case INSTALLED:
// Release one permit on the created semaphore since the Intent event was received.
created.release();
break;
case WITHDRAWN:
// Release one permit on the removed semaphore since the Intent event was received.
removed.release();
break;
default:
break;
}
}
}
/**
* Core service test class.
......@@ -205,55 +269,17 @@ public class PtToPtIntentVirtualNetworkProviderTest {
}
}
/**
* Represents a fake IntentService class that easily allows to store and
* retrieve intents without implementing the IntentService logic.
*/
private class TestIntentService extends IntentServiceAdapter {
private Set<Intent> intents;
public TestIntentService() {
intents = Sets.newHashSet();
}
@Override
public void submit(Intent intent) {
intents.add(intent);
}
@Override
public void withdraw(Intent intent) {
}
@Override
public IntentState getIntentState(Key intentKey) {
return IntentState.WITHDRAWN;
}
private static class TestIntentCompiler implements IntentCompiler<PointToPointIntent> {
@Override
public void purge(Intent intent) {
intents.remove(intent);
public List<Intent> compile(PointToPointIntent intent, List<Intent> installable) {
return Lists.newArrayList(new MockInstallableIntent());
}
@Override
public long getIntentCount() {
return intents.size();
}
@Override
public Iterable<Intent> getIntents() {
return intents;
}
private static class MockInstallableIntent extends FlowRuleIntent {
@Override
public Intent getIntent(Key intentKey) {
for (Intent intent : intents) {
if (intent.key().equals(intentKey)) {
return intent;
}
}
return null;
public MockInstallableIntent() {
super(APP_ID, Collections.singletonList(new IntentTestsMocks.MockFlowRule(100)), Collections.emptyList());
}
}
}
......
......@@ -44,6 +44,7 @@ import org.onosproject.incubator.net.virtual.VirtualPort;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.store.AbstractStore;
......@@ -295,6 +296,7 @@ public class DistributedVirtualNetworkStore
* @return true if the network identifier exists, false otherwise.
*/
private boolean networkExists(NetworkId networkId) {
checkNotNull(networkId, "The network identifier cannot be null.");
return (networkIdVirtualNetworkMap.containsKey(networkId));
}
......@@ -339,7 +341,8 @@ public class DistributedVirtualNetworkStore
}
@Override
public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId realizedBy) {
public VirtualLink addLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst,
Link.State state, TunnelId realizedBy) {
checkState(networkExists(networkId), "The network has not been added.");
Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
if (virtualLinkSet == null) {
......@@ -352,6 +355,7 @@ public class DistributedVirtualNetworkStore
.networkId(networkId)
.src(src)
.dst(dst)
.state(state)
.tunnelId(realizedBy)
.build();
......@@ -361,7 +365,7 @@ public class DistributedVirtualNetworkStore
}
@Override
public void updateLink(VirtualLink virtualLink, TunnelId tunnelId) {
public void updateLink(VirtualLink virtualLink, TunnelId tunnelId, Link.State state) {
checkState(networkExists(virtualLink.networkId()), "The network has not been added.");
Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(virtualLink.networkId());
if (virtualLinkSet == null) {
......@@ -374,6 +378,7 @@ public class DistributedVirtualNetworkStore
.src(virtualLink.src())
.dst(virtualLink.dst())
.tunnelId(tunnelId)
.state(state)
.build();
virtualLinkSet.add(newVirtualLink);
......@@ -471,16 +476,8 @@ public class DistributedVirtualNetworkStore
return ImmutableSet.copyOf(virtualLinkSet);
}
/**
* Returns the virtual link matching the network identifier, source connect point,
* and destination connect point.
*
* @param networkId network identifier
* @param src source connect point
* @param dst destination connect point
* @return virtual link
*/
private VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
@Override
public VirtualLink getLink(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
Set<VirtualLink> virtualLinkSet = networkIdVirtualLinkSetMap.get(networkId);
if (virtualLinkSet == null) {
return null;
......@@ -504,6 +501,10 @@ public class DistributedVirtualNetworkStore
virtualPortSet = new HashSet<>();
}
if (deviceId == null) {
return ImmutableSet.copyOf(virtualPortSet);
}
Set<VirtualPort> portSet = new HashSet<>();
virtualPortSet.forEach(virtualPort -> {
if (virtualPort.element().id().equals(deviceId)) {
......