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 0000000000..1edc547ac5 --- /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 choices() { + List 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 0000000000..1f22d4d903 --- /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 018b1c2983..4c5b0b778a 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 @@ public class OpenstackFlowRuleManager implements OpenstackFlowRuleService { @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 d7bcc7f02f..74bf68191f 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.Ethernet; 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.osgi.service.component.ComponentContext; 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.api.Constants.PRIORITY_ARP_GAT 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 @@ public class OpenstackRoutingArpHandler { @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 @@ public class OpenstackRoutingArpHandler { // 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 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 @@ public class OpenstackRoutingArpHandler { * @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 completedGws = osNodeService.completeNodes(GATEWAY); Set finalGws = Sets.newConcurrentHashSet(); @@ -442,7 +438,7 @@ public class OpenstackRoutingArpHandler { InstancePort port, Set gateways, boolean install) { - if (arpMode.equals(ARP_BROADCAST_MODE)) { + if (ARP_BROADCAST_MODE.equals(getArpMode())) { OpenstackNode gw = getGwByInstancePort(gateways, port); @@ -469,7 +465,7 @@ public class OpenstackRoutingArpHandler { private synchronized void setFloatingIpArpRule(NetFloatingIP fip, Set 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 @@ public class OpenstackRoutingArpHandler { } 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 @@ public class OpenstackRoutingArpHandler { } private void setDefaultArpRule(OpenstackNode osNode, boolean install) { - switch (arpMode) { + switch (getArpMode()) { case ARP_PROXY_MODE: setDefaultArpRuleForProxyMode(osNode, install); break; @@ -868,7 +864,7 @@ public class OpenstackRoutingArpHandler { 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 a58053ac4f..4e6054fd64 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.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; @@ -84,6 +85,7 @@ import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GAT 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 @@ public final class OpenstackSwitchingArpHandler { @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 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 @@ public final class OpenstackSwitchingArpHandler { 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 @@ public final class OpenstackSwitchingArpHandler { */ 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() @@ -347,6 +341,184 @@ public final class OpenstackSwitchingArpHandler { } } + /** + * 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 @@ public final class OpenstackSwitchingArpHandler { 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 @@ public final class OpenstackSwitchingArpHandler { } private void setDefaultArpRule(OpenstackNode osNode, boolean install) { - switch (arpMode) { + switch (getArpMode()) { case ARP_PROXY_MODE: setDefaultArpRuleForProxyMode(osNode, install); break; @@ -469,13 +643,13 @@ public final class OpenstackSwitchingArpHandler { 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 @@ public final class OpenstackSwitchingArpHandler { 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 @@ public final class OpenstackSwitchingArpHandler { @Override public boolean isRelevant(InstancePortEvent event) { - if (arpMode.equals(ARP_PROXY_MODE)) { + if (ARP_PROXY_MODE.equals(getArpMode())) { return false; } @@ -561,170 +744,5 @@ public final class OpenstackSwitchingArpHandler { 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 9914957c02..2d8bd12082 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.JsonNode; 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.security.cert.X509Certificate; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.TreeMap; @@ -348,6 +350,19 @@ public final class OpenstackNetworkingUtil { }); } + /** + * 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 properties, String name) { + Optional 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. * 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 3d6edff357..77b38986f2 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 @@ + + + + + + + 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 f46d668ba2..59ab91cb04 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.assertArrayEquals; 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 @@ public class OpenstackSwitchingArpHandlerTest { 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();