ONOS-2709
Fix bug of installing flowrules.
Change-Id: I84fc3e3c4894b3f84173a5364e4506d4fc6ba3fc
diff --git a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
index 32bcc29..6fc63e1 100644
--- a/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
+++ b/apps/vtn/src/main/java/org/onosproject/vtn/impl/VTNManager.java
@@ -19,7 +19,10 @@
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ScheduledExecutorService;
@@ -42,6 +45,7 @@
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeDescription;
import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.DefaultTunnelDescription;
import org.onosproject.net.behaviour.IpTunnelEndPoint;
@@ -119,6 +123,11 @@
private static final String PORT_HEAD = "vxlan";
private static final String DEFAULT_BRIDGE_NAME = "br-int";
private static final String CONTROLLER_IP_KEY = "ipaddress";
+ private static final int DEFAULT_MAC_PRIORITY = 0x0000;
+ private static final int MAC_PRIORITY = 0xffff;
+ private static final int DEFAULT_PORT_PRIORITY = 0x0000;
+ private static final int PORT_PRIORITY = 0xffff;
+ private static final String SWITCH_CHANNEL_ID = "channelId";
@Activate
public void activate() {
@@ -152,19 +161,20 @@
bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME));
String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
IpAddress ip = IpAddress.valueOf(ipAddress);
- Sets.newHashSet(devices)
- .stream()
- .filter(d -> d.type() == Device.Type.CONTROLLER)
- .filter(d -> !device.id().equals(d.id()))
- .forEach(d -> {
- String ipAddress1 = d.annotations()
- .value(CONTROLLER_IP_KEY);
- IpAddress ip1 = IpAddress.valueOf(ipAddress1);
- applyTunnelConfig(ip, ip1, handler);
- DriverHandler handler1 = driverService
- .createHandler(d.id());
- applyTunnelConfig(ip1, ip, handler1);
- });
+ Sets.newHashSet(devices).stream()
+ .filter(d -> Device.Type.CONTROLLER == d.type())
+ .filter(d -> !device.id().equals(d.id())).forEach(d -> {
+ if (!device.id().equals(d.id())
+ && Device.Type.CONTROLLER == d.type()) {
+ String ipAddress1 = d.annotations()
+ .value(CONTROLLER_IP_KEY);
+ IpAddress ip1 = IpAddress.valueOf(ipAddress1);
+ applyTunnelConfig(ip, ip1, handler);
+ DriverHandler handler1 = driverService
+ .createHandler(d.id());
+ applyTunnelConfig(ip1, ip, handler1);
+ }
+ });
}
@Override
@@ -172,18 +182,15 @@
Iterable<Device> devices = deviceService.getAvailableDevices();
String ipAddress = device.annotations().value(CONTROLLER_IP_KEY);
IpAddress dst = IpAddress.valueOf(ipAddress);
- Sets.newHashSet(devices)
- .stream()
+ Sets.newHashSet(devices).stream()
.filter(d -> d.type() == Device.Type.CONTROLLER)
- .filter(d -> !device.id().equals(d.id()))
- .forEach(d -> {
- String ipAddress1 = d.annotations()
- .value(CONTROLLER_IP_KEY);
- DriverHandler handler = driverService
- .createHandler(d.id());
- IpAddress src = IpAddress.valueOf(ipAddress1);
- removeTunnelConfig(src, dst, handler);
- });
+ .filter(d -> !device.id().equals(d.id())).forEach(d -> {
+ String ipAddress1 = d.annotations()
+ .value(CONTROLLER_IP_KEY);
+ DriverHandler handler = driverService.createHandler(d.id());
+ IpAddress src = IpAddress.valueOf(ipAddress1);
+ removeTunnelConfig(src, dst, handler);
+ });
}
private void applyTunnelConfig(IpAddress src, IpAddress dst,
@@ -216,6 +223,32 @@
public void onOvsDetected(Device device) {
programMacDefaultRules(device.id(), appId, Objective.Operation.ADD);
programPortDefaultRules(device.id(), appId, Objective.Operation.ADD);
+ Set<Host> hosts = hostService.getConnectedHosts(device.id());
+ hosts.forEach(h -> {
+ String ifaceId = h.annotations().value(IFACEID);
+ String currentControllerIp = getControllerIpOfSwitch(device.id());
+ VirtualPortId portId = VirtualPortId.portId(ifaceId);
+ VirtualPort port = virtualPortService.getPort(portId);
+ TenantNetwork network = tenantNetworkService
+ .getNetwork(port.networkId());
+ String vxlanName = "vxlan-" + currentControllerIp;
+
+ DriverHandler handler = driverService.createHandler(device.id());
+ BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+ Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
+ .getBridges();
+ Iterator<BridgeDescription> it = bridgeDescriptions.iterator();
+ if (it.hasNext()) {
+ BridgeDescription sw = it.next();
+ Set<PortNumber> ports = bridgeConfig.getPortNumbers();
+ ports.stream().filter(p -> p.name().equalsIgnoreCase(vxlanName))
+ .forEach(p -> {
+ programTunnelOut(sw.deviceId(), network.segmentationId(), p,
+ h.mac(), appId, Objective.Operation.ADD);
+ });
+ }
+
+ });
}
@Override
@@ -227,58 +260,137 @@
@Override
public void onHostDetected(Host host) {
String ifaceId = host.annotations().value(IFACEID);
+ DeviceId deviceId = host.location().deviceId();
+ String currentControllerIp = getControllerIpOfSwitch(deviceId);
+ Iterable<Device> devices = deviceService.getAvailableDevices();
VirtualPortId portId = VirtualPortId.portId(ifaceId);
VirtualPort port = virtualPortService.getPort(portId);
- TenantNetwork network = tenantNetworkService.getNetwork(port
- .networkId());
+ TenantNetwork network = tenantNetworkService
+ .getNetwork(port.networkId());
+ String tunnelName = "vxlan-" + currentControllerIp;
binding.put(host.id(), network.segmentationId());
- DeviceId deviceId = host.location().deviceId();
List<Port> allPorts = deviceService.getPorts(deviceId);
PortNumber inPort = host.location().port();
Set<Port> localPorts = new HashSet<>();
- allPorts.forEach(p -> {
- if (!p.number().name().startsWith(PORT_HEAD)) {
+ Set<Port> tunnelPorts = new HashSet<>();
+ List<Port> outports = new ArrayList<>();
+ Sets.newHashSet(allPorts.iterator()).stream()
+ .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
+ if (!p.annotations().value("portName").startsWith(PORT_HEAD)) {
localPorts.add(p);
+ } else {
+ tunnelPorts.add(p);
}
+ outports.add(p);
});
+
programLocalBcastRules(deviceId, network.segmentationId(), inPort,
- allPorts, appId, Objective.Operation.ADD);
+ outports, appId, Objective.Operation.ADD);
programLocalOut(deviceId, network.segmentationId(), inPort, host.mac(),
appId, Objective.Operation.ADD);
- programTunnelFloodOut(deviceId, network.segmentationId(), inPort,
- localPorts, appId, Objective.Operation.ADD);
- programTunnelOut(deviceId, network.segmentationId(), inPort,
- host.mac(), appId, Objective.Operation.ADD);
+ tunnelPorts
+ .forEach(tp -> programTunnelFloodOut(deviceId,
+ network.segmentationId(),
+ tp.number(), localPorts,
+ appId,
+ Objective.Operation.ADD));
+ Sets.newHashSet(devices).stream()
+ .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
+ DriverHandler handler = driverService.createHandler(d.id());
+ BridgeConfig bridgeConfig = handler
+ .behaviour(BridgeConfig.class);
+ Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
+ .getBridges();
+
+ Iterator<BridgeDescription> it = bridgeDescriptions
+ .iterator();
+ if (it.hasNext()) {
+ BridgeDescription sw = it.next();
+ Set<PortNumber> ports = bridgeConfig.getPortNumbers();
+ ports.stream()
+ .filter(p -> p.name()
+ .equalsIgnoreCase(tunnelName))
+ .forEach(p -> {
+ programTunnelOut(sw.deviceId(),
+ network.segmentationId(), p,
+ host.mac(), appId,
+ Objective.Operation.ADD);
+ });
+ }
+ });
programLocalIn(deviceId, network.segmentationId(), inPort, host.mac(),
appId, Objective.Operation.ADD);
- programTunnelIn(deviceId, network.segmentationId(), inPort, host.mac(),
- appId, Objective.Operation.ADD);
+ tunnelPorts
+ .forEach(tp -> programTunnelIn(deviceId,
+ network.segmentationId(),
+ tp.number(), inPort, host.mac(),
+ appId, Objective.Operation.ADD));
+
}
@Override
public void onHostVanished(Host host) {
SegmentationId segId = binding.remove(host.id());
DeviceId deviceId = host.location().deviceId();
+ String currentControllerIp = getControllerIpOfSwitch(deviceId);
+ Iterable<Device> devices = deviceService.getAvailableDevices();
List<Port> allPorts = deviceService.getPorts(deviceId);
PortNumber inPort = host.location().port();
+ String vxlanName = "vxlan-" + currentControllerIp;
Set<Port> localPorts = new HashSet<>();
- allPorts.forEach(p -> {
- if (!p.number().name().startsWith(PORT_HEAD)) {
+ Set<Port> tunnelPorts = new HashSet<>();
+ List<Port> outports = new ArrayList<>();
+ Sets.newHashSet(allPorts.iterator()).stream()
+ .filter(p -> !p.number().equals(PortNumber.LOCAL)).forEach(p -> {
+ if (!p.annotations().value("portName").startsWith(PORT_HEAD)) {
localPorts.add(p);
+ } else {
+ tunnelPorts.add(p);
}
+ outports.add(p);
});
- programLocalBcastRules(deviceId, segId, inPort, allPorts, appId,
- Objective.Operation.REMOVE);
- programLocalOut(deviceId, segId, inPort, host.mac(), appId,
- Objective.Operation.REMOVE);
- programTunnelFloodOut(deviceId, segId, inPort, localPorts, appId,
- Objective.Operation.REMOVE);
- programTunnelOut(deviceId, segId, inPort, host.mac(), appId,
- Objective.Operation.REMOVE);
- programLocalIn(deviceId, segId, inPort, host.mac(), appId,
- Objective.Operation.REMOVE);
- programTunnelIn(deviceId, segId, inPort, host.mac(), appId,
- Objective.Operation.REMOVE);
+
+ programLocalBcastRules(deviceId, segId, inPort,
+ outports, appId, Objective.Operation.REMOVE);
+ programLocalOut(deviceId, segId, inPort, host.mac(),
+ appId, Objective.Operation.REMOVE);
+ tunnelPorts
+ .forEach(tp -> programTunnelFloodOut(deviceId,
+ segId,
+ tp.number(), localPorts,
+ appId,
+ Objective.Operation.REMOVE));
+ Sets.newHashSet(devices).stream()
+ .filter(d -> d.type() == Device.Type.CONTROLLER).forEach(d -> {
+ DriverHandler handler = driverService.createHandler(d.id());
+ BridgeConfig bridgeConfig = handler
+ .behaviour(BridgeConfig.class);
+ Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
+ .getBridges();
+
+ Iterator<BridgeDescription> it = bridgeDescriptions
+ .iterator();
+ if (it.hasNext()) {
+ BridgeDescription sw = it.next();
+ Set<PortNumber> ports = bridgeConfig.getPortNumbers();
+ ports.stream()
+ .filter(p -> p.name()
+ .equalsIgnoreCase(vxlanName))
+ .forEach(p -> {
+ programTunnelOut(sw.deviceId(),
+ segId, p,
+ host.mac(), appId,
+ Objective.Operation.REMOVE);
+ });
+ }
+ });
+ programLocalIn(deviceId, segId, inPort, host.mac(),
+ appId, Objective.Operation.REMOVE);
+ tunnelPorts
+ .forEach(tp -> programTunnelIn(deviceId,
+ segId,
+ tp.number(), inPort, host.mac(),
+ appId, Objective.Operation.REMOVE));
}
private class InnerDeviceListener implements DeviceListener {
@@ -309,7 +421,7 @@
onOvsVanished(device);
});
} else {
- log.info("do nothing for this device type");
+ log.info("Do nothing for this device type");
}
}
@@ -328,8 +440,11 @@
backgroundService.execute(() -> {
onHostVanished(host);
});
- } else {
- log.info("unknow host");
+ } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
+ backgroundService.execute(() -> {
+ onHostVanished(host);
+ onHostDetected(host);
+ });
}
}
@@ -338,16 +453,18 @@
// Used to forward the flows to the local VM.
private void programLocalOut(DeviceId dpid, SegmentationId segmentationId,
PortNumber outPort, MacAddress sourceMac,
- ApplicationId appid, Objective.Operation type) {
+ ApplicationId appid,
+ Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthDst(sourceMac).build();
- TrafficTreatment treatment = DefaultTrafficTreatment
- .builder()
- .add(Instructions.modTunnelId(Long.parseLong(segmentationId
- .toString()))).setOutput(outPort).build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .add(Instructions
+ .modTunnelId(Long.parseLong(segmentationId.toString())))
+ .setOutput(outPort).build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
- .fromApp(appId).withFlag(Flag.SPECIFIC);
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(MAC_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
@@ -356,24 +473,28 @@
}
- // Used to forward the flows to the remote VM via VXLAN tunnel.
+ // Used to forward the flows into the VXLAN tunnel.
private void programTunnelOut(DeviceId dpid, SegmentationId segmentationId,
- PortNumber outPort, MacAddress sourceMac,
- ApplicationId appid, Objective.Operation type) {
+ PortNumber tunnelOutPort, MacAddress dstMac,
+ ApplicationId appid,
+ Objective.Operation type) {
TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthDst(sourceMac).build();
- TrafficTreatment treatment = DefaultTrafficTreatment
- .builder()
- .add(Instructions.modTunnelId(Long.parseLong(segmentationId
- .toString()))).setOutput(outPort).build();
+ .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+
+ .setOutput(tunnelOutPort).build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
- .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(MAC_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
flowObjectiveService.forward(dpid, objective.remove());
}
+
}
// Used to forward multicast flows to remote VMs of the same tenant via
@@ -384,8 +505,7 @@
Iterable<Port> localports,
ApplicationId appid,
Objective.Operation type) {
- TrafficSelector selector = DefaultTrafficSelector
- .builder()
+ TrafficSelector selector = DefaultTrafficSelector.builder()
.matchInPort(ofPortOut)
.add(Criteria.matchTunnelId(Long.parseLong(segmentationId
@@ -399,7 +519,7 @@
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment.build())
.withSelector(selector).fromApp(appId).makePermanent()
- .withFlag(Flag.SPECIFIC);
+ .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
@@ -415,7 +535,8 @@
.build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
- .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+ .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
+ .withPriority(DEFAULT_MAC_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
@@ -429,12 +550,11 @@
PortNumber inPort, List<Port> allports,
ApplicationId appid,
Objective.Operation type) {
- TrafficSelector selector = DefaultTrafficSelector
- .builder()
- .matchInPort(inPort)
- .matchEthDst(MacAddress.BROADCAST)
- .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
- .toString()))).build();
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(inPort).matchEthDst(MacAddress.BROADCAST)
+ .add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
for (Port outport : allports) {
@@ -445,7 +565,7 @@
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment.build())
.withSelector(selector).fromApp(appId).makePermanent()
- .withFlag(Flag.SPECIFIC);
+ .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
@@ -465,7 +585,7 @@
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment.build())
.withSelector(selector).fromApp(appId).makePermanent()
- .withFlag(Flag.SPECIFIC);
+ .withFlag(Flag.SPECIFIC).withPriority(PORT_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
@@ -475,18 +595,19 @@
// Used to forward the flows from the egress tunnel to the VM.
private void programTunnelIn(DeviceId dpid, SegmentationId segmentationId,
- PortNumber inPort, MacAddress sourceMac,
- ApplicationId appid, Objective.Operation type) {
- TrafficSelector selector = DefaultTrafficSelector
- .builder()
- .matchInPort(inPort)
- .add(Criteria.matchTunnelId(Long.parseLong(segmentationId
- .toString()))).build();
+ PortNumber tunnelInPort, PortNumber outPort,
+ MacAddress sourceMac, ApplicationId appid,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(tunnelInPort).add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
- .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+ .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
+ .withPriority(PORT_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
@@ -501,11 +622,20 @@
TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
ForwardingObjective.Builder objective = DefaultForwardingObjective
.builder().withTreatment(treatment).withSelector(selector)
- .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC);
+ .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
+ .withPriority(DEFAULT_PORT_PRIORITY);
if (type.equals(Objective.Operation.ADD)) {
flowObjectiveService.forward(dpid, objective.add());
} else {
flowObjectiveService.forward(dpid, objective.remove());
}
}
+
+ // Used to get channelId from the device annotations.
+ private String getControllerIpOfSwitch(DeviceId deviceId) {
+ Device device = deviceService.getDevice(deviceId);
+ String url = device.annotations().value(SWITCH_CHANNEL_ID);
+ return url.substring(0, url.lastIndexOf(":"));
+ }
+
}