Skip to content

Commit b3dc1ca

Browse files
committed
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
1 parent a271b3c commit b3dc1ca

File tree

5 files changed

+142
-112
lines changed

5 files changed

+142
-112
lines changed

apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java

Lines changed: 92 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555
import org.onosproject.openstacknode.api.OpenstackNodeEvent;
5656
import org.onosproject.openstacknode.api.OpenstackNodeListener;
5757
import org.onosproject.openstacknode.api.OpenstackNodeService;
58+
import org.openstack4j.model.common.IdEntity;
5859
import org.openstack4j.model.network.Network;
60+
import org.openstack4j.model.network.NetworkType;
5961
import org.openstack4j.model.network.Subnet;
6062
import org.osgi.service.component.ComponentContext;
6163
import org.osgi.service.component.annotations.Activate;
@@ -72,6 +74,7 @@
7274
import java.util.Objects;
7375
import java.util.Set;
7476
import java.util.concurrent.ExecutorService;
77+
import java.util.stream.Collectors;
7578

7679
import static com.google.common.base.Preconditions.checkNotNull;
7780
import static java.util.concurrent.Executors.newSingleThreadExecutor;
@@ -792,6 +795,35 @@ public void process(PacketContext context) {
792795
}
793796
}
794797

798+
private void setBaseVnetArpRuleForBroadcastMode(OpenstackNode osNode,
799+
String segId,
800+
boolean isTunnel,
801+
boolean install) {
802+
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
803+
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
804+
.matchArpOp(ARP.OP_REQUEST);
805+
806+
if (isTunnel) {
807+
sBuilder.matchTunnelId(Long.valueOf(segId));
808+
} else {
809+
sBuilder.matchVlanId(VlanId.vlanId(segId));
810+
}
811+
812+
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
813+
.setOutput(PortNumber.FLOOD)
814+
.build();
815+
816+
osFlowRuleService.setRule(
817+
appId,
818+
osNode.intgBridge(),
819+
sBuilder.build(),
820+
treatment,
821+
PRIORITY_ARP_FLOOD_RULE,
822+
ARP_TABLE,
823+
install
824+
);
825+
}
826+
795827
/**
796828
* An internal network listener which listens to openstack network event,
797829
* manages the gateway collection and installs flow rule that handles
@@ -827,7 +859,11 @@ public void event(OpenstackNetworkEvent event) {
827859
break;
828860
case OPENSTACK_NETWORK_CREATED:
829861
case OPENSTACK_NETWORK_UPDATED:
862+
eventExecutor.execute(() -> processNetworkCreation(event));
863+
break;
830864
case OPENSTACK_NETWORK_REMOVED:
865+
eventExecutor.execute(() -> processNetworkRemoval(event));
866+
break;
831867
case OPENSTACK_PORT_CREATED:
832868
case OPENSTACK_PORT_UPDATED:
833869
case OPENSTACK_PORT_REMOVED:
@@ -854,6 +890,41 @@ private void processSubnetRemoval(OpenstackNetworkEvent event) {
854890
setFakeGatewayArpRule(event.subnet(), event.subject(),
855891
false, null);
856892
}
893+
894+
private void processNetworkCreation(OpenstackNetworkEvent event) {
895+
if (!isRelevantHelper()) {
896+
return;
897+
}
898+
899+
setVnetArpRule(event.subject(), true);
900+
}
901+
902+
private void processNetworkRemoval(OpenstackNetworkEvent event) {
903+
if (!isRelevantHelper()) {
904+
return;
905+
}
906+
907+
setVnetArpRule(event.subject(), false);
908+
}
909+
910+
private void setVnetArpRule(Network network, boolean install) {
911+
String netId = network.getId();
912+
NetworkType netType = network.getNetworkType();
913+
914+
if (netType != NetworkType.LOCAL && netType != NetworkType.FLAT
915+
&& netType != NetworkType.VLAN) {
916+
String segId = osNetworkService.segmentId(netId);
917+
osNodeService.completeNodes(COMPUTE)
918+
.forEach(node -> setBaseVnetArpRuleForBroadcastMode(
919+
node, segId, true, install));
920+
}
921+
if (netType == NetworkType.VLAN) {
922+
String segId = osNetworkService.segmentId(netId);
923+
osNodeService.completeNodes(COMPUTE)
924+
.forEach(node -> setBaseVnetArpRuleForBroadcastMode(
925+
node, segId, false, install));
926+
}
927+
}
857928
}
858929

859930
/**
@@ -926,7 +997,7 @@ private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
926997

927998
private void processDefaultArpRuleForBroadcastMode(OpenstackNode osNode,
928999
boolean install) {
929-
setDefaultArpRuleForBroadcastMode(osNode, install);
1000+
setVnetArpRuleForBroadcastMode(osNode, install);
9301001

9311002
// we do not add fake gateway ARP rules for FLAT network
9321003
// ARP packets generated by FLAT typed VM should not be
@@ -961,27 +1032,29 @@ private void setDefaultArpRuleForProxyMode(OpenstackNode osNode, boolean install
9611032
);
9621033
}
9631034

964-
private void setDefaultArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
965-
TrafficSelector selector = DefaultTrafficSelector.builder()
966-
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
967-
.matchArpOp(ARP.OP_REQUEST)
968-
.build();
969-
970-
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
971-
.setOutput(PortNumber.FLOOD)
972-
.build();
1035+
private void setVnetArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
1036+
Set<String> netIds = osNetworkService.networks().stream()
1037+
.map(IdEntity::getId).collect(Collectors.toSet());
1038+
1039+
netIds.stream()
1040+
.filter(nid -> osNetworkService.networkType(nid) == VXLAN ||
1041+
osNetworkService.networkType(nid) == GRE ||
1042+
osNetworkService.networkType(nid) == GENEVE)
1043+
.forEach(nid -> {
1044+
String segId = osNetworkService.segmentId(nid);
1045+
setBaseVnetArpRuleForBroadcastMode(osNode, segId, true, install);
1046+
});
9731047

974-
osFlowRuleService.setRule(
975-
appId,
976-
osNode.intgBridge(),
977-
selector,
978-
treatment,
979-
PRIORITY_ARP_FLOOD_RULE,
980-
ARP_TABLE,
981-
install
982-
);
1048+
netIds.stream()
1049+
.filter(nid -> osNetworkService.networkType(nid) == VLAN)
1050+
.forEach(nid -> {
1051+
String segId = osNetworkService.segmentId(nid);
1052+
setBaseVnetArpRuleForBroadcastMode(osNode, segId, false, install);
1053+
});
9831054
}
9841055

1056+
1057+
9851058
private void setAllArpRules(OpenstackNode osNode, boolean install) {
9861059
if (ARP_BROADCAST_MODE.equals(getArpMode())) {
9871060
instancePortService.instancePorts().stream()

apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060

6161
import static java.util.concurrent.Executors.newSingleThreadExecutor;
6262
import static org.onlab.util.Tools.groupedThreads;
63+
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
6364
import static org.onosproject.openstacknetworking.api.Constants.ACL_EGRESS_TABLE;
6465
import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
6566
import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
@@ -77,9 +78,11 @@
7778
import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
7879
import static org.onosproject.openstacknetworking.api.InstancePortEvent.Type.OPENSTACK_INSTANCE_MIGRATION_STARTED;
7980
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
81+
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.structurePortName;
8082
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
8183
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.tunnelPortNumByNetId;
8284
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
85+
import static org.onosproject.openstacknode.api.Constants.INTEGRATION_TO_PHYSICAL_PREFIX;
8386
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
8487
import static org.slf4j.LoggerFactory.getLogger;
8588

@@ -158,68 +161,54 @@ protected void deactivate() {
158161
log.info("Stopped");
159162
}
160163

161-
private void setFlatJumpRules(InstancePort port, boolean install) {
162-
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
163-
selector.matchInPort(port.portNumber());
164+
private void setJumpRulesForFlat(InstancePort port, boolean install) {
165+
TrafficSelector selector = DefaultTrafficSelector.builder()
166+
.matchInPort(port.portNumber())
167+
.build();
164168

165-
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
166-
treatment.transition(STAT_FLAT_OUTBOUND_TABLE);
169+
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
170+
.transition(STAT_FLAT_OUTBOUND_TABLE)
171+
.build();
167172

168173
osFlowRuleService.setRule(
169174
appId,
170175
port.deviceId(),
171-
selector.build(),
172-
treatment.build(),
176+
selector,
177+
treatment,
173178
PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
174179
DHCP_TABLE,
175180
install);
181+
}
176182

177-
Network network = osNetworkService.network(port.networkId());
183+
private void setDownstreamRuleForFlat(InstancePort instPort,
184+
short ethType, boolean install) {
185+
TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
178186

179-
if (network == null) {
180-
log.warn("The network does not exist");
181-
return;
187+
if (ethType == Ethernet.TYPE_IPV4) {
188+
sBuilder.matchEthType(Ethernet.TYPE_IPV4)
189+
.matchIPDst(instPort.ipAddress().toIpPrefix());
190+
} else if (ethType == Ethernet.TYPE_ARP) {
191+
sBuilder.matchEthType(Ethernet.TYPE_ARP)
192+
.matchArpTpa(instPort.ipAddress().getIp4Address());
182193
}
183-
PortNumber portNumber = osNodeService.node(port.deviceId())
184-
.phyIntfPortNum(network.getProviderPhyNet());
185194

186-
if (portNumber == null) {
187-
log.warn("The port number does not exist");
188-
return;
189-
}
190-
}
191-
192-
private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
193-
TrafficSelector selector = DefaultTrafficSelector.builder()
194-
.matchEthType(Ethernet.TYPE_IPV4)
195-
.matchIPDst(instPort.ipAddress().toIpPrefix())
196-
.build();
197195
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
198196
.setOutput(instPort.portNumber())
199197
.build();
200198

201199
osFlowRuleService.setRule(
202200
appId,
203201
instPort.deviceId(),
204-
selector,
202+
sBuilder.build(),
205203
treatment,
206204
PRIORITY_FLAT_DOWNSTREAM_RULE,
207205
FLAT_TABLE,
208206
install);
207+
}
209208

210-
selector = DefaultTrafficSelector.builder()
211-
.matchEthType(Ethernet.TYPE_ARP)
212-
.matchArpTpa(instPort.ipAddress().getIp4Address())
213-
.build();
214-
215-
osFlowRuleService.setRule(
216-
appId,
217-
instPort.deviceId(),
218-
selector,
219-
treatment,
220-
PRIORITY_FLAT_DOWNSTREAM_RULE,
221-
FLAT_TABLE,
222-
install);
209+
private void setDownstreamRulesForFlat(InstancePort instPort, boolean install) {
210+
setDownstreamRuleForFlat(instPort, Ethernet.TYPE_IPV4, install);
211+
setDownstreamRuleForFlat(instPort, Ethernet.TYPE_ARP, install);
223212
}
224213

225214
private void setUpstreamRulesForFlat(InstancePort instPort, boolean install) {
@@ -234,26 +223,27 @@ private void setUpstreamRulesForFlat(InstancePort instPort, boolean install) {
234223
return;
235224
}
236225

237-
PortNumber portNumber = osNodeService.node(instPort.deviceId())
238-
.phyIntfPortNum(network.getProviderPhyNet());
239-
240-
if (portNumber == null) {
241-
log.warn("The port number does not exist");
242-
return;
243-
}
244-
245-
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
246-
.setOutput(portNumber)
247-
.build();
226+
deviceService.getPorts(instPort.deviceId()).stream()
227+
.filter(port -> {
228+
String annotPortName = port.annotations().value(PORT_NAME);
229+
String portName = structurePortName(INTEGRATION_TO_PHYSICAL_PREFIX
230+
+ network.getProviderPhyNet());
231+
return Objects.equals(annotPortName, portName);
232+
})
233+
.findAny().ifPresent(port -> {
234+
TrafficTreatment treatment = DefaultTrafficTreatment.builder()
235+
.setOutput(port.number())
236+
.build();
248237

249-
osFlowRuleService.setRule(
250-
appId,
251-
instPort.deviceId(),
252-
selector,
253-
treatment,
254-
PRIORITY_FLAT_UPSTREAM_RULE,
255-
FLAT_TABLE,
256-
install);
238+
osFlowRuleService.setRule(
239+
appId,
240+
instPort.deviceId(),
241+
selector,
242+
treatment,
243+
PRIORITY_FLAT_UPSTREAM_RULE,
244+
FLAT_TABLE,
245+
install);
246+
});
257247
}
258248

259249
/**
@@ -750,7 +740,7 @@ private void setNetworkRulesForVlan(InstancePort instPort, boolean install) {
750740
}
751741

752742
private void setNetworkRulesForFlat(InstancePort instPort, boolean install) {
753-
setFlatJumpRules(instPort, install);
743+
setJumpRulesForFlat(instPort, install);
754744
setDownstreamRulesForFlat(instPort, install);
755745
setUpstreamRulesForFlat(instPort, install);
756746
}
@@ -798,7 +788,7 @@ private void removeVportRulesForVlan(InstancePort instPort) {
798788
}
799789

800790
private void removeVportRulesForFlat(InstancePort instPort) {
801-
setFlatJumpRules(instPort, false);
791+
setJumpRulesForFlat(instPort, false);
802792
setUpstreamRulesForFlat(instPort, false);
803793
setDownstreamRulesForFlat(instPort, false);
804794
}

apps/openstacknode/api/src/main/java/org/onosproject/openstacknode/api/DefaultOpenstackNode.java

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,14 @@
3030
import java.util.ArrayList;
3131
import java.util.Collection;
3232
import java.util.Objects;
33-
import java.util.Optional;
3433

3534
import static com.google.common.base.Preconditions.checkArgument;
3635
import static org.onosproject.net.AnnotationKeys.PORT_MAC;
3736
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
3837
import static org.onosproject.openstacknode.api.Constants.GENEVE_TUNNEL;
3938
import static org.onosproject.openstacknode.api.Constants.GRE_TUNNEL;
40-
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
4139
import static org.onosproject.openstacknode.api.Constants.PATCH_INTG_BRIDGE;
40+
import static org.onosproject.openstacknode.api.Constants.VXLAN_TUNNEL;
4241

4342
/**
4443
* Representation of a openstack node.
@@ -395,25 +394,6 @@ public NeutronConfig neutronConfig() {
395394
return neutronConfig;
396395
}
397396

398-
@Override
399-
public PortNumber phyIntfPortNum(String providerPhysnet) {
400-
Optional<OpenstackPhyInterface> openstackPhyInterface =
401-
phyIntfs.stream().filter(p -> p.network().equals(providerPhysnet)).findAny();
402-
403-
if (openstackPhyInterface.isPresent()) {
404-
DeviceService deviceService = DefaultServiceDirectory.getService(DeviceService.class);
405-
Port port = deviceService.getPorts(intgBridge).stream()
406-
.filter(p -> p.isEnabled() &&
407-
Objects.equals(p.annotations().value(PORT_NAME), openstackPhyInterface.get().intf()))
408-
.findAny().orElse(null);
409-
410-
return port != null ? port.number() : null;
411-
} else {
412-
return null;
413-
}
414-
415-
}
416-
417397
/**
418398
* Returns new builder instance.
419399
*

0 commit comments

Comments
 (0)