Directly refer to patch port of tenant bridge from device events
Do not remove tenant bridge in case other tenant networks use it
Change-Id: I5a37a8acbb8616ab6d66bb9ea4e574df2acee785
(cherry picked from commit fb3bdbcb649d2765180f5795718daf2616986045)
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubernetesExternalLbArpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubernetesExternalLbArpHandler.java
index 5af9834..f310dcb 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubernetesExternalLbArpHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubernetesExternalLbArpHandler.java
@@ -341,7 +341,7 @@
private void retrievePeerMac(IpAddress srcIp, MacAddress srcMac,
IpAddress peerIp, KubevirtNode gatewayNode,
PortNumber portNumber) {
- log.trace("Sending ARP request to the peer {} to retrieve the MAC address.",
+ log.debug("Sending ARP request to the peer {} to retrieve the MAC address.",
peerIp.getIp4Address().toString());
Ethernet ethRequest = ARP.buildArpRequest(srcMac.toBytes(),
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
index b82aa3c..f1d88c4 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
@@ -16,6 +16,7 @@
package org.onosproject.kubevirtnetworking.impl;
import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
import org.onlab.packet.ARP;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
@@ -65,6 +66,8 @@
import org.onosproject.net.behaviour.InterfaceConfig;
import org.onosproject.net.behaviour.PatchDescription;
import org.onosproject.net.device.DeviceAdminService;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -77,6 +80,7 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
+import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -117,6 +121,7 @@
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterForKubevirtPort;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.getRouterMacAddress;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.kubernetesElbMac;
+import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.numOfDupSegNetworks;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.portNumber;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.resolveHostname;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.segmentIdHex;
@@ -195,6 +200,8 @@
private final InternalRouterEventListener kubevirtRouterlistener =
new InternalRouterEventListener();
+ private final DeviceListener bridgeListener = new InternalBridgeListener();
+
private final ExecutorService eventExecutor = newSingleThreadExecutor(
groupedThreads(this.getClass().getSimpleName(), "event-handler"));
@@ -209,6 +216,7 @@
networkService.addListener(networkListener);
nodeService.addListener(nodeListener);
+ deviceService.addListener(bridgeListener);
kubevirtPortService.addListener(portListener);
kubevirtRouterService.addListener(kubevirtRouterlistener);
@@ -219,6 +227,7 @@
protected void deactivate() {
networkService.removeListener(networkListener);
nodeService.removeListener(nodeListener);
+ deviceService.removeListener(bridgeListener);
kubevirtPortService.removeListener(portListener);
kubevirtRouterService.removeListener(kubevirtRouterlistener);
leadershipService.withdraw(appId.name());
@@ -231,7 +240,7 @@
Device tenantBridge = deviceService.getDevice(network.tenantDeviceId(node.hostname()));
if (tenantBridge != null && deviceService.isAvailable(tenantBridge.id())) {
- log.warn("The tenant bridge {} already exists at node {}",
+ log.info("The tenant bridge {} already exists at node {}",
network.tenantBridgeName(), node.hostname());
return;
}
@@ -335,57 +344,9 @@
private void removeAllFlows(KubevirtNode node, KubevirtNetwork network) {
DeviceId deviceId = network.tenantDeviceId(node.hostname());
- removeIngressRules(network);
flowService.purgeRules(deviceId);
}
- private void removeIngressRules(KubevirtNetwork network) {
- if (network == null) {
- return;
- }
-
- if (network.type() == FLAT || network.type() == VLAN) {
- return;
- }
-
- if (network.segmentId() == null) {
- return;
- }
-
- for (KubevirtNode localNode : kubevirtNodeService.completeNodes(WORKER)) {
-
- while (true) {
- KubevirtNode updatedNode = kubevirtNodeService.node(localNode.hostname());
- if (tunnelToTenantPort(deviceService, updatedNode, network) != null) {
- break;
- } else {
- log.info("Waiting for tunnel to tenant patch port creation " +
- "on ingress rule setup on node {}", updatedNode);
- waitFor(3);
- }
- }
-
- PortNumber patchPortNumber = tunnelToTenantPort(deviceService, localNode, network);
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchTunnelId(Long.parseLong(network.segmentId()));
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setOutput(patchPortNumber);
-
- flowService.setRule(
- appId,
- localNode.tunBridge(),
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_TUNNEL_RULE,
- TUNNEL_DEFAULT_TABLE,
- false);
-
- log.debug("Set ingress rules for segment ID {}", network.segmentId());
- }
- }
-
private void removePatchInterface(KubevirtNode node, KubevirtNetwork network) {
Device device = deviceService.getDevice(node.ovsdb());
@@ -469,7 +430,6 @@
setForwardingRule(deviceId, true);
// security group related rules
- setTenantIngressTransitionRule(network, network.tenantDeviceId(node.hostname()), true);
setTenantEgressTransitionRule(network.tenantDeviceId(node.hostname()), true);
log.info("Install default flow rules for tenant bridge {}", network.tenantBridgeName());
@@ -606,25 +566,6 @@
install);
}
- private void setTenantIngressTransitionRule(KubevirtNetwork network,
- DeviceId deviceId, boolean install) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
- .matchInPort(network.tenantToTunnelPort(deviceId));
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
- tBuilder.transition(TENANT_ACL_INGRESS_TABLE);
-
- flowService.setRule(appId,
- deviceId,
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_IP_INGRESS_RULE,
- TENANT_ICMP_TABLE,
- install
- );
- }
-
private void setTenantEgressTransitionRule(DeviceId deviceId, boolean install) {
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort());
@@ -649,7 +590,7 @@
MacAddress routerMacAddress = getRouterMacAddress(router);
if (routerMacAddress == null) {
- log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
+ log.warn("Setting gateway default egress rule to gateway for tenant internal network because " +
"there's no br-int port for device {}", gwDeviceId);
return;
}
@@ -657,7 +598,7 @@
KubevirtNode gwNode = kubevirtNodeService.node(gwDeviceId);
if (gwNode == null) {
- log.warn("Setting gateway default eggress rule to gateway for tenant internal network because " +
+ log.warn("Setting gateway default egress rule to gateway for tenant internal network because " +
"there's no gateway node for device {}", gwDeviceId);
return;
}
@@ -1299,7 +1240,9 @@
return;
}
- nodeService.completeNodes(WORKER).forEach(n -> {
+ nodeService.completeNodes(WORKER).stream()
+ .sorted(Comparator.comparing(KubevirtNode::hostname))
+ .forEach(n -> {
createBridge(n, network);
createPatchTenantInterface(n, network);
setDefaultRulesForTenantNetwork(n, network);
@@ -1311,12 +1254,15 @@
return;
}
- nodeService.completeNodes(WORKER).forEach(n -> {
+ if (numOfDupSegNetworks(networkService, network) > 0) {
+ return;
+ }
+ nodeService.completeNodes(WORKER).stream()
+ .sorted(Comparator.comparing(KubevirtNode::hostname))
+ .forEach(n -> {
removeAllFlows(n, network);
removePatchInterface(n, network);
-
waitFor(5);
-
removeBridge(n, network);
});
}
@@ -1461,6 +1407,63 @@
}
}
+ private class InternalBridgeListener implements DeviceListener {
+
+ @Override
+ public boolean isRelevant(DeviceEvent event) {
+ return event.subject().type() == Device.Type.SWITCH;
+ }
+
+ private boolean isRelevantHelper() {
+ return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+ }
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ Port port = event.port();
+
+ switch (event.type()) {
+ case PORT_ADDED:
+ eventExecutor.execute(() -> {
+ if (!isRelevantHelper()) {
+ return;
+ }
+ installTenantIngressTransitionRule(device, port);
+ });
+ break;
+ case PORT_REMOVED:
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ private void installTenantIngressTransitionRule(Device device, Port port) {
+
+ String portName = port.annotations().value(PORT_NAME);
+ if (!StringUtils.startsWithIgnoreCase(portName, TENANT_TO_TUNNEL_PREFIX)) {
+ return;
+ }
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ sBuilder.matchEthType(EthType.EtherType.IPV4.ethType().toShort())
+ .matchInPort(port.number());
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ tBuilder.transition(TENANT_ACL_INGRESS_TABLE);
+
+ flowService.setRule(appId,
+ device.id(),
+ sBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_IP_INGRESS_RULE,
+ TENANT_ICMP_TABLE,
+ true
+ );
+ }
+ }
+
private class InternalKubevirtPortListener implements KubevirtPortListener {
private boolean isRelevantHelper() {
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
index 9ba10b4..4ff5c97 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
@@ -148,7 +148,7 @@
*/
private void retrievePeerRouterMac(KubevirtRouter router, IpAddress peerRouterIp) {
- log.info("Sending ARP request to the peer router {} to retrieve the MAC address.",
+ log.debug("Sending ARP request to the peer router {} to retrieve the MAC address.",
peerRouterIp.getIp4Address().toString());
String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java
index b51af25..9c71f54 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSecurityGroupHandler.java
@@ -16,6 +16,7 @@
package org.onosproject.kubevirtnetworking.impl;
import com.google.common.collect.Sets;
+import org.apache.commons.lang.StringUtils;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
@@ -51,8 +52,12 @@
import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
import org.onosproject.kubevirtnode.api.KubevirtNodeService;
import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -71,7 +76,9 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;
+import java.util.Comparator;
import java.util.Dictionary;
+import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -97,6 +104,7 @@
import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ACL_INGRESS_TABLE;
import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_ACL_RECIRC_TABLE;
import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_FORWARDING_TABLE;
+import static org.onosproject.kubevirtnetworking.api.Constants.TENANT_TO_TUNNEL_PREFIX;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VLAN;
import static org.onosproject.kubevirtnetworking.impl.OsgiPropertyConstants.USE_SECURITY_GROUP;
@@ -108,6 +116,7 @@
import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.computeCtStateFlag;
import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.niciraConnTrackTreatmentBuilder;
import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -205,6 +214,8 @@
private final KubevirtNetworkListener networkListener =
new InternalNetworkListener();
+ private final DeviceListener bridgeListener = new InternalBridgeListener();
+
private final ExecutorService eventExecutor = newSingleThreadExecutor(
groupedThreads(this.getClass().getSimpleName(), "event-handler"));
@@ -219,6 +230,7 @@
portService.addListener(portListener);
networkService.addListener(networkListener);
configService.registerProperties(getClass());
+ deviceService.addListener(bridgeListener);
nodeService.addListener(nodeListener);
log.info("Started");
@@ -228,6 +240,7 @@
protected void deactivate() {
securityGroupService.removeListener(securityGroupListener);
portService.removeListener(portListener);
+ deviceService.removeListener(bridgeListener);
configService.unregisterProperties(getClass(), false);
nodeService.removeListener(nodeListener);
networkService.removeListener(networkListener);
@@ -295,23 +308,14 @@
initializeAclTable(deviceId, ACL_RECIRC_TABLE, PortNumber.NORMAL, install);
}
- private void initializeTenantAclTable(KubevirtNetwork network,
- DeviceId deviceId, boolean install) {
- // FIXME: in bridge initialization phase, some patch ports may not be
- // available until they are created, we wait for a while ensure all
- // patch ports are created via network bootstrap
- while (true) {
- if (network.tenantToTunnelPort(deviceId) != null) {
- break;
- } else {
- log.info("Wait for tenant patch ports creation for device {} " +
- "and network {}", deviceId, network.networkId());
- waitFor(5);
+ private void initializeTenantAclTable(DeviceId deviceId, boolean install) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ String portName = port.annotations().value(PORT_NAME);
+ if (StringUtils.startsWithIgnoreCase(portName, TENANT_TO_TUNNEL_PREFIX)) {
+ initializeAclTable(deviceId, TENANT_ACL_RECIRC_TABLE, port.number(), install);
+ return;
}
}
-
- PortNumber patchPort = network.tenantToTunnelPort(deviceId);
- initializeAclTable(deviceId, TENANT_ACL_RECIRC_TABLE, patchPort, install);
}
private void initializeAclTable(DeviceId deviceId, int recircTable,
@@ -379,11 +383,11 @@
initializeProviderAclTable(node.intgBridge(), install);
}
- private void initializeTenantPipeline(KubevirtNetwork network,
- KubevirtNode node, boolean install) {
+ private DeviceId initializeTenantPipelineWithoutAcl(KubevirtNetwork network,
+ KubevirtNode node, boolean install) {
DeviceId deviceId = network.tenantDeviceId(node.hostname());
if (deviceId == null) {
- return;
+ return null;
}
// we check whether the given device is available from the store
@@ -401,7 +405,17 @@
initializeTenantIngressTable(deviceId, install);
initializeTenantEgressTable(deviceId, install);
initializeTenantConnTrackTable(deviceId, install);
- initializeTenantAclTable(network, deviceId, install);
+
+ return deviceId;
+ }
+
+ private void initializeTenantPipeline(KubevirtNetwork network,
+ KubevirtNode node, boolean install) {
+ DeviceId deviceId = initializeTenantPipelineWithoutAcl(network, node, install);
+ if (deviceId == null) {
+ return;
+ }
+ initializeTenantAclTable(deviceId, install);
}
private void updateSecurityGroupRule(KubevirtPort port,
@@ -1011,6 +1025,50 @@
}
}
+ private class InternalBridgeListener implements DeviceListener {
+
+ @Override
+ public boolean isRelevant(DeviceEvent event) {
+ return event.subject().type() == Device.Type.SWITCH;
+ }
+
+ private boolean isRelevantHelper() {
+ return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
+ }
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ Port port = event.port();
+
+ switch (event.type()) {
+ case PORT_ADDED:
+ eventExecutor.execute(() -> {
+ if (!isRelevantHelper()) {
+ return;
+ }
+ initializeTenantAclTable(device, port);
+ });
+ break;
+ case PORT_REMOVED:
+ break;
+ default:
+ // do nothing
+ break;
+ }
+ }
+
+ private void initializeTenantAclTable(Device device, Port port) {
+
+ String portName = port.annotations().value(PORT_NAME);
+ if (!StringUtils.startsWithIgnoreCase(portName, TENANT_TO_TUNNEL_PREFIX)) {
+ return;
+ }
+
+ initializeAclTable(device.id(), TENANT_ACL_RECIRC_TABLE, port.number(), true);
+ }
+ }
+
private class InternalNetworkListener implements KubevirtNetworkListener {
private boolean isRelevantHelper() {
@@ -1036,7 +1094,9 @@
return;
}
- Set<KubevirtNode> nodes = nodeService.completeNodes(WORKER);
+ List<KubevirtNode> nodes = nodeService.completeNodes(WORKER)
+ .stream().sorted(Comparator.comparing(KubevirtNode::hostname))
+ .collect(Collectors.toList());
if (nodes.size() > 0) {
// now we wait 5s for all tenant bridges are created,
@@ -1045,7 +1105,7 @@
waitFor(5);
for (KubevirtNode node : nodes) {
- initializeTenantPipeline(network, node, true);
+ initializeTenantPipelineWithoutAcl(network, node, true);
}
}
}
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
index dcfb4f4..010f675 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtSwitchingTenantHandler.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.kubevirtnetworking.impl;
+import org.apache.commons.lang.StringUtils;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpPrefix;
@@ -25,8 +26,6 @@
import org.onosproject.core.CoreService;
import org.onosproject.kubevirtnetworking.api.KubevirtFlowRuleService;
import org.onosproject.kubevirtnetworking.api.KubevirtNetwork;
-import org.onosproject.kubevirtnetworking.api.KubevirtNetworkEvent;
-import org.onosproject.kubevirtnetworking.api.KubevirtNetworkListener;
import org.onosproject.kubevirtnetworking.api.KubevirtNetworkService;
import org.onosproject.kubevirtnetworking.api.KubevirtPodService;
import org.onosproject.kubevirtnetworking.api.KubevirtPort;
@@ -38,7 +37,11 @@
import org.onosproject.kubevirtnode.api.KubevirtNodeListener;
import org.onosproject.kubevirtnode.api.KubevirtNodeService;
import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -54,12 +57,15 @@
import java.util.Objects;
import java.util.concurrent.ExecutorService;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.kubevirtnetworking.api.Constants.KUBEVIRT_NETWORKING_APP_ID;
import static org.onosproject.kubevirtnetworking.api.Constants.PRIORITY_TUNNEL_RULE;
import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_DEFAULT_TABLE;
+import static org.onosproject.kubevirtnetworking.api.Constants.TUNNEL_TO_TENANT_PREFIX;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.FLAT;
import static org.onosproject.kubevirtnetworking.api.KubevirtNetwork.Type.VLAN;
import static org.onosproject.kubevirtnetworking.util.KubevirtNetworkingUtil.tunnelPort;
@@ -68,6 +74,7 @@
import static org.onosproject.kubevirtnetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.MASTER;
import static org.onosproject.kubevirtnode.api.KubevirtNode.Type.WORKER;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -103,13 +110,13 @@
private final ExecutorService eventExecutor = newSingleThreadExecutor(
groupedThreads(this.getClass().getSimpleName(), "event-handler"));
- private final InternalKubevirtNetworkListener kubevirtNetworkListener =
- new InternalKubevirtNetworkListener();
private final InternalKubevirtPortListener kubevirtPortListener =
new InternalKubevirtPortListener();
private final InternalKubevirtNodeListener kubevirtNodeListener =
new InternalKubevirtNodeListener();
+ private final DeviceListener bridgeListener = new InternalBridgeListener();
+
private ApplicationId appId;
private NodeId localNodeId;
@@ -119,15 +126,15 @@
localNodeId = clusterService.getLocalNode().id();
leadershipService.runForLeadership(appId.name());
kubevirtPortService.addListener(kubevirtPortListener);
- kubevirtNetworkService.addListener(kubevirtNetworkListener);
kubevirtNodeService.addListener(kubevirtNodeListener);
+ deviceService.addListener(bridgeListener);
log.info("Started");
}
@Deactivate
protected void deactivate() {
- kubevirtNetworkService.removeListener(kubevirtNetworkListener);
+ deviceService.removeListener(bridgeListener);
kubevirtPortService.removeListener(kubevirtPortListener);
kubevirtNodeService.removeListener(kubevirtNodeListener);
leadershipService.withdraw(appId.name());
@@ -136,58 +143,6 @@
log.info("Stopped");
}
- private void setIngressRules(KubevirtNetwork network, boolean install) {
- // FIXME: due to the event ordering issue, we remove all ingress rules from KubevirtNetworkHandler class.
- if (!install) {
- return;
- }
-
- if (network == null) {
- return;
- }
-
- if (network.type() == FLAT || network.type() == VLAN) {
- return;
- }
-
- if (network.segmentId() == null) {
- return;
- }
-
- for (KubevirtNode localNode : kubevirtNodeService.completeNodes(WORKER)) {
-
- while (true) {
- KubevirtNode updatedNode = kubevirtNodeService.node(localNode.hostname());
- if (tunnelToTenantPort(deviceService, updatedNode, network) != null) {
- break;
- } else {
- log.info("Waiting for tunnel to tenant patch port creation " +
- "on ingress rule setup on node {}", updatedNode);
- waitFor(3);
- }
- }
-
- PortNumber patchPortNumber = tunnelToTenantPort(deviceService, localNode, network);
-
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
- .matchTunnelId(Long.parseLong(network.segmentId()));
-
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
- .setOutput(patchPortNumber);
-
- flowRuleService.setRule(
- appId,
- localNode.tunBridge(),
- sBuilder.build(),
- tBuilder.build(),
- PRIORITY_TUNNEL_RULE,
- TUNNEL_DEFAULT_TABLE,
- install);
-
- log.debug("Set ingress rules for segment ID {}", network.segmentId());
- }
- }
-
private void setIngressRules(KubevirtNode node, boolean install) {
for (KubevirtNetwork network : kubevirtNetworkService.tenantNetworks()) {
@@ -195,15 +150,9 @@
return;
}
- while (true) {
- KubevirtNode updatedNode = kubevirtNodeService.node(node.hostname());
- if (tunnelToTenantPort(deviceService, updatedNode, network) != null) {
- break;
- } else {
- log.info("Waiting for tunnel to tenant patch port creation " +
- "on ingress rule setup on node {}", updatedNode);
- waitFor(3);
- }
+ KubevirtNode updatedNode = kubevirtNodeService.node(node.hostname());
+ if (tunnelToTenantPort(deviceService, updatedNode, network) == null) {
+ continue;
}
PortNumber patchPortNumber = tunnelToTenantPort(deviceService, node, network);
@@ -351,19 +300,40 @@
}
}
- private class InternalKubevirtNetworkListener implements KubevirtNetworkListener {
+ private class InternalBridgeListener implements DeviceListener {
+
+ @Override
+ public boolean isRelevant(DeviceEvent event) {
+ return event.subject().type() == Device.Type.SWITCH;
+ }
+
private boolean isRelevantHelper() {
return Objects.equals(localNodeId, leadershipService.getLeader(appId.name()));
}
@Override
- public void event(KubevirtNetworkEvent event) {
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ Port port = event.port();
+
switch (event.type()) {
- case KUBEVIRT_NETWORK_CREATED:
- eventExecutor.execute(() -> processNetworkAddition(event.subject()));
+ case PORT_ADDED:
+ eventExecutor.execute(() -> {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ setIngressRules(device, port, true);
+ });
break;
- case KUBEVIRT_NETWORK_REMOVED:
- eventExecutor.execute(() -> processNetworkRemoval(event.subject()));
+ case PORT_REMOVED:
+ eventExecutor.execute(() -> {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ setIngressRules(device, port, false);
+ });
break;
default:
// do nothing
@@ -371,23 +341,51 @@
}
}
- private void processNetworkAddition(KubevirtNetwork network) {
- if (!isRelevantHelper()) {
+ private void setIngressRules(Device device, Port port, boolean install) {
+ boolean foundTunBridge = false;
+
+ for (KubevirtNode node : kubevirtNodeService.nodes()) {
+ if (device.id().equals(node.tunBridge())) {
+ foundTunBridge = true;
+ }
+ }
+
+ if (!foundTunBridge) {
return;
}
- setIngressRules(network, true);
- }
-
- private void processNetworkRemoval(KubevirtNetwork network) {
- if (!isRelevantHelper()) {
+ String portName = port.annotations().value(PORT_NAME);
+ if (!StringUtils.startsWithIgnoreCase(portName, TUNNEL_TO_TENANT_PREFIX)) {
return;
}
- setIngressRules(network, false);
+ Pattern pattern = Pattern.compile("(?i)[0-9a-f]+");
+ Matcher matcher = pattern.matcher(portName);
+
+ // Find the first occurrence of a hexadecimal digit sequence
+ if (matcher.find()) {
+ // Convert the hexadecimal digits to an integer
+ int value = Integer.parseInt(matcher.group(), 16);
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchTunnelId(Long.parseLong(Integer.toString(value)));
+
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setOutput(port.number());
+
+ flowRuleService.setRule(
+ appId,
+ device.id(),
+ sBuilder.build(),
+ tBuilder.build(),
+ PRIORITY_TUNNEL_RULE,
+ TUNNEL_DEFAULT_TABLE,
+ install);
+
+ log.debug("Set ingress rules for segment ID {}", value);
+ }
}
}
-
private class InternalKubevirtPortListener implements KubevirtPortListener {
@Override
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
index d1ec93f..d60800a 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/util/KubevirtNetworkingUtil.java
@@ -457,6 +457,19 @@
}
/**
+ * Gets the number of tenant networks which have the identical segmentation ID of the given network.
+ *
+ * @param networkService network service
+ * @param network kubevirt network
+ * @return number of tenant networks
+ */
+ public static long numOfDupSegNetworks(KubevirtNetworkService networkService, KubevirtNetwork network) {
+ return networkService.networks().stream()
+ .filter(n -> Objects.equals(network.segmentId(), n.segmentId()))
+ .filter(n -> !Objects.equals(network.networkId(), n.networkId())).count();
+ }
+
+ /**
* Obtains the tunnel bridge to tenant bridge patch port number.
*
* @param deviceService device service