Only flood the ARP traffic to virtual network to avoid network loop
1. Purge unnecessary phyIntfPort method from openstacknode.
2. Update setUpstreamRulesForFlat method to reflect multi-br change
Change-Id: I6d70702d2aac2a067577635fada06c8eb21b56ae
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
index 3b805e8..a4e817f 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
@@ -55,7 +55,9 @@
import org.onosproject.openstacknode.api.OpenstackNodeEvent;
import org.onosproject.openstacknode.api.OpenstackNodeListener;
import org.onosproject.openstacknode.api.OpenstackNodeService;
+import org.openstack4j.model.common.IdEntity;
import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.NetworkType;
import org.openstack4j.model.network.Subnet;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
@@ -72,6 +74,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
@@ -792,6 +795,35 @@
}
}
+ private void setBaseVnetArpRuleForBroadcastMode(OpenstackNode osNode,
+ String segId,
+ boolean isTunnel,
+ boolean install) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+ .matchArpOp(ARP.OP_REQUEST);
+
+ if (isTunnel) {
+ sBuilder.matchTunnelId(Long.valueOf(segId));
+ } else {
+ sBuilder.matchVlanId(VlanId.vlanId(segId));
+ }
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.FLOOD)
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ sBuilder.build(),
+ treatment,
+ PRIORITY_ARP_FLOOD_RULE,
+ ARP_TABLE,
+ install
+ );
+ }
+
/**
* An internal network listener which listens to openstack network event,
* manages the gateway collection and installs flow rule that handles
@@ -827,7 +859,11 @@
break;
case OPENSTACK_NETWORK_CREATED:
case OPENSTACK_NETWORK_UPDATED:
+ eventExecutor.execute(() -> processNetworkCreation(event));
+ break;
case OPENSTACK_NETWORK_REMOVED:
+ eventExecutor.execute(() -> processNetworkRemoval(event));
+ break;
case OPENSTACK_PORT_CREATED:
case OPENSTACK_PORT_UPDATED:
case OPENSTACK_PORT_REMOVED:
@@ -854,6 +890,41 @@
setFakeGatewayArpRule(event.subnet(), event.subject(),
false, null);
}
+
+ private void processNetworkCreation(OpenstackNetworkEvent event) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ setVnetArpRule(event.subject(), true);
+ }
+
+ private void processNetworkRemoval(OpenstackNetworkEvent event) {
+ if (!isRelevantHelper()) {
+ return;
+ }
+
+ setVnetArpRule(event.subject(), false);
+ }
+
+ private void setVnetArpRule(Network network, boolean install) {
+ String netId = network.getId();
+ NetworkType netType = network.getNetworkType();
+
+ if (netType != NetworkType.LOCAL && netType != NetworkType.FLAT
+ && netType != NetworkType.VLAN) {
+ String segId = osNetworkService.segmentId(netId);
+ osNodeService.completeNodes(COMPUTE)
+ .forEach(node -> setBaseVnetArpRuleForBroadcastMode(
+ node, segId, true, install));
+ }
+ if (netType == NetworkType.VLAN) {
+ String segId = osNetworkService.segmentId(netId);
+ osNodeService.completeNodes(COMPUTE)
+ .forEach(node -> setBaseVnetArpRuleForBroadcastMode(
+ node, segId, false, install));
+ }
+ }
}
/**
@@ -926,7 +997,7 @@
private void processDefaultArpRuleForBroadcastMode(OpenstackNode osNode,
boolean install) {
- setDefaultArpRuleForBroadcastMode(osNode, install);
+ setVnetArpRuleForBroadcastMode(osNode, install);
// we do not add fake gateway ARP rules for FLAT network
// ARP packets generated by FLAT typed VM should not be
@@ -961,27 +1032,29 @@
);
}
- private void setDefaultArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.ARP.ethType().toShort())
- .matchArpOp(ARP.OP_REQUEST)
- .build();
+ private void setVnetArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
+ Set<String> netIds = osNetworkService.networks().stream()
+ .map(IdEntity::getId).collect(Collectors.toSet());
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.FLOOD)
- .build();
+ netIds.stream()
+ .filter(nid -> osNetworkService.networkType(nid) == VXLAN ||
+ osNetworkService.networkType(nid) == GRE ||
+ osNetworkService.networkType(nid) == GENEVE)
+ .forEach(nid -> {
+ String segId = osNetworkService.segmentId(nid);
+ setBaseVnetArpRuleForBroadcastMode(osNode, segId, true, install);
+ });
- osFlowRuleService.setRule(
- appId,
- osNode.intgBridge(),
- selector,
- treatment,
- PRIORITY_ARP_FLOOD_RULE,
- ARP_TABLE,
- install
- );
+ netIds.stream()
+ .filter(nid -> osNetworkService.networkType(nid) == VLAN)
+ .forEach(nid -> {
+ String segId = osNetworkService.segmentId(nid);
+ setBaseVnetArpRuleForBroadcastMode(osNode, segId, false, install);
+ });
}
+
+
private void setAllArpRules(OpenstackNode osNode, boolean install) {
if (ARP_BROADCAST_MODE.equals(getArpMode())) {
instancePortService.instancePorts().stream()
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index b1d69bf..c406990 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -60,6 +60,7 @@
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknetworking.api.Constants.ACL_EGRESS_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
@@ -77,9 +78,11 @@
import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.structurePortName;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
+import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
import static org.slf4j.LoggerFactory.getLogger;
@@ -158,42 +161,37 @@
log.info("Stopped");
}
- private void setFlatJumpRules(InstancePort port, boolean install) {
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchInPort(port.portNumber());
+ private void setJumpRulesForFlat(InstancePort port, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(port.portNumber())
+ .build();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .transition(STAT_FLAT_OUTBOUND_TABLE)
+ .build();
osFlowRuleService.setRule(
appId,
port.deviceId(),
- selector.build(),
- treatment.build(),
+ selector,
+ treatment,
PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
DHCP_TABLE,
install);
-
- Network network = osNetworkService.network(port.networkId());
-
- if (network == null) {
- log.warn("The network does not exist");
- return;
- }
- PortNumber portNumber = osNodeService.node(port.deviceId())
- .phyIntfPortNum(network.getProviderPhyNet());
-
- if (portNumber == null) {
- log.warn("The port number does not exist");
- return;
- }
}
- private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(instPort.ipAddress().toIpPrefix())
- .build();
+ private void setDownstreamRuleForFlat(InstancePort instPort,
+ short ethType, boolean install) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+
+ if (ethType == Ethernet.TYPE_IPV4) {
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(instPort.ipAddress().toIpPrefix());
+ } else if (ethType == Ethernet.TYPE_ARP) {
+ sBuilder.matchEthType(Ethernet.TYPE_ARP)
+ .matchArpTpa(instPort.ipAddress().getIp4Address());
+ }
+
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
.setOutput(instPort.portNumber())
.build();
@@ -201,25 +199,16 @@
osFlowRuleService.setRule(
appId,
instPort.deviceId(),
- selector,
+ sBuilder.build(),
treatment,
PRIORITY_FLAT_DOWNSTREAM_RULE,
FLAT_TABLE,
install);
+ }
- selector = DefaultTrafficSelector.builder()
- .matchEthType(Ethernet.TYPE_ARP)
- .matchArpTpa(instPort.ipAddress().getIp4Address())
- .build();
-
- osFlowRuleService.setRule(
- appId,
- instPort.deviceId(),
- selector,
- treatment,
- PRIORITY_FLAT_DOWNSTREAM_RULE,
- FLAT_TABLE,
- install);
+ private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
+ setDownstreamRuleForFlat(instPort, Ethernet.TYPE_IPV4, install);
+ setDownstreamRuleForFlat(instPort, Ethernet.TYPE_ARP, install);
}
private void setUpstreamRulesForFlat(InstancePort instPort, boolean install) {
@@ -234,26 +223,27 @@
return;
}
- PortNumber portNumber = osNodeService.node(instPort.deviceId())
- .phyIntfPortNum(network.getProviderPhyNet());
+ deviceService.getPorts(instPort.deviceId()).stream()
+ .filter(port -> {
+ String annotPortName = port.annotations().value(PORT_NAME);
+ String portName = structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX
+ + network.getProviderPhyNet());
+ return Objects.equals(annotPortName, portName);
+ })
+ .findAny().ifPresent(port -> {
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(port.number())
+ .build();
- if (portNumber == null) {
- log.warn("The port number does not exist");
- return;
- }
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(portNumber)
- .build();
-
- osFlowRuleService.setRule(
- appId,
- instPort.deviceId(),
- selector,
- treatment,
- PRIORITY_FLAT_UPSTREAM_RULE,
- FLAT_TABLE,
- install);
+ osFlowRuleService.setRule(
+ appId,
+ instPort.deviceId(),
+ selector,
+ treatment,
+ PRIORITY_FLAT_UPSTREAM_RULE,
+ FLAT_TABLE,
+ install);
+ });
}
/**
@@ -750,7 +740,7 @@
}
private void setNetworkRulesForFlat(InstancePort instPort, boolean install) {
- setFlatJumpRules(instPort, install);
+ setJumpRulesForFlat(instPort, install);
setDownstreamRulesForFlat(instPort, install);
setUpstreamRulesForFlat(instPort, install);
}
@@ -798,7 +788,7 @@
}
private void removeVportRulesForFlat(InstancePort instPort) {
- setFlatJumpRules(instPort, false);
+ setJumpRulesForFlat(instPort, false);
setUpstreamRulesForFlat(instPort, false);
setDownstreamRulesForFlat(instPort, false);
}
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
index 5d79f7d..0d72a2b 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java
@@ -30,15 +30,14 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
-import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
import static org.onosproject.net.AnnotationKeys.PORT_MAC;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.openstacknode.api.Constants.GENEVE_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
-import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
+import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
/**
* Representation of a openstack node.
@@ -395,25 +394,6 @@
return neutronConfig;
}
- @Override
- public PortNumber phyIntfPortNum(String providerPhysnet) {
- Optional<OpenstackPhyInterface> openstackPhyInterface =
- phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
-
- if (openstackPhyInterface.isPresent()) {
- DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
- Port port = deviceService.getPorts(intgBridge).stream()
- .filter(p -> p.isEnabled() &&
- Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
- .findAny().orElse(null);
-
- return port != null ? port.number() : null;
- } else {
- return null;
- }
-
- }
-
/**
* Returns new builder instance.
*
diff --git a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
index 2578eb8..8a0e1eb 100644
--- a/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
+++ b/apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/OpenstackNode.java
@@ -188,14 +188,6 @@
Collection<OpenstackPhyInterface> phyIntfs();
/**
- * Returns the port number of given physical interface.
- *
- * @param providerPhysnet provider physical network name
- * @return port number
- */
- PortNumber phyIntfPortNum(String providerPhysnet);
-
- /**
* Returns a collection of customized controllers.
*
* @return customized controllers
diff --git a/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java b/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
index 79a2048..5e6f703 100644
--- a/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
+++ b/apps/openstacknode/api/src/test/java/org/onosproject/openstacknode/api/OpenstackNodeAdapter.java
@@ -134,11 +134,6 @@
}
@Override
- public PortNumber phyIntfPortNum(String providerPhysnet) {
- return null;
- }
-
- @Override
public Collection<ControllerInfo> controllers() {
return null;
}