Add group rule service, purge flood rules, use group to handle ARP
Change-Id: If0db889d6ab28a4d36f433f16bf84241d2726045
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
index 6475a7a..891b1ee 100644
--- a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/Constants.java
@@ -68,7 +68,6 @@
public static final String UNSUPPORTED_VENDOR = "unsupported_vendor";
public static final int PRIORITY_TUNNEL_TAG_RULE = 30000;
- public static final int PRIORITY_FLOATING_INTERNAL = 42000;
public static final int PRIORITY_FLOATING_EXTERNAL = 41000;
public static final int PRIORITY_STATEFUL_SNAT_RULE = 40500;
public static final int PRIORITY_ICMP_RULE = 43000;
@@ -79,7 +78,6 @@
public static final int PRIORITY_SNAT_RULE = 26000;
public static final int PRIORITY_SWITCHING_RULE = 30000;
public static final int PRIORITY_FLAT_JUMP_UPSTREAM_RULE = 41000;
- public static final int PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE = 41000;
public static final int PRIORITY_FLAT_UPSTREAM_RULE = 41000;
public static final int PRIORITY_FLAT_DOWNSTREAM_RULE = 42000;
public static final int PRIORITY_DHCP_RULE = 42000;
@@ -90,11 +88,10 @@
public static final int PRIORITY_CT_RULE = 32000;
public static final int PRIORITY_CT_DROP_RULE = 32500;
public static final int PRIORITY_ARP_GATEWAY_RULE = 41000;
- public static final int PRIORITY_ARP_SUBNET_RULE = 40000;
public static final int PRIORITY_ARP_CONTROL_RULE = 40000;
public static final int PRIORITY_ARP_REPLY_RULE = 40000;
public static final int PRIORITY_ARP_REQUEST_RULE = 40000;
- public static final int PRIORITY_ARP_FLOOD_RULE = 39000;
+ public static final int PRIORITY_ARP_GROUP_RULE = 39000;
public static final int PRIORITY_FORCED_ACL_RULE = 50000;
public static final int PRIORITY_ICMP_PROBE_RULE = 50000;
diff --git a/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackGroupRuleService.java b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackGroupRuleService.java
new file mode 100644
index 0000000..4a0df58
--- /dev/null
+++ b/apps/openstacknetworking/api/src/main/java/org/onosproject/openstacknetworking/api/OpenstackGroupRuleService.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019-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.api;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupDescription;
+
+import java.util.List;
+
+/**
+ * Service for setting group rules.
+ */
+public interface OpenstackGroupRuleService {
+
+ /**
+ * Configures the group table rule.
+ *
+ * @param appId application ID
+ * @param deviceId device ID
+ * @param groupId group ID
+ * @param type group type
+ * @param buckets a list of group buckets
+ * @param install true for rule addition, false for rule removal
+ */
+ void setRule(ApplicationId appId, DeviceId deviceId, int groupId,
+ GroupDescription.Type type, List<GroupBucket> buckets, boolean install);
+
+ /**
+ * Checks whether has the group in store with given device ID and group ID.
+ *
+ * @param deviceId device ID
+ * @param groupId group ID
+ * @return true if the group exists, false otherwise
+ */
+ boolean hasGroup(DeviceId deviceId, int groupId);
+
+ /**
+ * Configures buckets to the existing group.
+ * With install flag true, this method will add buckets to existing buckets,
+ * while with install flag false, this method will remove buckets from
+ * existing buckets.
+ *
+ * @param appId application ID
+ * @param deviceId device ID
+ * @param groupId group ID
+ * @param buckets a list of group buckets
+ * @param install true for buckets addition, false for buckets removal
+ */
+ void setBuckets(ApplicationId appId, DeviceId deviceId, int groupId,
+ List<GroupBucket> buckets, boolean install);
+
+ /**
+ * Configures buckets.
+ *
+ * @param appId application ID
+ * @param deviceId device ID
+ * @param groupId group ID
+ * @param buckets a lit of group buckets
+ */
+ void setBuckets(ApplicationId appId, DeviceId deviceId, int groupId,
+ List<GroupBucket> buckets);
+}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackGroupRuleManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackGroupRuleManager.java
new file mode 100644
index 0000000..e3af2c1
--- /dev/null
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackGroupRuleManager.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019-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.impl;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupService;
+import org.onosproject.openstacknetworking.api.OpenstackGroupRuleService;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getGroupKey;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Sets group table rules directly using GroupService.
+ */
+@Component(immediate = true, service = OpenstackGroupRuleService.class)
+public class OpenstackGroupRuleManager implements OpenstackGroupRuleService {
+
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected GroupService groupService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected CoreService coreService;
+
+ @Activate
+ protected void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public void setRule(ApplicationId appId, DeviceId deviceId, int groupId,
+ GroupDescription.Type type, List<GroupBucket> buckets,
+ boolean install) {
+ if (install) {
+ GroupDescription groupDesc = new DefaultGroupDescription(deviceId,
+ type, new GroupBuckets(buckets), getGroupKey(groupId), groupId, appId);
+ groupService.addGroup(groupDesc);
+ log.info("Adding group rule {}", groupId);
+ } else {
+ groupService.removeGroup(deviceId, getGroupKey(groupId), appId);
+ log.info("Removing group rule {}", groupId);
+ }
+ }
+
+ @Override
+ public boolean hasGroup(DeviceId deviceId, int groupId) {
+ return groupService.getGroup(deviceId, getGroupKey(groupId)) != null;
+ }
+
+ @Override
+ public void setBuckets(ApplicationId appId, DeviceId deviceId,
+ int groupId, List<GroupBucket> buckets, boolean install) {
+ if (install) {
+ groupService.addBucketsToGroup(deviceId, getGroupKey(groupId),
+ new GroupBuckets(buckets), getGroupKey(groupId), appId);
+ log.info("Adding buckets for group rule {}", groupId);
+ } else {
+ groupService.removeBucketsFromGroup(deviceId, getGroupKey(groupId),
+ new GroupBuckets(buckets), getGroupKey(groupId), appId);
+ log.info("Removing buckets for group rule {}", groupId);
+ }
+ }
+
+ @Override
+ public void setBuckets(ApplicationId appId, DeviceId deviceId,
+ int groupId, List<GroupBucket> buckets) {
+ groupService.setBucketsForGroup(deviceId, getGroupKey(groupId),
+ new GroupBuckets(buckets), getGroupKey(groupId), appId);
+ }
+}
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 a4e817f..8c6d1d9 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
@@ -15,6 +15,7 @@
*/
package org.onosproject.openstacknetworking.impl;
+import com.google.common.collect.Lists;
import org.onlab.packet.ARP;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
@@ -30,6 +31,7 @@
import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.core.GroupId;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.PortNumber;
@@ -38,6 +40,7 @@
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
@@ -47,6 +50,7 @@
import org.onosproject.openstacknetworking.api.InstancePortListener;
import org.onosproject.openstacknetworking.api.InstancePortService;
import org.onosproject.openstacknetworking.api.OpenstackFlowRuleService;
+import org.onosproject.openstacknetworking.api.OpenstackGroupRuleService;
import org.onosproject.openstacknetworking.api.OpenstackNetwork.Type;
import org.onosproject.openstacknetworking.api.OpenstackNetworkEvent;
import org.onosproject.openstacknetworking.api.OpenstackNetworkListener;
@@ -71,6 +75,7 @@
import java.nio.ByteBuffer;
import java.util.Dictionary;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
@@ -79,13 +84,14 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
+import static org.onosproject.net.group.GroupDescription.Type.ALL;
import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
import static org.onosproject.openstacknetworking.api.Constants.ARP_PROXY_MODE;
import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
-import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_FLOOD_RULE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GROUP_RULE;
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.InstancePort.State.ACTIVE;
@@ -102,6 +108,7 @@
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.openstacknetworking.util.RulePopulatorUtil.buildGroupBucket;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildMoveArpShaToThaExtension;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildMoveArpSpaToTpaExtension;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildMoveEthSrcToDstExtension;
@@ -131,6 +138,9 @@
protected OpenstackFlowRuleService osFlowRuleService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected OpenstackGroupRuleService osGroupRuleService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
protected ComponentConfigService configService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -417,9 +427,11 @@
case GRE:
case GENEVE:
setRemoteArpRequestRuleForTunnel(port, install);
+ setLocalArpRequestRuleForVnet(port, install);
break;
case VLAN:
setArpRequestRuleForVlan(port, install);
+ setLocalArpRequestRuleForVnet(port, install);
break;
default:
break;
@@ -454,7 +466,7 @@
}
/**
- * Installs flow rules to match ARP request packets only for VxLAN.
+ * Installs flow rules at remote node to match ARP request packets for Tunnel.
*
* @param port instance port
* @param install installation flag
@@ -476,6 +488,22 @@
}
/**
+ * Installs flow rules at local node to matchA RP request packets for Tunnel.
+ *
+ * @param port instance port
+ * @param install installation flag
+ */
+ private void setLocalArpRequestRuleForVnet(InstancePort port, boolean install) {
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder()
+ .setOutput(port.portNumber());
+
+ List<GroupBucket> bkts = Lists.newArrayList();
+ bkts.add(buildGroupBucket(tBuilder.build(), ALL, (short) -1));
+ osGroupRuleService.setBuckets(appId, port.deviceId(),
+ port.networkId().hashCode(), bkts, install);
+ }
+
+ /**
* Installs flow rules to match ARP request packets for VLAN.
*
* @param port instance port
@@ -761,6 +789,43 @@
}
}
+ // a helper method
+ private void setBaseVnetArpRuleForBroadcastMode(OpenstackNode osNode,
+ String segId, String netId,
+ boolean isTunnel,
+ boolean install) {
+
+ // add group rule
+ int groupId = netId.hashCode();
+ osGroupRuleService.setRule(appId, osNode.intgBridge(), groupId,
+ ALL, Lists.newArrayList(), install);
+
+ // add flow rule
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+ .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+ .matchArpOp(ARP.OP_REQUEST);
+
+ if (isTunnel) {
+ sBuilder.matchTunnelId(Long.parseLong(segId));
+ } else {
+ sBuilder.matchVlanId(VlanId.vlanId(segId));
+ }
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .group(GroupId.valueOf(netId.hashCode()))
+ .build();
+
+ osFlowRuleService.setRule(
+ appId,
+ osNode.intgBridge(),
+ sBuilder.build(),
+ treatment,
+ PRIORITY_ARP_GROUP_RULE,
+ ARP_TABLE,
+ install
+ );
+ }
+
/**
* Extracts properties from the component configuration context.
*
@@ -795,35 +860,6 @@
}
}
- 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
@@ -915,14 +951,18 @@
&& netType != NetworkType.VLAN) {
String segId = osNetworkService.segmentId(netId);
osNodeService.completeNodes(COMPUTE)
- .forEach(node -> setBaseVnetArpRuleForBroadcastMode(
- node, segId, true, install));
+ .forEach(node -> {
+ setBaseVnetArpRuleForBroadcastMode(node, segId,
+ netId, true, install);
+ });
}
if (netType == NetworkType.VLAN) {
String segId = osNetworkService.segmentId(netId);
osNodeService.completeNodes(COMPUTE)
- .forEach(node -> setBaseVnetArpRuleForBroadcastMode(
- node, segId, false, install));
+ .forEach(node -> {
+ setBaseVnetArpRuleForBroadcastMode(
+ node, segId, netId, false, install);
+ });
}
}
}
@@ -1042,19 +1082,17 @@
osNetworkService.networkType(nid) == GENEVE)
.forEach(nid -> {
String segId = osNetworkService.segmentId(nid);
- setBaseVnetArpRuleForBroadcastMode(osNode, segId, true, install);
+ setBaseVnetArpRuleForBroadcastMode(osNode, segId, nid, true, install);
});
netIds.stream()
.filter(nid -> osNetworkService.networkType(nid) == VLAN)
.forEach(nid -> {
String segId = osNetworkService.segmentId(nid);
- setBaseVnetArpRuleForBroadcastMode(osNode, segId, false, install);
+ setBaseVnetArpRuleForBroadcastMode(osNode, segId, nid, false, install);
});
}
-
-
private void setAllArpRules(OpenstackNode osNode, boolean install) {
if (ARP_BROADCAST_MODE.equals(getArpMode())) {
instancePortService.instancePorts().stream()
@@ -1064,6 +1102,8 @@
setArpRequestRule(p, install);
setArpReplyRule(p, install);
});
+ } else {
+ // we do nothing for proxy mode
}
}
}
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 40d07f5..8837a65 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
@@ -56,6 +56,8 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupKey;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.PacketService;
import org.onosproject.openstacknetworking.api.Constants.VnicType;
@@ -1321,6 +1323,16 @@
}
/**
+ * Obtains flow group key from the given id.
+ *
+ * @param groupId flow group identifier
+ * @return flow group key
+ */
+ public static GroupKey getGroupKey(int groupId) {
+ return new DefaultGroupKey((Integer.toString(groupId)).getBytes());
+ }
+
+ /**
* Builds up and a complete endpoint URL from gateway node.
*
* @param node gateway node
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
index bc7ecba..de5295c 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/util/RulePopulatorUtil.java
@@ -25,11 +25,15 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.ExtensionSelector;
import org.onosproject.net.flow.criteria.ExtensionSelectorType;
import org.onosproject.net.flow.instructions.ExtensionPropertyException;
import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupDescription;
import org.slf4j.Logger;
import java.util.ArrayList;
@@ -226,6 +230,32 @@
}
/**
+ * Returns the group bucket with given traffic treatment and group type.
+ *
+ * @param treatment traffic treatment
+ * @param type group type
+ * @param weight weight (only for select type)
+ * @return group bucket
+ */
+ public static GroupBucket buildGroupBucket(TrafficTreatment treatment,
+ GroupDescription.Type type, short weight) {
+ switch (type) {
+ case ALL:
+ return DefaultGroupBucket.createAllGroupBucket(treatment);
+ case SELECT:
+ if (weight == -1) {
+ return DefaultGroupBucket.createSelectGroupBucket(treatment);
+ } else {
+ return DefaultGroupBucket.createSelectGroupBucket(treatment, weight);
+ }
+ case INDIRECT:
+ return DefaultGroupBucket.createIndirectGroupBucket(treatment);
+ default:
+ return null;
+ }
+ }
+
+ /**
* Returns the nicira push extension treatment.
*
* @param device device instance