ONOS-3404 Change p2p tunnel to p2any tunnel by using set tunnel_dst in
flow.
Change-Id: I06cb6d42772434de9c016e795de5c6d8a6f45dfb
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
index 7192ad9..2e38251 100644
--- a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
@@ -15,12 +15,14 @@
*/
package org.onosproject.vtn.manager.impl;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -30,6 +32,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.util.KryoNamespace;
@@ -43,6 +46,7 @@
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.BridgeDescription;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.BasicDeviceConfig;
import org.onosproject.net.device.DeviceEvent;
@@ -50,15 +54,24 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment.Builder;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.LogicalClockService;
-import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.onosproject.vtn.manager.VTNService;
import org.onosproject.vtn.table.ClassifierService;
@@ -79,6 +92,7 @@
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
import org.slf4j.Logger;
+import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
/**
@@ -120,6 +134,9 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected GroupService groupService;
+
private ApplicationId appId;
private ClassifierService classifierService;
private L2ForwardService l2ForwardService;
@@ -133,9 +150,10 @@
private static final String EX_PORT_NAME = "eth0";
private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
+ private static final String DEFAULT_IP = "0.0.0.0";
private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
- private ConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
+ private EventuallyConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
@Activate
public void activate() {
@@ -162,9 +180,9 @@
.build();
switchOfLocalHostPorts = storageService
- .<DeviceId, NetworkOfLocalHostPorts>consistentMapBuilder()
- .withName(SWITCH_OF_LOCAL_HOST_PORTS)
- .withSerializer(Serializer.using(serializer.build()))
+ .<DeviceId, NetworkOfLocalHostPorts>eventuallyConsistentMapBuilder()
+ .withName(SWITCH_OF_LOCAL_HOST_PORTS).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
.build();
log.info("Started");
@@ -251,44 +269,10 @@
private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
DriverHandler localHandler) {
- Iterable<Device> devices = deviceService.getAvailableDevices();
- Sets.newHashSet(devices).stream()
- .filter(d -> Device.Type.CONTROLLER == d.type())
- .filter(d -> !localDeviceId.equals(d.id())).forEach(d -> {
- DriverHandler tunHandler = driverService
- .createHandler(d.id());
- String remoteIpAddress = d.annotations()
- .value(CONTROLLER_IP_KEY);
- IpAddress remoteIp = IpAddress.valueOf(remoteIpAddress);
- if (remoteIp.toString()
- .equalsIgnoreCase(localIp.toString())) {
- log.error("The localIp and remoteIp are the same");
- return;
- }
- if (localHandler != null) {
- // Create tunnel in br-int on local controller
- if (mastershipService.isLocalMaster(localDeviceId)) {
- VtnConfig.applyTunnelConfig(localHandler, localIp, remoteIp);
- log.info("Add tunnel between {} and {}", localIp,
- remoteIp);
- }
- // Create tunnel in br-int on other controllers
- if (mastershipService.isLocalMaster(d.id())) {
- VtnConfig.applyTunnelConfig(tunHandler, remoteIp,
- localIp);
- log.info("Add tunnel between {} and {}", remoteIp,
- localIp);
- }
- } else {
- // remove tunnel in br-int on other controllers
- if (mastershipService.isLocalMaster(d.id())) {
- VtnConfig.removeTunnelConfig(tunHandler, remoteIp,
- localIp);
- log.info("Remove tunnel between {} and {}", remoteIp,
- localIp);
- }
- }
- });
+ if (mastershipService.isLocalMaster(localDeviceId)) {
+ VtnConfig.applyTunnelConfig(localHandler, localIp, IpAddress.valueOf(DEFAULT_IP));
+ log.info("Add tunnel on {}", localIp);
+ }
}
private void applyTunnelOut(Device device, Objective.Operation type) {
@@ -321,6 +305,7 @@
DriverHandler handler = driverService.createHandler(localControllerId);
Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
Iterable<Host> allHosts = hostService.getHosts();
+ String tunnelName = "vxlan-" + DEFAULT_IP;
if (allHosts != null) {
Sets.newHashSet(allHosts).stream().forEach(host -> {
MacAddress hostMac = host.mac();
@@ -346,13 +331,12 @@
}
IpAddress remoteIpAddress = IpAddress
.valueOf(remoteControllerIp);
- String tunnelName = "vxlan-" + remoteIpAddress.toString();
ports.stream()
.filter(p -> p.name().equalsIgnoreCase(tunnelName))
.forEach(p -> {
l2ForwardService
.programTunnelOut(device.id(), segmentationId, p,
- hostMac, type);
+ hostMac, type, remoteIpAddress);
});
});
}
@@ -392,16 +376,11 @@
Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
// Get all the local vm's PortNumber in the current node
Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
- .get(deviceId).value().getNetworkOfLocalHostPorts();
+ .get(deviceId).getNetworkOfLocalHostPorts();
Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
-
- l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
- inPort, networkOflocalHostPorts,
- localTunnelPorts,
- type);
-
- l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
- type);
+ for (PortNumber p : localTunnelPorts) {
+ programGroupTable(deviceId, appId, p, devices, type);
+ }
if (type == Objective.Operation.ADD) {
if (networkOflocalHostPorts == null) {
@@ -409,20 +388,33 @@
localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
}
networkOflocalHostPorts.add(inPort);
+ l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
+ inPort, networkOflocalHostPorts,
+ localTunnelPorts,
+ type);
classifierService.programTunnelIn(deviceId, segmentationId,
localTunnelPorts,
type);
} else if (type == Objective.Operation.REMOVE) {
- networkOflocalHostPorts.remove(inPort);
- if (networkOflocalHostPorts.isEmpty()) {
- classifierService.programTunnelIn(deviceId, segmentationId,
- localTunnelPorts,
- Objective.Operation.REMOVE);
- switchOfLocalHostPorts.get(deviceId).value().getNetworkOfLocalHostPorts()
- .remove(virtualPort.networkId());
+ if (networkOflocalHostPorts != null) {
+ l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
+ inPort, networkOflocalHostPorts,
+ localTunnelPorts,
+ type);
+ networkOflocalHostPorts.remove(inPort);
+ if (networkOflocalHostPorts.isEmpty()) {
+ classifierService.programTunnelIn(deviceId, segmentationId,
+ localTunnelPorts,
+ type);
+ switchOfLocalHostPorts.get(deviceId).getNetworkOfLocalHostPorts()
+ .remove(virtualPort.networkId());
+ }
}
}
+ l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
+ type);
+
l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
networkOflocalHostPorts,
localTunnelPorts,
@@ -440,9 +432,11 @@
SegmentationId segmentationId,
MacAddress dstMac,
Objective.Operation type) {
- String tunnelName = "vxlan-" + ipAddress.toString();
+ String tunnelName = "vxlan-" + DEFAULT_IP;
Sets.newHashSet(devices).stream()
- .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
+ .filter(d -> d.type() == Device.Type.CONTROLLER)
+ .filter(d -> !("ovsdb:" + ipAddress).equals(d.id().toString()))
+ .forEach(d -> {
DriverHandler handler = driverService.createHandler(d.id());
BridgeConfig bridgeConfig = handler
.behaviour(BridgeConfig.class);
@@ -459,7 +453,7 @@
.forEach(p -> {
l2ForwardService.programTunnelOut(sw.deviceId(),
segmentationId, p,
- dstMac, type);
+ dstMac, type, ipAddress);
});
}
});
@@ -525,4 +519,45 @@
}
}
+ private void programGroupTable(DeviceId deviceId, ApplicationId appid,
+ PortNumber portNumber, Iterable<Device> devices, Objective.Operation type) {
+ if (type.equals(Objective.Operation.REMOVE)) {
+ return;
+ }
+
+ List<GroupBucket> buckets = Lists.newArrayList();
+ Sets.newHashSet(devices)
+ .stream()
+ .filter(d -> d.type() == Device.Type.CONTROLLER)
+ .filter(d -> !deviceId.equals(d.id()))
+ .forEach(d -> {
+ String ipAddress = d.annotations()
+ .value(CONTROLLER_IP_KEY);
+ Ip4Address dst = Ip4Address.valueOf(ipAddress);
+ Builder builder = DefaultTrafficTreatment.builder();
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ try {
+ treatment.setPropertyValue("tunnelDst", dst);
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
+ }
+
+ builder.extension(treatment, deviceId);
+ builder.setOutput(portNumber);
+ GroupBucket bucket = DefaultGroupBucket
+ .createAllGroupBucket(builder.build());
+ buckets.add(bucket);
+ });
+ final GroupKey key = new DefaultGroupKey(APP_ID.getBytes());
+ GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.ALL,
+ new GroupBuckets(buckets),
+ key,
+ L2ForwardServiceImpl.GROUP_ID,
+ appid);
+ groupService.addGroup(groupDescription);
+ }
}