Add CLI for reconfiguring ARP mode on openstacknetworking app
Change-Id: I4211681ccf6eaea9c76ec27adc45e0f1cc71d0d7
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/ArpModeCompleter.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/ArpModeCompleter.java
new file mode 100644
index 0000000..1edc547
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/ArpModeCompleter.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.cli;
+
+import com.google.common.collect.Lists;
+import org.onosproject.cli.AbstractChoicesCompleter;
+
+import java.util.List;
+
+/**
+ * ARP mode completer.
+ */
+public class ArpModeCompleter extends AbstractChoicesCompleter {
+
+ @Override
+ protected List<String> choices() {
+ List<String> strings = Lists.newArrayList();
+ strings.add("proxy");
+ strings.add("broadcast");
+ return strings;
+ }
+}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackConfigArpModeCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackConfigArpModeCommand.java
new file mode 100644
index 0000000..1f22d4d
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackConfigArpModeCommand.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2018-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstacknetworking.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.openstacknetworking.api.Constants;
+import org.onosproject.openstacknetworking.impl.OpenstackRoutingArpHandler;
+import org.onosproject.openstacknetworking.impl.OpenstackSwitchingArpHandler;
+import org.onosproject.openstacknode.api.NodeState;
+import org.onosproject.openstacknode.api.OpenstackNode;
+import org.onosproject.openstacknode.api.OpenstackNodeAdminService;
+import org.onosproject.openstacknode.api.OpenstackNodeService;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
+
+/**
+ * Configure ARP mode.
+ */
+@Command(scope = "onos", name = "openstack-config-arp-mode",
+ description = "Re-configure ARP mode (proxy | broadcast)")
+public class OpenstackConfigArpModeCommand extends AbstractShellCommand {
+
+ private static final String ARP_MODE_NAME = "arpMode";
+ private static final String PROXY_MODE = "proxy";
+ private static final String BROADCAST_MODE = "broadcast";
+
+ @Argument(index = 0, name = "arpMode",
+ description = "ARP mode (proxy | broadcast)",
+ required = true, multiValued = false)
+ String arpMode = null;
+
+ @Override
+ protected void execute() {
+
+ if (checkArpMode(arpMode)) {
+ configArpMode();
+
+ ComponentConfigService service = get(ComponentConfigService.class);
+ String switchingComponent = OpenstackSwitchingArpHandler.class.getName();
+ String routingComponent = OpenstackRoutingArpHandler.class.getName();
+
+ // we check the arpMode configured in each component, and purge and
+ // reinstall all rules only if the arpMode is changed to the configured one
+ while (true) {
+ String switchingValue =
+ getPropertyValue(service.getProperties(switchingComponent), ARP_MODE_NAME);
+ String routingValue =
+ getPropertyValue(service.getProperties(routingComponent), ARP_MODE_NAME);
+
+ if (arpMode.equals(switchingValue) && arpMode.equals(routingValue)) {
+ break;
+ }
+ }
+
+ purgeRules();
+ syncRules();
+ }
+ }
+
+ private boolean checkArpMode(String arpMode) {
+
+ if (isNullOrEmpty(arpMode)) {
+ error("ARP mode should not be empty string or null");
+ return false;
+ } else {
+ if (arpMode.equals(PROXY_MODE) || arpMode.equals(BROADCAST_MODE)) {
+ return true;
+ } else {
+ error("ARP mode should be either proxy or broadcast");
+ return false;
+ }
+ }
+ }
+
+ private void purgeRules() {
+ FlowRuleService flowRuleService = AbstractShellCommand.get(FlowRuleService.class);
+ CoreService coreService = AbstractShellCommand.get(CoreService.class);
+ ApplicationId appId = coreService.getAppId(Constants.OPENSTACK_NETWORKING_APP_ID);
+ if (appId == null) {
+ error("Failed to purge OpenStack networking flow rules.");
+ return;
+ }
+ flowRuleService.removeFlowRulesById(appId);
+ }
+
+ private void configArpMode() {
+ ComponentConfigService service = get(ComponentConfigService.class);
+ String switchingComponent = OpenstackSwitchingArpHandler.class.getName();
+ String routingComponent = OpenstackRoutingArpHandler.class.getName();
+
+ if (!isNullOrEmpty(arpMode)) {
+ service.setProperty(switchingComponent, ARP_MODE_NAME, arpMode);
+ service.setProperty(routingComponent, ARP_MODE_NAME, arpMode);
+ }
+ }
+
+ private void syncRules() {
+ // All handlers in this application reacts the node complete event and
+ // tries to re-configure flow rules for the complete node.
+ OpenstackNodeService osNodeService = AbstractShellCommand.get(OpenstackNodeService.class);
+ OpenstackNodeAdminService osNodeAdminService = AbstractShellCommand.get(OpenstackNodeAdminService.class);
+ if (osNodeService == null) {
+ error("Failed to re-install flow rules for OpenStack networking.");
+ return;
+ }
+ osNodeService.completeNodes().forEach(osNode -> {
+ OpenstackNode updated = osNode.updateState(NodeState.INIT);
+ osNodeAdminService.updateNode(updated);
+ });
+ }
+}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
index 018b1c2..4c5b0b7 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
@@ -137,7 +137,7 @@
@Override
public void onError(FlowRuleOperations ops) {
- log.debug("Failed to privision vni or forwarding table");
+ log.debug("Failed to provision vni or forwarding table");
}
}));
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
index d7bcc7f..74bf681 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingArpHandler.java
@@ -32,8 +32,8 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
-import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.cluster.NodeId;
@@ -77,7 +77,6 @@
import org.slf4j.Logger;
import java.nio.ByteBuffer;
-import java.util.Dictionary;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -97,6 +96,7 @@
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.associatedFloatingIp;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByComputeDevId;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGwByInstancePort;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.isAssociatedWithVM;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.GATEWAY;
import static org.slf4j.LoggerFactory.getLogger;
@@ -146,8 +146,6 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService configService;
- // TODO: need to find a way to unify aprMode and gatewayMac variables with
- // that in SwitchingArpHandler
@Property(name = ARP_MODE, value = DEFAULT_ARP_MODE_STR,
label = "ARP processing mode, broadcast | proxy (default)")
protected String arpMode = DEFAULT_ARP_MODE_STR;
@@ -205,21 +203,19 @@
// that in SwitchingArpHandler
@Modified
void modified(ComponentContext context) {
- Dictionary<?, ?> properties = context.getProperties();
- String updateArpMode;
-
- updateArpMode = Tools.get(properties, ARP_MODE);
- if (!Strings.isNullOrEmpty(updateArpMode) && !updateArpMode.equals(arpMode)) {
- arpMode = updateArpMode;
- }
log.info("Modified");
}
+ private String getArpMode() {
+ Set<ConfigProperty> properties = configService.getProperties(this.getClass().getName());
+ return getPropertyValue(properties, ARP_MODE);
+ }
+
private void processArpPacket(PacketContext context, Ethernet ethernet) {
ARP arp = (ARP) ethernet.getPayload();
- if (arp.getOpCode() == ARP.OP_REQUEST && arpMode.equals(ARP_PROXY_MODE)) {
+ if (arp.getOpCode() == ARP.OP_REQUEST && ARP_PROXY_MODE.equals(getArpMode())) {
if (log.isTraceEnabled()) {
log.trace("ARP request received from {} for {}",
Ip4Address.valueOf(arp.getSenderProtocolAddress()).toString(),
@@ -381,7 +377,7 @@
* @param install flow rule installation flag
*/
private void setFloatingIpArpRuleForGateway(OpenstackNode gateway, boolean install) {
- if (arpMode.equals(ARP_BROADCAST_MODE)) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
Set<OpenstackNode> completedGws = osNodeService.completeNodes(GATEWAY);
Set<OpenstackNode> finalGws = Sets.newConcurrentHashSet();
@@ -442,7 +438,7 @@
InstancePort port,
Set<OpenstackNode> gateways,
boolean install) {
- if (arpMode.equals(ARP_BROADCAST_MODE)) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
OpenstackNode gw = getGwByInstancePort(gateways, port);
@@ -469,7 +465,7 @@
private synchronized void setFloatingIpArpRule(NetFloatingIP fip,
Set<OpenstackNode> gateways,
boolean install) {
- if (arpMode.equals(ARP_BROADCAST_MODE)) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
if (fip == null) {
log.warn("Failed to set ARP broadcast rule for floating IP");
@@ -671,7 +667,7 @@
}
private void setFakeGatewayArpRule(ExternalGateway extGw, boolean install) {
- if (arpMode.equals(ARP_BROADCAST_MODE)) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
if (extGw == null) {
return;
@@ -859,7 +855,7 @@
}
private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
- switch (arpMode) {
+ switch (getArpMode()) {
case ARP_PROXY_MODE:
setDefaultArpRuleForProxyMode(osNode, install);
break;
@@ -868,7 +864,7 @@
break;
default:
log.warn("Invalid ARP mode {}. Please use either " +
- "broadcast or proxy mode.", arpMode);
+ "broadcast or proxy mode.", getArpMode());
break;
}
}
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 a58053ac..4e6054f 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
@@ -32,6 +32,7 @@
import org.onlab.packet.MacAddress;
import org.onlab.util.Tools;
import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.LeadershipService;
import org.onosproject.cluster.NodeId;
@@ -84,6 +85,7 @@
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_REPLY_RULE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_REQUEST_RULE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_SUBNET_RULE;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
@@ -189,24 +191,16 @@
@Modified
void modified(ComponentContext context) {
- Dictionary<?, ?> properties = context.getProperties();
- String updatedMac;
-
- updatedMac = Tools.get(properties, GATEWAY_MAC);
- if (!Strings.isNullOrEmpty(updatedMac) && !updatedMac.equals(gatewayMac)) {
- gatewayMac = updatedMac;
- }
-
- String updateArpMode;
-
- updateArpMode = Tools.get(properties, ARP_MODE);
- if (!Strings.isNullOrEmpty(updateArpMode) && !updateArpMode.equals(arpMode)) {
- arpMode = updateArpMode;
- }
+ readComponentConfiguration(context);
log.info("Modified");
}
+ private String getArpMode() {
+ Set<ConfigProperty> properties = configService.getProperties(this.getClass().getName());
+ return getPropertyValue(properties, ARP_MODE);
+ }
+
private void addSubnetGateway(Subnet osSubnet) {
if (Strings.isNullOrEmpty(osSubnet.getGateway())) {
return;
@@ -236,7 +230,7 @@
private void processPacketIn(PacketContext context, Ethernet ethPacket) {
// if the ARP mode is configured as broadcast mode, we simply ignore ARP packet_in
- if (arpMode.equals(ARP_BROADCAST_MODE)) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
return;
}
@@ -304,7 +298,7 @@
*/
private void setFakeGatewayArpRule(Subnet osSubnet, boolean install, OpenstackNode osNode) {
- if (arpMode.equals(ARP_BROADCAST_MODE)) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
String gateway = osSubnet.getGateway();
TrafficSelector selector = DefaultTrafficSelector.builder()
@@ -348,6 +342,184 @@
}
/**
+ * Installs flow rules to match ARP request packets.
+ *
+ * @param port instance port
+ * @param install installation flag
+ */
+ private void setArpRequestRule(InstancePort port, boolean install) {
+ NetworkType type = osNetworkService.network(port.networkId()).getNetworkType();
+
+ switch (type) {
+ case VXLAN:
+ setRemoteArpRequestRuleForVxlan(port, install);
+ break;
+ case VLAN:
+ // since VLAN ARP packet can be broadcasted to all hosts that connected with L2 network,
+ // there is no need to add any flow rules to handle ARP request
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Installs flow rules to match ARP reply packets.
+ *
+ * @param port instance port
+ * @param install installation flag
+ */
+ private void setArpReplyRule(InstancePort port, boolean install) {
+ NetworkType type = osNetworkService.network(port.networkId()).getNetworkType();
+
+ switch (type) {
+ case VXLAN:
+ setArpReplyRuleForVxlan(port, install);
+ break;
+ case VLAN:
+ setArpReplyRuleForVlan(port, install);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Installs flow rules to match ARP request packets only for VxLAN.
+ *
+ * @param port instance port
+ * @param install installation flag
+ */
+ private void setRemoteArpRequestRuleForVxlan(InstancePort port, boolean install) {
+
+ OpenstackNode localNode = osNodeService.node(port.deviceId());
+
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+ .matchArpOp(ARP.OP_REQUEST)
+ .matchArpTpa(port.ipAddress().getIp4Address())
+ .build();
+
+ setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
+ }
+
+ /**
+ * Installs flow rules to match ARP reply packets only for VxLAN.
+ *
+ * @param port instance port
+ * @param install installation flag
+ */
+ private void setArpReplyRuleForVxlan(InstancePort port, boolean install) {
+
+ OpenstackNode localNode = osNodeService.node(port.deviceId());
+
+ TrafficSelector selector = setArpReplyRuleForVnet(port, install);
+ setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
+ }
+
+ /**
+ * Installs flow rules to match ARP reply packets only for VLAN.
+ *
+ * @param port instance port
+ * @param install installation flag
+ */
+ private void setArpReplyRuleForVlan(InstancePort port, boolean install) {
+
+ TrafficSelector selector = setArpReplyRuleForVnet(port, install);
+ setRemoteArpTreatmentForVlan(selector, port, install);
+ }
+
+ // a helper method
+ private TrafficSelector setArpReplyRuleForVnet(InstancePort port, boolean install) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+ .matchArpOp(ARP.OP_REPLY)
+ .matchArpTpa(port.ipAddress().getIp4Address())
+ .matchArpTha(port.macAddress())
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(port.portNumber())
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ port.deviceId(),
+ selector,
+ treatment,
+ PRIORITY_ARP_REPLY_RULE,
+ DHCP_ARP_TABLE,
+ install
+ );
+
+ return selector;
+ }
+
+ // a helper method
+ private void setRemoteArpTreatmentForVxlan(TrafficSelector selector,
+ InstancePort port,
+ OpenstackNode localNode,
+ boolean install) {
+ for (OpenstackNode remoteNode : osNodeService.completeNodes(COMPUTE)) {
+ if (!remoteNode.intgBridge().equals(port.deviceId())) {
+ TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
+ .extension(buildExtension(
+ deviceService,
+ remoteNode.intgBridge(),
+ localNode.dataIp().getIp4Address()),
+ remoteNode.intgBridge())
+ .setOutput(remoteNode.tunnelPortNum())
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ remoteNode.intgBridge(),
+ selector,
+ treatmentToRemote,
+ PRIORITY_ARP_REQUEST_RULE,
+ DHCP_ARP_TABLE,
+ install
+ );
+ }
+ }
+ }
+
+ // a helper method
+ private void setRemoteArpTreatmentForVlan(TrafficSelector selector,
+ InstancePort port,
+ boolean install) {
+ for (OpenstackNode remoteNode : osNodeService.completeNodes(COMPUTE)) {
+ if (!remoteNode.intgBridge().equals(port.deviceId()) && remoteNode.vlanIntf() != null) {
+ TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
+ .setOutput(remoteNode.vlanPortNum())
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ remoteNode.intgBridge(),
+ selector,
+ treatmentToRemote,
+ PRIORITY_ARP_REQUEST_RULE,
+ DHCP_ARP_TABLE,
+ install);
+ }
+ }
+ }
+
+ /**
+ * Extracts properties from the component configuration context.
+ *
+ * @param context the component context
+ */
+ private void readComponentConfiguration(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+
+ String updatedMac = Tools.get(properties, GATEWAY_MAC);
+ gatewayMac = updatedMac != null ? updatedMac : DEFAULT_GATEWAY_MAC_STR;
+ log.info("Configured. Gateway MAC is {}", gatewayMac);
+ }
+
+ /**
* An internal packet processor which processes ARP request, and results in
* packet-out ARP reply.
*/
@@ -446,9 +618,11 @@
switch (event.type()) {
case OPENSTACK_NODE_COMPLETE:
setDefaultArpRule(osNode, true);
+ setAllArpRules(true);
break;
case OPENSTACK_NODE_INCOMPLETE:
setDefaultArpRule(osNode, false);
+ setAllArpRules(false);
break;
default:
break;
@@ -456,7 +630,7 @@
}
private void setDefaultArpRule(OpenstackNode osNode, boolean install) {
- switch (arpMode) {
+ switch (getArpMode()) {
case ARP_PROXY_MODE:
setDefaultArpRuleForProxyMode(osNode, install);
break;
@@ -469,13 +643,13 @@
osNetworkService.subnets().stream().filter(subnet ->
osNetworkService.network(subnet.getNetworkId()) != null &&
osNetworkService.network(subnet.getNetworkId())
- .getNetworkType() == NetworkType.FLAT)
+ .getNetworkType() != NetworkType.FLAT)
.forEach(subnet ->
setFakeGatewayArpRule(subnet, install, osNode));
break;
default:
log.warn("Invalid ARP mode {}. Please use either " +
- "broadcast or proxy mode.", arpMode);
+ "broadcast or proxy mode.", getArpMode());
break;
}
}
@@ -520,6 +694,15 @@
install
);
}
+
+ private void setAllArpRules(boolean install) {
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+ instancePortService.instancePorts().forEach(p -> {
+ setArpRequestRule(p, install);
+ setArpReplyRule(p, install);
+ });
+ }
+ }
}
/**
@@ -534,7 +717,7 @@
@Override
public boolean isRelevant(InstancePortEvent event) {
- if (arpMode.equals(ARP_PROXY_MODE)) {
+ if (ARP_PROXY_MODE.equals(getArpMode())) {
return false;
}
@@ -561,170 +744,5 @@
break;
}
}
-
- /**
- * Installs flow rules to match ARP request packets.
- *
- * @param port instance port
- * @param install installation flag
- */
- private void setArpRequestRule(InstancePort port, boolean install) {
- NetworkType type = osNetworkService.network(port.networkId()).getNetworkType();
-
- switch (type) {
- case VXLAN:
- setRemoteArpRequestRuleForVxlan(port, install);
- break;
- case VLAN:
- // since VLAN ARP packet can be broadcasted to all hosts that connected with L2 network,
- // there is no need to add any flow rules to handle ARP request
- break;
- default:
- break;
- }
- }
-
- /**
- * Installs flow rules to match ARP reply packets.
- *
- * @param port instance port
- * @param install installation flag
- */
- private void setArpReplyRule(InstancePort port, boolean install) {
- NetworkType type = osNetworkService.network(port.networkId()).getNetworkType();
-
- switch (type) {
- case VXLAN:
- setArpReplyRuleForVxlan(port, install);
- break;
- case VLAN:
- setArpReplyRuleForVlan(port, install);
- break;
- default:
- break;
- }
- }
-
- /**
- * Installs flow rules to match ARP request packets only for VxLAN.
- *
- * @param port instance port
- * @param install installation flag
- */
- private void setRemoteArpRequestRuleForVxlan(InstancePort port, boolean install) {
-
- OpenstackNode localNode = osNodeService.node(port.deviceId());
-
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.ARP.ethType().toShort())
- .matchArpOp(ARP.OP_REQUEST)
- .matchArpTpa(port.ipAddress().getIp4Address())
- .build();
-
- setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
- }
-
- /**
- * Installs flow rules to match ARP reply packets only for VxLAN.
- *
- * @param port instance port
- * @param install installation flag
- */
- private void setArpReplyRuleForVxlan(InstancePort port, boolean install) {
-
- OpenstackNode localNode = osNodeService.node(port.deviceId());
-
- TrafficSelector selector = setArpReplyRuleForVnet(port, install);
- setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
- }
-
- /**
- * Installs flow rules to match ARP reply packets only for VLAN.
- *
- * @param port instance port
- * @param install installation flag
- */
- private void setArpReplyRuleForVlan(InstancePort port, boolean install) {
-
- TrafficSelector selector = setArpReplyRuleForVnet(port, install);
- setRemoteArpTreatmentForVlan(selector, port, install);
- }
-
- // a helper method
- private TrafficSelector setArpReplyRuleForVnet(InstancePort port, boolean install) {
- TrafficSelector selector = DefaultTrafficSelector.builder()
- .matchEthType(EthType.EtherType.ARP.ethType().toShort())
- .matchArpOp(ARP.OP_REPLY)
- .matchArpTpa(port.ipAddress().getIp4Address())
- .matchArpTha(port.macAddress())
- .build();
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(port.portNumber())
- .build();
-
- osFlowRuleService.setRule(
- appId,
- port.deviceId(),
- selector,
- treatment,
- PRIORITY_ARP_REPLY_RULE,
- DHCP_ARP_TABLE,
- install
- );
-
- return selector;
- }
-
- // a helper method
- private void setRemoteArpTreatmentForVxlan(TrafficSelector selector,
- InstancePort port,
- OpenstackNode localNode,
- boolean install) {
- for (OpenstackNode remoteNode : osNodeService.completeNodes(COMPUTE)) {
- if (!remoteNode.intgBridge().equals(port.deviceId())) {
- TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
- .extension(buildExtension(
- deviceService,
- remoteNode.intgBridge(),
- localNode.dataIp().getIp4Address()),
- remoteNode.intgBridge())
- .setOutput(remoteNode.tunnelPortNum())
- .build();
-
- osFlowRuleService.setRule(
- appId,
- remoteNode.intgBridge(),
- selector,
- treatmentToRemote,
- PRIORITY_ARP_REQUEST_RULE,
- DHCP_ARP_TABLE,
- install
- );
- }
- }
- }
-
- // a helper method
- private void setRemoteArpTreatmentForVlan(TrafficSelector selector,
- InstancePort port,
- boolean install) {
- for (OpenstackNode remoteNode : osNodeService.completeNodes(COMPUTE)) {
- if (!remoteNode.intgBridge().equals(port.deviceId()) && remoteNode.vlanIntf() != null) {
- TrafficTreatment treatmentToRemote = DefaultTrafficTreatment.builder()
- .setOutput(remoteNode.vlanPortNum())
- .build();
-
- osFlowRuleService.setRule(
- appId,
- remoteNode.intgBridge(),
- selector,
- treatmentToRemote,
- PRIORITY_ARP_REQUEST_RULE,
- DHCP_ARP_TABLE,
- install);
- }
- }
- }
}
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
index 9914957..2d8bd12 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/OpenstackNetworkingUtil.java
@@ -19,10 +19,11 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Strings;
+import org.onosproject.cfg.ConfigProperty;
import org.onosproject.net.DeviceId;
import org.onosproject.openstacknetworking.api.InstancePort;
-import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
import org.onosproject.openstacknetworking.api.OpenstackNetworkService;
+import org.onosproject.openstacknetworking.api.OpenstackRouterAdminService;
import org.onosproject.openstacknode.api.OpenstackAuth;
import org.onosproject.openstacknode.api.OpenstackAuth.Perspective;
import org.onosproject.openstacknode.api.OpenstackNode;
@@ -54,6 +55,7 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
@@ -349,6 +351,19 @@
}
/**
+ * Obtains the property value with specified property key name.
+ *
+ * @param properties a collection of properties
+ * @param name key name
+ * @return mapping value
+ */
+ public static String getPropertyValue(Set<ConfigProperty> properties, String name) {
+ Optional<ConfigProperty> property =
+ properties.stream().filter(p -> p.name().equals(name)).findFirst();
+ return property.map(ConfigProperty::value).orElse(null);
+ }
+
+ /**
* Builds up and a complete endpoint URL from gateway node.
*
* @param node gateway node
diff --git a/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 3d6edff..77b3898 100644
--- a/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/openstacknetworking/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -68,9 +68,16 @@
<ref component-id="ipAddressCompleter"/>
</completers>
</command>
+ <command>
+ <action class="org.onosproject.openstacknetworking.cli.OpenstackConfigArpModeCommand" />
+ <completers>
+ <ref component-id="arpModeCompleter"/>
+ </completers>
+ </command>
</command-bundle>
<bean id="ipAddressCompleter" class="org.onosproject.openstacknetworking.cli.IpAddressCompleter"/>
<bean id="macAddressCompleter" class="org.onosproject.openstacknetworking.cli.MacAddressCompleter"/>
<bean id="vlanIdCompleter" class="org.onosproject.openstacknetworking.cli.VlanIdCompleter"/>
+ <bean id="arpModeCompleter" class="org.onosproject.openstacknetworking.cli.ArpModeCompleter"/>
</blueprint>
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java
index f46d668..59ab91c 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandlerTest.java
@@ -45,7 +45,6 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.onosproject.net.NetTestTools.connectPoint;
-import static org.onosproject.openstacknetworking.api.Constants.ARP_PROXY_MODE;
public class OpenstackSwitchingArpHandlerTest {
@@ -68,7 +67,6 @@
arpHandler.osNetworkService = new TestOpenstackNetworkService();
arpHandler.osNodeService = new TestOpenstackNodeService();
arpHandler.osFlowRuleService = new TestOpenstackFlowRuleService();
- arpHandler.arpMode = ARP_PROXY_MODE;
arpHandler.clusterService = new TestClusterService();
arpHandler.leadershipService = new TestLeadershipService();
arpHandler.activate();