Brian Stanke
Committed by Gerrit Code Review

ONOS-2184 - Implementation of virtual network topology provider.

Change-Id: I846ba56c138187c6e5435692798e709b74a78020
...@@ -37,6 +37,7 @@ public abstract class TestDeviceParams { ...@@ -37,6 +37,7 @@ public abstract class TestDeviceParams {
37 protected static final DeviceId DID2 = deviceId("of:bar"); 37 protected static final DeviceId DID2 = deviceId("of:bar");
38 protected static final DeviceId DID3 = deviceId("of:who"); 38 protected static final DeviceId DID3 = deviceId("of:who");
39 protected static final DeviceId DID4 = deviceId("of:what"); 39 protected static final DeviceId DID4 = deviceId("of:what");
40 + protected static final DeviceId DID5 = deviceId("of:when");
40 protected static final MacAddress MAC1 = MacAddress.valueOf("00:11:00:00:00:01"); 41 protected static final MacAddress MAC1 = MacAddress.valueOf("00:11:00:00:00:01");
41 protected static final MacAddress MAC2 = MacAddress.valueOf("00:22:00:00:00:02"); 42 protected static final MacAddress MAC2 = MacAddress.valueOf("00:22:00:00:00:02");
42 protected static final VlanId VLAN1 = VlanId.vlanId((short) 11); 43 protected static final VlanId VLAN1 = VlanId.vlanId((short) 11);
......
...@@ -31,15 +31,12 @@ import org.onosproject.incubator.net.virtual.VirtualNetworkService; ...@@ -31,15 +31,12 @@ import org.onosproject.incubator.net.virtual.VirtualNetworkService;
31 import org.onosproject.incubator.net.virtual.VirtualNetworkStore; 31 import org.onosproject.incubator.net.virtual.VirtualNetworkStore;
32 import org.onosproject.incubator.net.virtual.VirtualPort; 32 import org.onosproject.incubator.net.virtual.VirtualPort;
33 import org.onosproject.net.ConnectPoint; 33 import org.onosproject.net.ConnectPoint;
34 -import org.onosproject.net.EncapsulationType;
35 import org.onosproject.net.Link; 34 import org.onosproject.net.Link;
36 import org.onosproject.net.Path; 35 import org.onosproject.net.Path;
37 -import org.onosproject.net.intent.Constraint;
38 import org.onosproject.net.intent.Intent; 36 import org.onosproject.net.intent.Intent;
39 import org.onosproject.net.intent.IntentService; 37 import org.onosproject.net.intent.IntentService;
40 import org.onosproject.net.intent.Key; 38 import org.onosproject.net.intent.Key;
41 import org.onosproject.net.intent.PointToPointIntent; 39 import org.onosproject.net.intent.PointToPointIntent;
42 -import org.onosproject.net.intent.constraint.EncapsulationConstraint;
43 import org.onosproject.net.intent.impl.IntentCompilationException; 40 import org.onosproject.net.intent.impl.IntentCompilationException;
44 import org.onosproject.net.topology.TopologyService; 41 import org.onosproject.net.topology.TopologyService;
45 import org.slf4j.Logger; 42 import org.slf4j.Logger;
...@@ -93,12 +90,32 @@ public class VirtualNetworkIntentCompiler ...@@ -93,12 +90,32 @@ public class VirtualNetworkIntentCompiler
93 Optional<Path> path = getPaths(intent).stream() 90 Optional<Path> path = getPaths(intent).stream()
94 .findFirst(); 91 .findFirst();
95 if (path != null && path.isPresent()) { 92 if (path != null && path.isPresent()) {
96 - path.get().links().forEach(link -> { 93 + List<Link> links = path.get().links();
97 - Intent physicalIntent = createPtPtIntent(intent, link);
98 - intents.add(physicalIntent);
99 94
100 - // store the virtual intent to physical intent tunnelId mapping 95 + // First create an intent between the intent ingress CP and the first link source CP,
101 - store.addTunnelId(intent, TunnelId.valueOf(physicalIntent.key().toString())); 96 + // only if the two CPs are not the same.
97 + Link firstLink = links.get(0);
98 + if (!intent.ingressPoint().equals(firstLink.src())) {
99 + intents.add(createPtPtIntent(intent, intent.ingressPoint(), firstLink.src()));
100 + }
101 +
102 + // Next create an intent between the intent egress CP and the last link destination CP,
103 + // only if the two CPs are not the same.
104 + Link lastLink = links.get(links.size() - 1);
105 + if (!intent.egressPoint().equals(lastLink.dst())) {
106 + intents.add(createPtPtIntent(intent, lastLink.dst(), intent.egressPoint()));
107 + }
108 +
109 + // Now loop through all of the virtual links in the path and create an intent.
110 + // An intent is also created connecting two virtual links.
111 + final int[] index = {0};
112 + links.forEach(link -> {
113 + intents.add(createPtPtIntent(intent, link.src(), link.dst()));
114 + if (index[0] > 0) {
115 + Link previousLink = links.get(index[0] - 1);
116 + intents.add(createPtPtIntent(intent, previousLink.dst(), link.src()));
117 + }
118 + index[0]++;
102 }); 119 });
103 } else { 120 } else {
104 throw new IntentCompilationException("Unable to find a path for intent " + intent); 121 throw new IntentCompilationException("Unable to find a path for intent " + intent);
...@@ -124,7 +141,7 @@ public class VirtualNetworkIntentCompiler ...@@ -124,7 +141,7 @@ public class VirtualNetworkIntentCompiler
124 } 141 }
125 142
126 /** 143 /**
127 - * Encodes the key using the network identifier, application identifer, source and destination 144 + * Encodes the key using the network identifier, application identifier, source and destination
128 * connect points. 145 * connect points.
129 * 146 *
130 * @param networkId virtual network identifier 147 * @param networkId virtual network identifier
...@@ -133,26 +150,26 @@ public class VirtualNetworkIntentCompiler ...@@ -133,26 +150,26 @@ public class VirtualNetworkIntentCompiler
133 * @param dst destination connect point 150 * @param dst destination connect point
134 * @return encoded key 151 * @return encoded key
135 */ 152 */
153 +
136 private static Key encodeKey(NetworkId networkId, ApplicationId applicationId, ConnectPoint src, ConnectPoint dst) { 154 private static Key encodeKey(NetworkId networkId, ApplicationId applicationId, ConnectPoint src, ConnectPoint dst) {
137 String key = String.format(KEY_FORMAT, networkId, src, dst); 155 String key = String.format(KEY_FORMAT, networkId, src, dst);
138 return Key.of(key, applicationId); 156 return Key.of(key, applicationId);
139 } 157 }
140 158
141 /** 159 /**
142 - * Creates a point-to-point intent from the virtual network intent and virtual link. 160 + * Creates a point-to-point intent using the virtual network intent between the source and destination
161 + * connect point.
143 * 162 *
144 * @param intent virtual network intent 163 * @param intent virtual network intent
145 - * @param link virtual link 164 + * @param src source connect point
165 + * @param dst destination connect point
146 * @return point to point intent 166 * @return point to point intent
147 */ 167 */
148 - private Intent createPtPtIntent(VirtualNetworkIntent intent, Link link) { 168 + private Intent createPtPtIntent(VirtualNetworkIntent intent, ConnectPoint src, ConnectPoint dst) {
149 - ConnectPoint ingressPoint = mapVirtualToPhysicalPort(intent.networkId(), link.src()); 169 + ConnectPoint ingressPoint = mapVirtualToPhysicalPort(intent.networkId(), src);
150 - ConnectPoint egressPoint = mapVirtualToPhysicalPort(intent.networkId(), link.dst()); 170 + ConnectPoint egressPoint = mapVirtualToPhysicalPort(intent.networkId(), dst);
151 Key intentKey = encodeKey(intent.networkId(), intent.appId(), ingressPoint, egressPoint); 171 Key intentKey = encodeKey(intent.networkId(), intent.appId(), ingressPoint, egressPoint);
152 172
153 - List<Constraint> constraints = new ArrayList<>();
154 - constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
155 -
156 // TODO Currently there can only be one intent between the ingress and egress across 173 // TODO Currently there can only be one intent between the ingress and egress across
157 // all virtual networks. We may want to support multiple intents between the same src/dst pairs. 174 // all virtual networks. We may want to support multiple intents between the same src/dst pairs.
158 PointToPointIntent physicalIntent = PointToPointIntent.builder() 175 PointToPointIntent physicalIntent = PointToPointIntent.builder()
...@@ -160,11 +177,16 @@ public class VirtualNetworkIntentCompiler ...@@ -160,11 +177,16 @@ public class VirtualNetworkIntentCompiler
160 .appId(intent.appId()) 177 .appId(intent.appId())
161 .ingressPoint(ingressPoint) 178 .ingressPoint(ingressPoint)
162 .egressPoint(egressPoint) 179 .egressPoint(egressPoint)
163 - .constraints(constraints) 180 + .constraints(intent.constraints())
181 + .selector(intent.selector())
182 + .treatment(intent.treatment())
164 .build(); 183 .build();
165 log.debug("Submitting physical intent: " + physicalIntent); 184 log.debug("Submitting physical intent: " + physicalIntent);
166 intentService.submit(physicalIntent); 185 intentService.submit(physicalIntent);
167 186
187 + // Store the physical intent against this virtual intent.
188 + store.addTunnelId(intent, TunnelId.valueOf(physicalIntent.key().toString()));
189 +
168 return physicalIntent; 190 return physicalIntent;
169 } 191 }
170 192
......
...@@ -39,13 +39,11 @@ import org.onosproject.incubator.net.virtual.impl.VirtualNetworkManager; ...@@ -39,13 +39,11 @@ import org.onosproject.incubator.net.virtual.impl.VirtualNetworkManager;
39 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore; 39 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
40 import org.onosproject.net.ConnectPoint; 40 import org.onosproject.net.ConnectPoint;
41 import org.onosproject.net.DefaultPort; 41 import org.onosproject.net.DefaultPort;
42 -import org.onosproject.net.EncapsulationType;
43 import org.onosproject.net.Link; 42 import org.onosproject.net.Link;
44 import org.onosproject.net.NetTestTools; 43 import org.onosproject.net.NetTestTools;
45 import org.onosproject.net.Port; 44 import org.onosproject.net.Port;
46 import org.onosproject.net.PortNumber; 45 import org.onosproject.net.PortNumber;
47 import org.onosproject.net.TestDeviceParams; 46 import org.onosproject.net.TestDeviceParams;
48 -import org.onosproject.net.intent.Constraint;
49 import org.onosproject.net.intent.FakeIntentManager; 47 import org.onosproject.net.intent.FakeIntentManager;
50 import org.onosproject.net.intent.Intent; 48 import org.onosproject.net.intent.Intent;
51 import org.onosproject.net.intent.IntentExtensionService; 49 import org.onosproject.net.intent.IntentExtensionService;
...@@ -53,10 +51,8 @@ import org.onosproject.net.intent.IntentService; ...@@ -53,10 +51,8 @@ import org.onosproject.net.intent.IntentService;
53 import org.onosproject.net.intent.Key; 51 import org.onosproject.net.intent.Key;
54 import org.onosproject.net.intent.MockIdGenerator; 52 import org.onosproject.net.intent.MockIdGenerator;
55 import org.onosproject.net.intent.TestableIntentService; 53 import org.onosproject.net.intent.TestableIntentService;
56 -import org.onosproject.net.intent.constraint.EncapsulationConstraint;
57 import org.onosproject.store.service.TestStorageService; 54 import org.onosproject.store.service.TestStorageService;
58 55
59 -import java.util.ArrayList;
60 import java.util.Collections; 56 import java.util.Collections;
61 import java.util.List; 57 import java.util.List;
62 import java.util.concurrent.atomic.AtomicLong; 58 import java.util.concurrent.atomic.AtomicLong;
...@@ -192,6 +188,9 @@ public class VirtualNetworkIntentCompilerTest extends TestDeviceParams { ...@@ -192,6 +188,9 @@ public class VirtualNetworkIntentCompilerTest extends TestDeviceParams {
192 return virtualNetwork; 188 return virtualNetwork;
193 } 189 }
194 190
191 + /**
192 + * Tests the virtual network intent compiler.
193 + */
195 @Test 194 @Test
196 public void testCompiler() { 195 public void testCompiler() {
197 compiler.activate(); 196 compiler.activate();
...@@ -199,20 +198,16 @@ public class VirtualNetworkIntentCompilerTest extends TestDeviceParams { ...@@ -199,20 +198,16 @@ public class VirtualNetworkIntentCompilerTest extends TestDeviceParams {
199 198
200 Key intentKey = Key.of("test", APP_ID); 199 Key intentKey = Key.of("test", APP_ID);
201 200
202 - List<Constraint> constraints = new ArrayList<>();
203 - constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
204 -
205 VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder() 201 VirtualNetworkIntent virtualIntent = VirtualNetworkIntent.builder()
206 .networkId(virtualNetwork.id()) 202 .networkId(virtualNetwork.id())
207 .key(intentKey) 203 .key(intentKey)
208 .appId(APP_ID) 204 .appId(APP_ID)
209 - .ingressPoint(cp1) 205 + .ingressPoint(cp2)
210 - .egressPoint(cp5) 206 + .egressPoint(cp6)
211 - .constraints(constraints)
212 .build(); 207 .build();
213 208
214 List<Intent> compiled = compiler.compile(virtualIntent, Collections.emptyList()); 209 List<Intent> compiled = compiler.compile(virtualIntent, Collections.emptyList());
215 - assertEquals("The virtual intents size is not as expected.", 2, compiled.size()); 210 + assertEquals("The virtual intents size is not as expected.", 5, compiled.size());
216 211
217 compiler.deactivate(); 212 compiler.deactivate();
218 } 213 }
......
...@@ -26,6 +26,18 @@ import org.onosproject.net.provider.Provider; ...@@ -26,6 +26,18 @@ import org.onosproject.net.provider.Provider;
26 public interface VirtualNetworkProvider extends Provider { 26 public interface VirtualNetworkProvider extends Provider {
27 27
28 /** 28 /**
29 + * Indicates whether or not the specified connect points on the underlying
30 + * network are traversable/reachable.
31 + *
32 + * @param src source connection point
33 + * @param dst destination connection point
34 + * @return true if the destination is reachable from the source
35 + */
36 + boolean isTraversable(ConnectPoint src, ConnectPoint dst);
37 +
38 + // TODO: Further enhance this interface to support the virtual intent programming across this boundary.
39 +
40 + /**
29 * Creates a network tunnel for all traffic from the specified source 41 * Creates a network tunnel for all traffic from the specified source
30 * connection point to the indicated destination connection point. 42 * connection point to the indicated destination connection point.
31 * 43 *
......
...@@ -19,6 +19,8 @@ import org.onosproject.incubator.net.tunnel.TunnelId; ...@@ -19,6 +19,8 @@ import org.onosproject.incubator.net.tunnel.TunnelId;
19 import org.onosproject.net.ConnectPoint; 19 import org.onosproject.net.ConnectPoint;
20 import org.onosproject.net.provider.ProviderService; 20 import org.onosproject.net.provider.ProviderService;
21 21
22 +import java.util.Set;
23 +
22 /** 24 /**
23 * Service through which virtual network providers can inject information into 25 * Service through which virtual network providers can inject information into
24 * the core. 26 * the core.
...@@ -26,6 +28,18 @@ import org.onosproject.net.provider.ProviderService; ...@@ -26,6 +28,18 @@ import org.onosproject.net.provider.ProviderService;
26 public interface VirtualNetworkProviderService extends ProviderService<VirtualNetworkProvider> { 28 public interface VirtualNetworkProviderService extends ProviderService<VirtualNetworkProvider> {
27 29
28 /** 30 /**
31 + * Set of separate topology clusters expressed in terms of connect points which
32 + * belong to the same SCC of the underlying topology.
33 + *
34 + * @param clusters set of sets of mutually reachable connection points;
35 + * the outer sets are not mutually reachable
36 + */
37 + void topologyChanged(Set<Set<ConnectPoint>> clusters);
38 +
39 + // TBD: Is the above sufficient to determine health/viability of virtual entities based on
40 + // clustering (SCC) of the physical ones?
41 +
42 + /**
29 * This method is used to notify the VirtualNetwork service that a tunnel is now ACTIVE. 43 * This method is used to notify the VirtualNetwork service that a tunnel is now ACTIVE.
30 * 44 *
31 * @param networkId network identifier 45 * @param networkId network identifier
......
...@@ -108,6 +108,11 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider ...@@ -108,6 +108,11 @@ public class PtToPtIntentVirtualNetworkProvider extends AbstractProvider
108 } 108 }
109 109
110 @Override 110 @Override
111 + public boolean isTraversable(ConnectPoint src, ConnectPoint dst) {
112 + return false;
113 + }
114 +
115 + @Override
111 public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) { 116 public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
112 checkNotNull(networkId, NETWORK_ID_NULL); 117 checkNotNull(networkId, NETWORK_ID_NULL);
113 checkNotNull(src, CONNECT_POINT_NULL); 118 checkNotNull(src, CONNECT_POINT_NULL);
......
...@@ -46,7 +46,7 @@ import java.util.Optional; ...@@ -46,7 +46,7 @@ import java.util.Optional;
46 import static com.google.common.base.Preconditions.*; 46 import static com.google.common.base.Preconditions.*;
47 47
48 /** 48 /**
49 - * intent service implementation built on the virtual network service. 49 + * Intent service implementation built on the virtual network service.
50 */ 50 */
51 public class VirtualNetworkIntentService extends AbstractListenerManager<IntentEvent, IntentListener> 51 public class VirtualNetworkIntentService extends AbstractListenerManager<IntentEvent, IntentListener>
52 implements IntentService, VnetService { 52 implements IntentService, VnetService {
...@@ -148,18 +148,17 @@ public class VirtualNetworkIntentService extends AbstractListenerManager<IntentE ...@@ -148,18 +148,17 @@ public class VirtualNetworkIntentService extends AbstractListenerManager<IntentE
148 public void withdraw(Intent intent) { 148 public void withdraw(Intent intent) {
149 checkNotNull(intent, INTENT_NULL); 149 checkNotNull(intent, INTENT_NULL);
150 // Withdraws the physical intents created due to the virtual intents. 150 // Withdraws the physical intents created due to the virtual intents.
151 - store.getTunnelIds(intent) 151 + store.getTunnelIds(intent).forEach(tunnelId -> {
152 - .forEach(tunnelId -> {
153 Key intentKey = Key.of(tunnelId.id(), intent.appId()); 152 Key intentKey = Key.of(tunnelId.id(), intent.appId());
154 Intent physicalIntent = intentService.getIntent(intentKey); 153 Intent physicalIntent = intentService.getIntent(intentKey);
155 checkNotNull(physicalIntent, INTENT_NULL); 154 checkNotNull(physicalIntent, INTENT_NULL);
156 155
157 // Withdraw the physical intent(s) 156 // Withdraw the physical intent(s)
158 - log.info("Withdrawing pt-pt intent: " + physicalIntent); 157 + log.debug("Withdrawing pt-pt intent: " + physicalIntent);
159 intentService.withdraw(physicalIntent); 158 intentService.withdraw(physicalIntent);
160 }); 159 });
161 // Now withdraw the virtual intent 160 // Now withdraw the virtual intent
162 - log.info("Withdrawing virtual intent: " + intent); 161 + log.debug("Withdrawing virtual intent: " + intent);
163 intentService.withdraw(intent); 162 intentService.withdraw(intent);
164 } 163 }
165 164
......
...@@ -27,6 +27,7 @@ import org.onlab.packet.IpAddress; ...@@ -27,6 +27,7 @@ import org.onlab.packet.IpAddress;
27 import org.onlab.packet.MacAddress; 27 import org.onlab.packet.MacAddress;
28 import org.onlab.packet.VlanId; 28 import org.onlab.packet.VlanId;
29 import org.onosproject.incubator.net.tunnel.TunnelId; 29 import org.onosproject.incubator.net.tunnel.TunnelId;
30 +import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
30 import org.onosproject.incubator.net.virtual.NetworkId; 31 import org.onosproject.incubator.net.virtual.NetworkId;
31 import org.onosproject.incubator.net.virtual.TenantId; 32 import org.onosproject.incubator.net.virtual.TenantId;
32 import org.onosproject.incubator.net.virtual.VirtualDevice; 33 import org.onosproject.incubator.net.virtual.VirtualDevice;
...@@ -197,7 +198,36 @@ public class VirtualNetworkManager ...@@ -197,7 +198,36 @@ public class VirtualNetworkManager
197 checkNotNull(networkId, NETWORK_NULL); 198 checkNotNull(networkId, NETWORK_NULL);
198 checkNotNull(src, LINK_POINT_NULL); 199 checkNotNull(src, LINK_POINT_NULL);
199 checkNotNull(dst, LINK_POINT_NULL); 200 checkNotNull(dst, LINK_POINT_NULL);
200 - return store.addLink(networkId, src, dst, Link.State.ACTIVE, null); 201 + ConnectPoint physicalSrc = mapVirtualToPhysicalPort(networkId, src);
202 + checkNotNull(physicalSrc, LINK_POINT_NULL);
203 + ConnectPoint physicalDst = mapVirtualToPhysicalPort(networkId, dst);
204 + checkNotNull(physicalDst, LINK_POINT_NULL);
205 +
206 + VirtualNetworkProvider provider = getProvider(DefaultVirtualLink.PID);
207 + Link.State state = Link.State.INACTIVE;
208 + if (provider != null) {
209 + boolean traversable = provider.isTraversable(physicalSrc, physicalDst);
210 + state = traversable ? Link.State.ACTIVE : Link.State.INACTIVE;
211 + }
212 + return store.addLink(networkId, src, dst, state, null);
213 + }
214 +
215 + /**
216 + * Maps the virtual connect point to a physical connect point.
217 + *
218 + * @param networkId network identifier
219 + * @param virtualCp virtual connect point
220 + * @return physical connect point
221 + */
222 + private ConnectPoint mapVirtualToPhysicalPort(NetworkId networkId,
223 + ConnectPoint virtualCp) {
224 + Set<VirtualPort> ports = store.getPorts(networkId, virtualCp.deviceId());
225 + for (VirtualPort port : ports) {
226 + if (port.number().equals(virtualCp.port())) {
227 + return new ConnectPoint(port.realizedBy().element().id(), port.realizedBy().number());
228 + }
229 + }
230 + return null;
201 } 231 }
202 232
203 /** 233 /**
...@@ -441,16 +471,73 @@ public class VirtualNetworkManager ...@@ -441,16 +471,73 @@ public class VirtualNetworkManager
441 return new InternalVirtualNetworkProviderService(provider); 471 return new InternalVirtualNetworkProviderService(provider);
442 } 472 }
443 473
444 - // Service issued to registered virtual network providers so that they 474 + /**
445 - // can interact with the core. 475 + * Service issued to registered virtual network providers so that they
476 + * can interact with the core.
477 + */
446 private class InternalVirtualNetworkProviderService 478 private class InternalVirtualNetworkProviderService
447 extends AbstractProviderService<VirtualNetworkProvider> 479 extends AbstractProviderService<VirtualNetworkProvider>
448 implements VirtualNetworkProviderService { 480 implements VirtualNetworkProviderService {
481 + /**
482 + * Constructor.
483 + * @param provider virtual network provider
484 + */
449 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) { 485 InternalVirtualNetworkProviderService(VirtualNetworkProvider provider) {
450 super(provider); 486 super(provider);
451 } 487 }
452 488
453 @Override 489 @Override
490 + public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
491 +
492 + Set<TenantId> tenantIds = getTenantIds();
493 + tenantIds.forEach(tenantId -> {
494 + Set<VirtualNetwork> virtualNetworks = getVirtualNetworks(tenantId);
495 +
496 + virtualNetworks.forEach(virtualNetwork -> {
497 + Set<VirtualLink> virtualLinks = getVirtualLinks(virtualNetwork.id());
498 +
499 + virtualLinks.forEach(virtualLink -> {
500 + if (isVirtualLinkInCluster(virtualNetwork.id(), virtualLink, clusters)) {
501 + store.updateLink(virtualLink, virtualLink.tunnelId(), Link.State.ACTIVE);
502 + } else {
503 + store.updateLink(virtualLink, virtualLink.tunnelId(), Link.State.INACTIVE);
504 + }
505 + });
506 + });
507 + });
508 + }
509 +
510 + /**
511 + * Determines if the virtual link (both source and destination connect point) is in a cluster.
512 + *
513 + * @param networkId virtual network identifier
514 + * @param virtualLink virtual link
515 + * @param clusters topology clusters
516 + * @return true if the virtual link is in a cluster.
517 + */
518 + private boolean isVirtualLinkInCluster(NetworkId networkId, VirtualLink virtualLink,
519 + Set<Set<ConnectPoint>> clusters) {
520 + ConnectPoint srcPhysicalCp = mapVirtualToPhysicalPort(networkId, virtualLink.src());
521 + ConnectPoint dstPhysicalCp = mapVirtualToPhysicalPort(networkId, virtualLink.dst());
522 +
523 + final boolean[] foundSrc = {false};
524 + final boolean[] foundDst = {false};
525 + clusters.forEach(connectPoints -> {
526 + connectPoints.forEach(connectPoint -> {
527 + if (connectPoint.equals(srcPhysicalCp)) {
528 + foundSrc[0] = true;
529 + } else if (connectPoint.equals(dstPhysicalCp)) {
530 + foundDst[0] = true;
531 + }
532 + });
533 + if (foundSrc[0] && foundDst[0]) {
534 + return;
535 + }
536 + });
537 + return foundSrc[0] && foundDst[0];
538 + }
539 +
540 + @Override
454 public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) { 541 public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
455 542
456 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src); 543 ConnectPoint srcVirtualCp = mapPhysicalToVirtualToPort(networkId, src);
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.incubator.net.virtual.impl;
18 +
19 +import org.apache.felix.scr.annotations.Activate;
20 +import org.apache.felix.scr.annotations.Component;
21 +import org.apache.felix.scr.annotations.Deactivate;
22 +import org.apache.felix.scr.annotations.Reference;
23 +import org.apache.felix.scr.annotations.ReferenceCardinality;
24 +import org.apache.felix.scr.annotations.Service;
25 +import org.onosproject.incubator.net.tunnel.TunnelId;
26 +import org.onosproject.incubator.net.virtual.DefaultVirtualLink;
27 +import org.onosproject.incubator.net.virtual.NetworkId;
28 +import org.onosproject.incubator.net.virtual.VirtualNetworkProvider;
29 +import org.onosproject.incubator.net.virtual.VirtualNetworkProviderRegistry;
30 +import org.onosproject.incubator.net.virtual.VirtualNetworkProviderService;
31 +import org.onosproject.net.ConnectPoint;
32 +import org.onosproject.net.Link;
33 +import org.onosproject.net.Path;
34 +import org.onosproject.net.link.LinkEvent;
35 +import org.onosproject.net.provider.AbstractProvider;
36 +import org.onosproject.net.topology.Topology;
37 +import org.onosproject.net.topology.TopologyCluster;
38 +import org.onosproject.net.topology.TopologyEvent;
39 +import org.onosproject.net.topology.TopologyListener;
40 +import org.onosproject.net.topology.TopologyService;
41 +import org.slf4j.Logger;
42 +
43 +import java.util.HashSet;
44 +import java.util.Set;
45 +
46 +import static org.slf4j.LoggerFactory.getLogger;
47 +
48 +/**
49 + * Virtual network topology provider.
50 + */
51 +@Component(immediate = true)
52 +@Service
53 +public class VirtualNetworkTopologyProvider extends AbstractProvider implements VirtualNetworkProvider {
54 +
55 + private final Logger log = getLogger(VirtualNetworkTopologyProvider.class);
56 +
57 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
58 + protected VirtualNetworkProviderRegistry providerRegistry;
59 +
60 + private VirtualNetworkProviderService providerService;
61 +
62 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
63 + protected TopologyService topologyService;
64 +
65 + protected TopologyListener topologyListener = new InternalTopologyListener();
66 +
67 + /**
68 + * Default constructor.
69 + */
70 + public VirtualNetworkTopologyProvider() {
71 + super(DefaultVirtualLink.PID);
72 + }
73 +
74 + @Activate
75 + public void activate() {
76 + providerService = providerRegistry.register(this);
77 + topologyService.addListener(topologyListener);
78 +
79 + log.info("Started");
80 + }
81 +
82 + @Deactivate
83 + public void deactivate() {
84 + topologyService.removeListener(topologyListener);
85 + providerRegistry.unregister(this);
86 + providerService = null;
87 + log.info("Stopped");
88 + }
89 +
90 + @Override
91 + public boolean isTraversable(ConnectPoint src, ConnectPoint dst) {
92 + final boolean[] foundSrc = new boolean[1];
93 + final boolean[] foundDst = new boolean[1];
94 + Topology topology = topologyService.currentTopology();
95 + Set<Path> paths = topologyService.getPaths(topology, src.deviceId(), dst.deviceId());
96 + paths.forEach(path -> {
97 + foundDst[0] = false;
98 + foundSrc[0] = false;
99 + // Traverse the links in each path to determine if both the src and dst connection
100 + // point are in the path, if so then this src/dst pair are traversable.
101 + path.links().forEach(link -> {
102 + if (link.src().equals(src)) {
103 + foundSrc[0] = true;
104 + }
105 + if (link.dst().equals(dst)) {
106 + foundDst[0] = true;
107 + }
108 + });
109 + if (foundSrc[0] && foundDst[0]) {
110 + return;
111 + }
112 + });
113 + return foundSrc[0] && foundDst[0];
114 + }
115 +
116 + @Override
117 + public TunnelId createTunnel(NetworkId networkId, ConnectPoint src, ConnectPoint dst) {
118 + return null;
119 + }
120 +
121 + @Override
122 + public void destroyTunnel(NetworkId networkId, TunnelId tunnelId) {
123 +
124 + }
125 +
126 + /**
127 + * Returns a set of set of interconnected connect points in the default topology.
128 + * The inner set represents the interconnected connect points, and the outerset
129 + * represents separate clusters.
130 + *
131 + * @param topology the default topology
132 + * @return set of set of interconnected connect points.
133 + */
134 + protected Set<Set<ConnectPoint>> getConnectPoints(Topology topology) {
135 + Set<Set<ConnectPoint>> clusters = new HashSet<>();
136 + Set<TopologyCluster> topologyClusters = topologyService.getClusters(topology);
137 + topologyClusters.forEach(topologyCluster -> {
138 + Set<ConnectPoint> connectPointSet = new HashSet<>();
139 + Set<Link> clusterLinks = topologyService.getClusterLinks(topology, topologyCluster);
140 + clusterLinks.forEach(link -> {
141 + connectPointSet.add(link.src());
142 + connectPointSet.add(link.dst());
143 + });
144 + if (!connectPointSet.isEmpty()) {
145 + clusters.add(connectPointSet);
146 + }
147 + });
148 + return clusters;
149 + }
150 +
151 + /**
152 + * Topology event listener.
153 + */
154 + private class InternalTopologyListener implements TopologyListener {
155 + @Override
156 + public void event(TopologyEvent event) {
157 + if (!isRelevant(event)) {
158 + return;
159 + }
160 +
161 + Topology topology = event.subject();
162 + providerService.topologyChanged(getConnectPoints(topology));
163 + }
164 +
165 + @Override
166 + public boolean isRelevant(TopologyEvent event) {
167 + final boolean[] relevant = {false};
168 + if (event.type().equals(TopologyEvent.Type.TOPOLOGY_CHANGED)) {
169 + event.reasons().forEach(event1 -> {
170 + // Only LinkEvents are relevant events, ie: DeviceEvents and others are ignored.
171 + if (event1 instanceof LinkEvent) {
172 + relevant[0] = true;
173 + return;
174 + }
175 + });
176 + }
177 + return relevant[0];
178 + }
179 + }
180 +}
...@@ -220,6 +220,11 @@ public class PtToPtIntentVirtualNetworkProviderTest { ...@@ -220,6 +220,11 @@ public class PtToPtIntentVirtualNetworkProviderTest {
220 } 220 }
221 221
222 @Override 222 @Override
223 + public void topologyChanged(Set<Set<ConnectPoint>> clusters) {
224 +
225 + }
226 +
227 + @Override
223 public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) { 228 public void tunnelUp(NetworkId networkId, ConnectPoint src, ConnectPoint dst, TunnelId tunnelId) {
224 // Release one permit on the created semaphore since the tunnelUp method was called. 229 // Release one permit on the created semaphore since the tunnelUp method was called.
225 created.release(); 230 created.release();
......
...@@ -31,6 +31,7 @@ import org.onosproject.incubator.net.virtual.VirtualLink; ...@@ -31,6 +31,7 @@ import org.onosproject.incubator.net.virtual.VirtualLink;
31 import org.onosproject.incubator.net.virtual.VirtualNetwork; 31 import org.onosproject.incubator.net.virtual.VirtualNetwork;
32 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore; 32 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
33 import org.onosproject.net.ConnectPoint; 33 import org.onosproject.net.ConnectPoint;
34 +import org.onosproject.net.DefaultPort;
34 import org.onosproject.net.Link; 35 import org.onosproject.net.Link;
35 import org.onosproject.net.NetTestTools; 36 import org.onosproject.net.NetTestTools;
36 import org.onosproject.net.PortNumber; 37 import org.onosproject.net.PortNumber;
...@@ -97,7 +98,13 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { ...@@ -97,7 +98,13 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams {
97 VirtualDevice dstVirtualDevice = 98 VirtualDevice dstVirtualDevice =
98 manager.createVirtualDevice(virtualNetwork.id(), DID2); 99 manager.createVirtualDevice(virtualNetwork.id(), DID2);
99 ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1)); 100 ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
101 + manager.createVirtualPort(virtualNetwork.id(), src.deviceId(), src.port(),
102 + new DefaultPort(srcVirtualDevice, src.port(), true));
103 +
100 ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2)); 104 ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
105 + manager.createVirtualPort(virtualNetwork.id(), dst.deviceId(), dst.port(),
106 + new DefaultPort(dstVirtualDevice, dst.port(), true));
107 +
101 VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), src, dst); 108 VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), src, dst);
102 VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), dst, src); 109 VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), dst, src);
103 110
...@@ -107,12 +114,12 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams { ...@@ -107,12 +114,12 @@ public class VirtualNetworkLinkServiceTest extends TestDeviceParams {
107 Iterator<Link> it = linkService.getLinks().iterator(); 114 Iterator<Link> it = linkService.getLinks().iterator();
108 assertEquals("The link set size did not match.", 2, Iterators.size(it)); 115 assertEquals("The link set size did not match.", 2, Iterators.size(it));
109 116
110 - // test the getActiveLinks() method where all links are ACTIVE 117 + // test the getActiveLinks() method where all links are INACTIVE
111 Iterator<Link> it2 = linkService.getActiveLinks().iterator(); 118 Iterator<Link> it2 = linkService.getActiveLinks().iterator();
112 - assertEquals("The link set size did not match.", 2, Iterators.size(it2)); 119 + assertEquals("The link set size did not match.", 0, Iterators.size(it2));
113 120
114 // test the getActiveLinks() method where one link is ACTIVE 121 // test the getActiveLinks() method where one link is ACTIVE
115 - virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.INACTIVE); 122 + virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE);
116 Iterator<Link> it3 = linkService.getActiveLinks().iterator(); 123 Iterator<Link> it3 = linkService.getActiveLinks().iterator();
117 assertEquals("The link set size did not match.", 1, Iterators.size(it3)); 124 assertEquals("The link set size did not match.", 1, Iterators.size(it3));
118 125
......
...@@ -31,6 +31,7 @@ import org.onosproject.incubator.net.virtual.VirtualLink; ...@@ -31,6 +31,7 @@ import org.onosproject.incubator.net.virtual.VirtualLink;
31 import org.onosproject.incubator.net.virtual.VirtualNetwork; 31 import org.onosproject.incubator.net.virtual.VirtualNetwork;
32 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore; 32 import org.onosproject.incubator.store.virtual.impl.DistributedVirtualNetworkStore;
33 import org.onosproject.net.ConnectPoint; 33 import org.onosproject.net.ConnectPoint;
34 +import org.onosproject.net.DefaultPort;
34 import org.onosproject.net.DeviceId; 35 import org.onosproject.net.DeviceId;
35 import org.onosproject.net.DisjointPath; 36 import org.onosproject.net.DisjointPath;
36 import org.onosproject.net.Link; 37 import org.onosproject.net.Link;
...@@ -108,11 +109,29 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams { ...@@ -108,11 +109,29 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams {
108 manager.createVirtualDevice(virtualNetwork.id(), DID4); 109 manager.createVirtualDevice(virtualNetwork.id(), DID4);
109 110
110 ConnectPoint cp1 = new ConnectPoint(virtualDevice1.id(), PortNumber.portNumber(1)); 111 ConnectPoint cp1 = new ConnectPoint(virtualDevice1.id(), PortNumber.portNumber(1));
112 + manager.createVirtualPort(virtualNetwork.id(), cp1.deviceId(), cp1.port(),
113 + new DefaultPort(virtualDevice1, cp1.port(), true));
114 +
111 ConnectPoint cp2 = new ConnectPoint(virtualDevice1.id(), PortNumber.portNumber(2)); 115 ConnectPoint cp2 = new ConnectPoint(virtualDevice1.id(), PortNumber.portNumber(2));
116 + manager.createVirtualPort(virtualNetwork.id(), cp2.deviceId(), cp2.port(),
117 + new DefaultPort(virtualDevice1, cp2.port(), true));
118 +
112 ConnectPoint cp3 = new ConnectPoint(virtualDevice2.id(), PortNumber.portNumber(3)); 119 ConnectPoint cp3 = new ConnectPoint(virtualDevice2.id(), PortNumber.portNumber(3));
120 + manager.createVirtualPort(virtualNetwork.id(), cp3.deviceId(), cp3.port(),
121 + new DefaultPort(virtualDevice2, cp3.port(), true));
122 +
113 ConnectPoint cp4 = new ConnectPoint(virtualDevice2.id(), PortNumber.portNumber(4)); 123 ConnectPoint cp4 = new ConnectPoint(virtualDevice2.id(), PortNumber.portNumber(4));
124 + manager.createVirtualPort(virtualNetwork.id(), cp4.deviceId(), cp4.port(),
125 + new DefaultPort(virtualDevice2, cp4.port(), true));
126 +
114 ConnectPoint cp5 = new ConnectPoint(virtualDevice3.id(), PortNumber.portNumber(5)); 127 ConnectPoint cp5 = new ConnectPoint(virtualDevice3.id(), PortNumber.portNumber(5));
128 + manager.createVirtualPort(virtualNetwork.id(), cp5.deviceId(), cp5.port(),
129 + new DefaultPort(virtualDevice3, cp5.port(), true));
130 +
115 ConnectPoint cp6 = new ConnectPoint(virtualDevice3.id(), PortNumber.portNumber(6)); 131 ConnectPoint cp6 = new ConnectPoint(virtualDevice3.id(), PortNumber.portNumber(6));
132 + manager.createVirtualPort(virtualNetwork.id(), cp6.deviceId(), cp6.port(),
133 + new DefaultPort(virtualDevice3, cp6.port(), true));
134 +
116 VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), cp1, cp3); 135 VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), cp1, cp3);
117 virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE); 136 virtualNetworkManagerStore.updateLink(link1, link1.tunnelId(), Link.State.ACTIVE);
118 VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), cp3, cp1); 137 VirtualLink link2 = manager.createVirtualLink(virtualNetwork.id(), cp3, cp1);
...@@ -177,7 +196,12 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams { ...@@ -177,7 +196,12 @@ public class VirtualNetworkTopologyServiceTest extends TestDeviceParams {
177 196
178 topology = topologyService.currentTopology(); 197 topology = topologyService.currentTopology();
179 ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1)); 198 ConnectPoint src = new ConnectPoint(srcVirtualDevice.id(), PortNumber.portNumber(1));
199 + manager.createVirtualPort(virtualNetwork.id(), src.deviceId(), src.port(),
200 + new DefaultPort(srcVirtualDevice, src.port(), true));
201 +
180 ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2)); 202 ConnectPoint dst = new ConnectPoint(dstVirtualDevice.id(), PortNumber.portNumber(2));
203 + manager.createVirtualPort(virtualNetwork.id(), dst.deviceId(), dst.port(),
204 + new DefaultPort(dstVirtualDevice, dst.port(), true));
181 VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), src, dst); 205 VirtualLink link1 = manager.createVirtualLink(virtualNetwork.id(), src, dst);
182 206
183 // test the isLatest() method where a new link has been added to the current topology. 207 // test the isLatest() method where a new link has been added to the current topology.
......