Merge remote-tracking branch 'origin/master' into dev-karaf-4.2.1
Change-Id: If611105632e508cb17352c6f5b1cbcfd85f716d1
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 123cacc..ead7234 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
@@ -84,6 +84,7 @@
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_FORCED_ACL_RULE = 50000;
public static final int PRIORITY_ICMP_PROBE_RULE = 50000;
@@ -94,9 +95,10 @@
public static final int STAT_FLAT_OUTBOUND_TABLE = 10;
public static final int VTAP_FLAT_OUTBOUND_TABLE = 11;
public static final int VTAP_FLAT_OUTBOUND_MIRROR_TABLE = 12;
- public static final int DHCP_ARP_TABLE = 5;
+ public static final int DHCP_TABLE = 5;
public static final int FLAT_TABLE = 20;
public static final int VTAG_TABLE = 30;
+ public static final int ARP_TABLE = 35;
public static final int ACL_TABLE = 40;
public static final int CT_TABLE = 41;
public static final int JUMP_TABLE = 50;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java
index 845c258..0a527e0 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java
@@ -35,7 +35,7 @@
import java.util.Optional;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FORCED_ACL_RULE;
@@ -121,7 +121,7 @@
sBuilder.build(),
treatment,
PRIORITY_FORCED_ACL_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
true);
}
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java
index 37a6b9c..70a2347 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java
@@ -35,7 +35,7 @@
import java.util.Optional;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FORCED_ACL_RULE;
@@ -118,7 +118,7 @@
sBuilder.build(),
treatment,
PRIORITY_FORCED_ACL_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
false);
}
}
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 2ea7400..0dc4db7 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
@@ -198,11 +198,18 @@
protected void initializePipeline(DeviceId deviceId) {
// for inbound table transition
connectTables(deviceId, Constants.STAT_INBOUND_TABLE, Constants.VTAP_INBOUND_TABLE);
- connectTables(deviceId, Constants.VTAP_INBOUND_TABLE, Constants.DHCP_ARP_TABLE);
+ connectTables(deviceId, Constants.VTAP_INBOUND_TABLE, Constants.DHCP_TABLE);
- // for vTag and ACL table transition
- connectTables(deviceId, Constants.DHCP_ARP_TABLE, Constants.VTAG_TABLE);
- connectTables(deviceId, Constants.VTAG_TABLE, Constants.ACL_TABLE);
+ // for DHCP and vTag table transition
+ connectTables(deviceId, Constants.DHCP_TABLE, Constants.VTAG_TABLE);
+
+ // for vTag and ARP table transition
+ connectTables(deviceId, Constants.VTAG_TABLE, Constants.ARP_TABLE);
+
+ // for ARP and ACL table transition
+ connectTables(deviceId, Constants.ARP_TABLE, Constants.ACL_TABLE);
+
+ // for ACL and JUMP table transition
connectTables(deviceId, Constants.ACL_TABLE, Constants.JUMP_TABLE);
// for JUMP table transition
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
index 995bb21..dd476de 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
@@ -77,7 +77,7 @@
import java.util.Objects;
import java.util.Set;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_DHCP_RULE;
import static org.onosproject.openstacknetworking.impl.OpenstackMetadataProxyHandler.Http.Type.RESPONSE;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.hmacEncrypt;
@@ -572,7 +572,7 @@
selector,
treatment,
PRIORITY_DHCP_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
install);
}
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index f1f1370..b2cb36e 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -788,9 +788,9 @@
break;
case OPENSTACK_INSTANCE_MIGRATION_ENDED:
- InstancePort revisedInstPort = swapStaleLocation(event.subject());
+ InstancePort oldInstPort = swapStaleLocation(event.subject());
- fip = associatedFloatingIp(revisedInstPort, ips);
+ fip = associatedFloatingIp(oldInstPort, ips);
if (fip == null) {
return;
@@ -805,7 +805,13 @@
throw new IllegalStateException(errorFormat);
}
- // If we only have one gateway, we simply do not remove any
+ eventExecutor.execute(() -> {
+ // We need to remove the old ComputeNodeToGateway rules from
+ // original compute node
+ setComputeNodeToGatewayHelper(oldInstPort, osNet, gateways, false);
+ });
+
+ // If we only have one gateway, we simply do not remove any
// flow rules from either gateway or compute node
if (gateways.size() == 1) {
return;
@@ -817,7 +823,7 @@
// it has been overwritten at port detention event
// if it is false, we will remove the rules
DeviceId newDeviceId = event.subject().deviceId();
- DeviceId oldDeviceId = revisedInstPort.deviceId();
+ DeviceId oldDeviceId = oldInstPort.deviceId();
OpenstackNode oldGateway = getGwByComputeDevId(gateways, oldDeviceId);
OpenstackNode newGateway = getGwByComputeDevId(gateways, newDeviceId);
@@ -827,15 +833,10 @@
}
eventExecutor.execute(() -> {
-
- // We need to remove the old ComputeNodeToGateway rules from
- // original compute node
- setComputeNodeToGatewayHelper(revisedInstPort, osNet, gateways, false);
-
// Since DownstreamExternal rules should only be placed in
// corresponding gateway node, we need to remove old rule from
// the corresponding gateway node
- setDownstreamExternalRulesHelper(fip, osNet, revisedInstPort,
+ setDownstreamExternalRulesHelper(fip, osNet, oldInstPort,
externalPeerRouter, gateways, false);
});
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 c1ea3cd..c78134d 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
@@ -74,15 +74,15 @@
import static com.google.common.base.Preconditions.checkNotNull;
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.DEFAULT_ARP_MODE_STR;
import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_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_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.api.InstancePort.State.ACTIVE;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
@@ -323,7 +323,7 @@
selector,
treatment,
PRIORITY_ARP_GATEWAY_RULE,
- DHCP_ARP_TABLE,
+ ARP_TABLE,
install
)
);
@@ -334,7 +334,7 @@
selector,
treatment,
PRIORITY_ARP_GATEWAY_RULE,
- DHCP_ARP_TABLE,
+ ARP_TABLE,
install
);
}
@@ -395,10 +395,13 @@
OpenstackNode localNode = osNodeService.node(port.deviceId());
+ String segId = osNetworkService.segmentId(port.networkId());
+
TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthType(EthType.EtherType.ARP.ethType().toShort())
.matchArpOp(ARP.OP_REQUEST)
.matchArpTpa(port.ipAddress().getIp4Address())
+ .matchTunnelId(Long.valueOf(segId))
.build();
setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
@@ -449,7 +452,7 @@
selector,
treatment,
PRIORITY_ARP_REPLY_RULE,
- DHCP_ARP_TABLE,
+ ARP_TABLE,
install
);
@@ -478,7 +481,7 @@
selector,
treatmentToRemote,
PRIORITY_ARP_REQUEST_RULE,
- DHCP_ARP_TABLE,
+ ARP_TABLE,
install
);
}
@@ -501,7 +504,7 @@
selector,
treatmentToRemote,
PRIORITY_ARP_REQUEST_RULE,
- DHCP_ARP_TABLE,
+ ARP_TABLE,
install);
}
}
@@ -674,7 +677,7 @@
selector,
treatment,
PRIORITY_ARP_CONTROL_RULE,
- DHCP_ARP_TABLE,
+ ARP_TABLE,
install
);
}
@@ -694,8 +697,8 @@
osNode.intgBridge(),
selector,
treatment,
- PRIORITY_ARP_SUBNET_RULE,
- DHCP_ARP_TABLE,
+ PRIORITY_ARP_FLOOD_RULE,
+ ARP_TABLE,
install
);
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java
index efd10d9..ca322ea 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java
@@ -85,7 +85,7 @@
import static org.onlab.packet.DHCP.MsgType.DHCPACK;
import static org.onlab.packet.DHCP.MsgType.DHCPOFFER;
import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_DHCP_RULE;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
import static org.slf4j.LoggerFactory.getLogger;
@@ -577,7 +577,7 @@
selector,
treatment,
PRIORITY_DHCP_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
install);
}
}
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index 3ac981a..b348d49 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -24,6 +24,8 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onlab.packet.VlanId;
+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;
@@ -56,12 +58,15 @@
import org.slf4j.Logger;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
+import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
@@ -74,6 +79,7 @@
import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
@@ -89,6 +95,7 @@
private final Logger log = getLogger(getClass());
+ private static final String ARP_MODE = "arpMode";
private static final String ERR_SET_FLOWS_VNI = "Failed to set flows for %s: Failed to get VNI for %s";
@Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -107,6 +114,10 @@
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
+ protected ComponentConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY)
+
protected LeadershipService leadershipService;
@Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -162,12 +173,22 @@
NetworkType type = osNetworkService.network(instPort.networkId()).getNetworkType();
switch (type) {
case VXLAN:
- setTunnelTagFlowRules(instPort, install);
+ setTunnelTagIpFlowRules(instPort, install);
setForwardingRulesForVxlan(instPort, install);
+
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+ setTunnelTagArpFlowRules(instPort, install);
+ }
+
break;
case VLAN:
- setVlanTagFlowRules(instPort, install);
+ setVlanTagIpFlowRules(instPort, install);
setForwardingRulesForVlan(instPort, install);
+
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+ setVlanTagArpFlowRules(instPort, install);
+ }
+
break;
case FLAT:
setFlatJumpRules(instPort, install);
@@ -190,10 +211,20 @@
switch (type) {
case VXLAN:
- setTunnelTagFlowRules(instPort, false);
+ setTunnelTagIpFlowRules(instPort, false);
+
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+ setTunnelTagArpFlowRules(instPort, false);
+ }
+
break;
case VLAN:
- setVlanTagFlowRules(instPort, false);
+ setVlanTagIpFlowRules(instPort, false);
+
+ if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+ setVlanTagArpFlowRules(instPort, false);
+ }
+
break;
case FLAT:
setFlatJumpRules(instPort, false);
@@ -219,7 +250,7 @@
selector.build(),
treatment.build(),
PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
install);
Network network = osNetworkService.network(port.networkId());
@@ -247,7 +278,7 @@
selector.build(),
treatment.build(),
PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
install);
selector = DefaultTrafficSelector.builder();
@@ -261,7 +292,7 @@
selector.build(),
treatment.build(),
PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
- DHCP_ARP_TABLE,
+ DHCP_TABLE,
install);
}
@@ -446,18 +477,27 @@
});
}
+ private void setTunnelTagArpFlowRules(InstancePort instPort, boolean install) {
+ setTunnelTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
+ }
+
+ private void setTunnelTagIpFlowRules(InstancePort instPort, boolean install) {
+ setTunnelTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
+ }
+
/**
* Configures the flow rule which is for using VXLAN to tag the packet
* based on the in_port number of a virtual instance.
- * Note that this rule will be inserted in VNI table (table 0).
+ * Note that this rule will be inserted in vTag table.
*
* @param instPort instance port object
* @param install install flag, add the rule if true, remove it otherwise
*/
- private void setTunnelTagFlowRules(InstancePort instPort, boolean install) {
+ private void setTunnelTagFlowRules(InstancePort instPort,
+ short ethType,
+ boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
- // TODO: need to handle IPv6 in near future
- .matchEthType(Ethernet.TYPE_IPV4)
+ .matchEthType(ethType)
.matchInPort(instPort.portNumber())
.build();
@@ -469,9 +509,9 @@
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
.setTunnelId(getVni(instPort))
- .transition(ACL_TABLE);
+ .transition(ARP_TABLE);
- if (securityGroupService.isSecurityGroupEnabled()) {
+ if (securityGroupService.isSecurityGroupEnabled() && ethType == Ethernet.TYPE_IPV4) {
tb.extension(ctTreatment, instPort.deviceId());
}
@@ -485,18 +525,27 @@
install);
}
+ private void setVlanTagIpFlowRules(InstancePort instPort, boolean install) {
+ setVlanTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
+ }
+
+ private void setVlanTagArpFlowRules(InstancePort instPort, boolean install) {
+ setVlanTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
+ }
+
/**
* Configures the flow rule which is for using VLAN to tag the packet
* based on the in_port number of a virtual instance.
- * Note that this rule will be inserted in VNI table (table 0).
+ * Note that this rule will be inserted in vTag table.
*
* @param instPort instance port object
* @param install install flag, add the rule if true, remove it otherwise
*/
- private void setVlanTagFlowRules(InstancePort instPort, boolean install) {
+ private void setVlanTagFlowRules(InstancePort instPort,
+ short ethType,
+ boolean install) {
TrafficSelector selector = DefaultTrafficSelector.builder()
- // TODO: need to handle IPv6 in near future
- .matchEthType(Ethernet.TYPE_IPV4)
+ .matchEthType(ethType)
.matchInPort(instPort.portNumber())
.build();
@@ -637,6 +686,11 @@
return Long.valueOf(osNet.getProviderSegID());
}
+ private String getArpMode() {
+ Set<ConfigProperty> properties = configService.getProperties(OpenstackSwitchingArpHandler.class.getName());
+ return getPropertyValue(properties, ARP_MODE);
+ }
+
/**
* An internal instance port listener which listens the port events generated
* from VM. The corresponding L2 forwarding rules will be generated and
diff --git a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java
index e3e449b..d1410b2 100644
--- a/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java
+++ b/apps/openstacknetworking/app/src/test/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManagerTest.java
@@ -45,7 +45,8 @@
import static org.junit.Assert.assertEquals;
import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.JUMP_TABLE;
@@ -187,13 +188,14 @@
fros = Sets.newConcurrentHashSet();
target.initializePipeline(DEVICE_ID);
- assertEquals("Flow Rule size was not match", 11, fros.size());
+ assertEquals("Flow Rule size was not match", 12, fros.size());
Map<Integer, Integer> fromToTableMap = Maps.newConcurrentMap();
fromToTableMap.put(STAT_INBOUND_TABLE, VTAP_INBOUND_TABLE);
- fromToTableMap.put(VTAP_INBOUND_TABLE, DHCP_ARP_TABLE);
- fromToTableMap.put(DHCP_ARP_TABLE, VTAG_TABLE);
- fromToTableMap.put(VTAG_TABLE, ACL_TABLE);
+ fromToTableMap.put(VTAP_INBOUND_TABLE, DHCP_TABLE);
+ fromToTableMap.put(DHCP_TABLE, VTAG_TABLE);
+ fromToTableMap.put(VTAG_TABLE, ARP_TABLE);
+ fromToTableMap.put(ARP_TABLE, ACL_TABLE);
fromToTableMap.put(ACL_TABLE, JUMP_TABLE);
fromToTableMap.put(STAT_OUTBOUND_TABLE, VTAP_OUTBOUND_TABLE);
fromToTableMap.put(VTAP_OUTBOUND_TABLE, FORWARDING_TABLE);
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
index 92a1020..a4400f7 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/cli/OpenstackNodeListCommand.java
@@ -28,6 +28,7 @@
import java.util.Comparator;
import java.util.List;
+import static org.onosproject.openstacknode.util.OpenstackNodeUtil.getGwByComputeNode;
import static org.onosproject.openstacknode.util.OpenstackNodeUtil.prettyJson;
/**
@@ -38,7 +39,7 @@
description = "Lists all nodes registered in OpenStack node service")
public class OpenstackNodeListCommand extends AbstractShellCommand {
- private static final String FORMAT = "%-20s%-15s%-24s%-24s%-20s%-20s%-15s%s";
+ private static final String FORMAT = "%-20s%-15s%-24s%-24s%-20s%-20s%-15s%-15s%-15s";
@Override
protected void doExecute() {
@@ -50,7 +51,7 @@
print("%s", json(osNodes));
} else {
print(FORMAT, "Hostname", "Type", "Integration Bridge",
- "Management IP", "Data IP", "VLAN Intf", "Uplink Port", "State");
+ "Management IP", "Data IP", "VLAN Intf", "Uplink Port", "State", "SelectedGw");
for (OpenstackNode osNode : osNodes) {
print(FORMAT,
osNode.hostname(),
@@ -60,7 +61,8 @@
osNode.dataIp() != null ? osNode.dataIp() : "",
osNode.vlanIntf() != null ? osNode.vlanIntf() : "",
osNode.uplinkPort() != null ? osNode.uplinkPort() : "",
- osNode.state());
+ osNode.state(),
+ getGwByComputeNode(osNodeService.completeNodes(OpenstackNode.NodeType.GATEWAY), osNode));
}
print("Total %s nodes", osNodeService.nodes().size());
}
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
index 9a242bb..f3645d7 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
@@ -546,6 +546,12 @@
}
private void processOpenstackNodeRemoved(OpenstackNode osNode) {
+ OvsdbClientService client = getOvsdbClient(osNode, ovsdbPort, ovsdbController);
+ if (client == null) {
+ log.info("Failed to get ovsdb client");
+ return;
+ }
+
//delete physical interfaces from the node
removePhysicalInterface(osNode);
@@ -560,6 +566,17 @@
}
});
}
+
+ //delete tunnel bridge from the node
+ if (hasDpdkTunnelBridge(osNode)) {
+ client.dropBridge(TUNNEL_BRIDGE);
+ }
+
+ //delete integration bridge from the node
+ client.dropBridge(INTEGRATION_BRIDGE);
+
+ //disconnect ovsdb
+ client.disconnect();
}
/**
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java
index f19b8d5..b520b17 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/util/OpenstackNodeUtil.java
@@ -48,7 +48,11 @@
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import static org.onlab.util.Tools.get;
@@ -69,6 +73,7 @@
private static final String ZERO = "0";
private static final String DPDK_DEVARGS = "dpdk-devargs";
+ private static final String NOT_AVAILABLE = "N/A";
/**
* Prevents object installation from external.
@@ -290,6 +295,56 @@
}
/**
+ * Obtains the gateway node by openstack node. Note that the gateway
+ * node is determined by device's device identifier.
+ *
+ * @param gws a collection of gateway nodes
+ * @param openstackNode device identifier
+ * @return the hostname of selected gateway node
+ */
+ public static String getGwByComputeNode(Set<OpenstackNode> gws, OpenstackNode openstackNode) {
+ int numOfGw = gws.size();
+
+ if (numOfGw == 0) {
+ return NOT_AVAILABLE;
+ }
+
+ if (!openstackNode.type().equals(OpenstackNode.NodeType.COMPUTE)) {
+ return NOT_AVAILABLE;
+ }
+
+ int gwIndex = Math.abs(openstackNode.intgBridge().hashCode()) % numOfGw;
+
+ return getGwByIndex(gws, gwIndex).hostname();
+ }
+
+ /**
+ * Obtains gateway instance by giving index number.
+ *
+ * @param gws a collection of gateway nodes
+ * @param index index number
+ * @return gateway instance
+ */
+ private static OpenstackNode getGwByIndex(Set<OpenstackNode> gws, int index) {
+ Map<String, OpenstackNode> hashMap = new HashMap<>();
+ gws.forEach(gw -> hashMap.put(gw.hostname(), gw));
+ TreeMap<String, OpenstackNode> treeMap = new TreeMap<>(hashMap);
+ Iterator<String> iteratorKey = treeMap.keySet().iterator();
+
+ int intIndex = 0;
+ OpenstackNode gw = null;
+ while (iteratorKey.hasNext()) {
+ String key = iteratorKey.next();
+
+ if (intIndex == index) {
+ gw = treeMap.get(key);
+ }
+ intIndex++;
+ }
+ return gw;
+ }
+
+ /**
* Builds up and a complete endpoint URL from gateway node.
*
* @param node gateway node
diff --git a/apps/openstackvtap/app/src/main/java/org/onosproject/openstackvtap/impl/OpenstackVtapManager.java b/apps/openstackvtap/app/src/main/java/org/onosproject/openstackvtap/impl/OpenstackVtapManager.java
index d9a2ae3..a2c1a0a 100644
--- a/apps/openstackvtap/app/src/main/java/org/onosproject/openstackvtap/impl/OpenstackVtapManager.java
+++ b/apps/openstackvtap/app/src/main/java/org/onosproject/openstackvtap/impl/OpenstackVtapManager.java
@@ -108,7 +108,7 @@
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE;
import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.VTAP_FLAT_OUTBOUND_GROUP_TABLE;
@@ -185,7 +185,7 @@
private static final int PRIORITY_VTAP_OUTPUT_RULE = 1000;
private static final int PRIORITY_VTAP_OUTPUT_DROP = 0;
- private static final int INBOUND_NEXT_TABLE = DHCP_ARP_TABLE;
+ private static final int INBOUND_NEXT_TABLE = DHCP_TABLE;
private static final int FLAT_OUTBOUND_NEXT_TABLE = FLAT_TABLE;
private static final int OUTBOUND_NEXT_TABLE = FORWARDING_TABLE;
diff --git a/apps/openstackvtap/app/src/main/resources/app/view/openstackvtap/openstackvtap.js b/apps/openstackvtap/app/src/main/resources/app/view/openstackvtap/openstackvtap.js
index 9b20eb0..d38c849 100644
--- a/apps/openstackvtap/app/src/main/resources/app/view/openstackvtap/openstackvtap.js
+++ b/apps/openstackvtap/app/src/main/resources/app/view/openstackvtap/openstackvtap.js
@@ -219,68 +219,6 @@
return div;
}
- function addInput(tbody, type, id, label, value) {
- var tr = tbody.append('tr'),
- lab;
- if (typeof label === 'string') {
- lab = label.replace(/_/g, ' ');
- } else {
- lab = label;
- }
-
- tr.append('td').attr('class', 'label').text(lab + ' :');
-
- if (type == 'radio') {
- var td = tr.append('td');
- for(var index in value) {
- if(index == 0) {
- td.append('input').classed( type + '-input', true)
- .attr('type', type)
- .attr('value', value[index])
- .attr('name', label)
- .attr('id', id)
- .attr('checked', 'true');
- } else {
- td.append('input').classed( type + '-input', true)
- .attr('type', type)
- .attr('name', label)
- .attr('id', id)
- .attr('value', value[index]);
- }
- td.append('span').text(value[index]);
- }
- } else {
- tr.append('td').append('input').classed(type + '-input', true).attr('type', type)
- .attr('id', id).attr('value', value);
- }
- }
-
- function addButton(tr, callback, value) {
- tr.append('td').append('input').classed('button-input', true).attr('type', 'button')
- .attr('value', value).on('click', callback);
- }
-
- function makeButton(callback, text, keyName) {
- var cb = fs.isF(callback),
- key = fs.isS(keyName);
-
- function invoke() {
- cb && cb();
- }
-
- return createDiv('vtap-button')
- .text(text)
- .on('click', invoke);
- }
-
- function createDiv(cls) {
- var div = d3.select(document.createElement('div'));
- if (cls) {
- div.classed(cls, true);
- }
- return div;
- }
-
function displayVtap() {
$log.debug("sendEvent openstackVtapIsActivatedRequest: ", selectedItem);
wss.sendEvent(osvIsActReq, selectedItem);
diff --git a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java
index 2afbce0..8043ae7 100644
--- a/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java
+++ b/apps/p4-tutorial/pipeconf/src/main/java/org/onosproject/p4tutorial/pipeconf/PortStatisticsDiscoveryImpl.java
@@ -26,7 +26,7 @@
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.pi.model.PiCounterId;
import org.onosproject.net.pi.model.PiPipeconf;
-import org.onosproject.net.pi.runtime.PiCounterCellData;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.service.PiPipeconfService;
import org.onosproject.p4runtime.api.P4RuntimeClient;
@@ -95,7 +95,7 @@
});
// Query the device.
- Collection<PiCounterCellData> counterEntryResponse;
+ Collection<PiCounterCell> counterEntryResponse;
try {
counterEntryResponse = client.readCounterCells(counterCellIds, pipeconf).get();
} catch (InterruptedException | ExecutionException e) {
@@ -105,24 +105,24 @@
}
// Process response.
- counterEntryResponse.forEach(counterData -> {
- if (counterData.cellId().counterType() != INDIRECT) {
- log.warn("Invalid counter data type {}, skipping", counterData.cellId().counterType());
+ counterEntryResponse.forEach(counterCell -> {
+ if (counterCell.cellId().counterType() != INDIRECT) {
+ log.warn("Invalid counter data type {}, skipping", counterCell.cellId().counterType());
return;
}
- if (!portStatBuilders.containsKey(counterData.cellId().index())) {
- log.warn("Unrecognized counter index {}, skipping", counterData);
+ if (!portStatBuilders.containsKey(counterCell.cellId().index())) {
+ log.warn("Unrecognized counter index {}, skipping", counterCell);
return;
}
- DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(counterData.cellId().index());
- if (counterData.cellId().counterId().equals(INGRESS_COUNTER_ID)) {
- statsBuilder.setPacketsReceived(counterData.packets());
- statsBuilder.setBytesReceived(counterData.bytes());
- } else if (counterData.cellId().counterId().equals(EGRESS_COUNTER_ID)) {
- statsBuilder.setPacketsSent(counterData.packets());
- statsBuilder.setBytesSent(counterData.bytes());
+ DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(counterCell.cellId().index());
+ if (counterCell.cellId().counterId().equals(INGRESS_COUNTER_ID)) {
+ statsBuilder.setPacketsReceived(counterCell.data().packets());
+ statsBuilder.setBytesReceived(counterCell.data().bytes());
+ } else if (counterCell.cellId().counterId().equals(EGRESS_COUNTER_ID)) {
+ statsBuilder.setPacketsSent(counterCell.data().packets());
+ statsBuilder.setBytesSent(counterCell.data().bytes());
} else {
- log.warn("Unrecognized counter ID {}, skipping", counterData);
+ log.warn("Unrecognized counter ID {}, skipping", counterCell);
}
});
diff --git a/cli/src/main/java/org/onosproject/cli/net/PipeconfCommand.java b/cli/src/main/java/org/onosproject/cli/net/PipeconfCommand.java
new file mode 100644
index 0000000..e70d7eb
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/PipeconfCommand.java
@@ -0,0 +1,97 @@
+/*
+ * 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.cli.net;
+
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.service.PiPipeconfService;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+
+/**
+ * Query registered pipeconfs.
+ */
+@Command(scope = "onos", name = "pipeconfs",
+ description = "Query registered pipeconfs.")
+public class PipeconfCommand extends AbstractShellCommand {
+
+ protected PiPipeconfService piPipeconfService;
+
+ @Option(name = "-s", aliases = "--short",
+ description = "Print more succinct output for each pipeconf",
+ required = false, multiValued = false)
+ private boolean shortOutput = false;
+
+ @Override
+ protected void doExecute() {
+ piPipeconfService = get(PiPipeconfService.class);
+
+ for (PiPipeconf piPipeconf : piPipeconfService.getPipeconfs()) {
+ if (shortOutput) {
+ print("id=%s", piPipeconf.id().toString());
+ } else {
+ print("id=%s, behaviors=%s, extensions=%s", piPipeconf.id().toString(),
+ getBehaviors(piPipeconf), getExtensions(piPipeconf));
+ }
+ }
+ }
+
+ /**
+ * Get all behaviour of a pipeconf and converts a list of behaviour name to string.
+ *
+ * @param piPipeconf query PiPipeconf
+ *
+ * @return string of behaviour name list
+ */
+ private String getBehaviors(PiPipeconf piPipeconf) {
+ Collection<Class<? extends Behaviour>> behaviours = piPipeconf.behaviours();
+ ArrayList<String> result = new ArrayList<>();
+
+ for (Class<? extends Behaviour> behaviour:behaviours) {
+ result.add(behaviour.getSimpleName());
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Get all extension of a pipeconf and converts a list of extension
+ * name to string.
+ *
+ * @param piPipeconf query PiPipeconf
+ *
+ * @return string of extension name list
+ */
+ private String getExtensions(PiPipeconf piPipeconf) {
+ ArrayList<String> result = new ArrayList<>();
+
+ for (PiPipeconf.ExtensionType extensionType : PiPipeconf.ExtensionType.values()
+ ) {
+ if (piPipeconf.extension(extensionType).isPresent()) {
+ result.add(extensionType.name());
+ }
+ }
+
+ return result.toString();
+ }
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java b/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java
index 9d3ec69..1077b52 100644
--- a/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/TableStatisticsCommand.java
@@ -57,13 +57,13 @@
String uri = null;
private static final String FORMAT =
- " table=%s, active=%s, lookedup=%s, matched=%s";
+ " table=%s, active=%s, lookedup=%s, matched=%s, maxsize=%s";
+ private static final String NA = "N/A";
@Override
protected void doExecute() {
FlowRuleService flowService = get(FlowRuleService.class);
DeviceService deviceService = get(DeviceService.class);
-
SortedMap<Device, List<TableStatisticsEntry>> deviceTableStats =
getSortedTableStats(deviceService, flowService);
@@ -117,8 +117,9 @@
print("deviceId=%s, tableCount=%d", d.id(), empty ? 0 : tableStats.size());
if (!empty) {
for (TableStatisticsEntry t : tableStats) {
- print(FORMAT, t.tableId(), t.activeFlowEntries(),
- t.packetsLookedup(), t.packetsMatched());
+ print(FORMAT, t.table(), t.activeFlowEntries(),
+ t.hasPacketsLookedup() ? t.packetsLookedup() : NA, t.packetsMatched(),
+ t.hasMaxSize() ? t.maxSize() : NA);
}
}
}
@@ -131,7 +132,7 @@
* @return sorted table statistics list
*/
protected SortedMap<Device, List<TableStatisticsEntry>> getSortedTableStats(DeviceService deviceService,
- FlowRuleService flowService) {
+ FlowRuleService flowService) {
SortedMap<Device, List<TableStatisticsEntry>> deviceTableStats = new TreeMap<>(Comparators.ELEMENT_COMPARATOR);
List<TableStatisticsEntry> tableStatsList;
Iterable<Device> devices = uri == null ? deviceService.getDevices() :
@@ -144,4 +145,4 @@
return deviceTableStats;
}
-}
+}
\ No newline at end of file
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 99a458d..e67a8fb 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -718,6 +718,10 @@
</command>
-->
+ <command>
+ <action class="org.onosproject.cli.net.PipeconfCommand"/>
+ </command>
+
<!--virtual network commands -->
<command>
<action class="org.onosproject.cli.net.vnet.TenantListCommand"/>
diff --git a/core/api/src/main/java/org/onosproject/net/flow/DefaultTableStatisticsEntry.java b/core/api/src/main/java/org/onosproject/net/flow/DefaultTableStatisticsEntry.java
index 53423d3..bf34437 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/DefaultTableStatisticsEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/DefaultTableStatisticsEntry.java
@@ -24,10 +24,36 @@
public final class DefaultTableStatisticsEntry implements TableStatisticsEntry {
private final DeviceId deviceId;
- private final int tableId;
+ private final TableId tableId;
private final long activeFlowEntries;
private final long packetsLookedupCount;
private final long packetsMatchedCount;
+ private final long maxSize;
+ private static final Long NOT_PRESENT = (long) -1;
+
+ /**
+ * Default table statistics constructor.
+ *
+ * @param deviceId device identifier
+ * @param tableId index table identifier
+ * @param activeFlowEntries number of active flow entries in the table
+ * @param packetsLookedupCount number of packets looked up in table
+ * @param packetsMatchedCount number of packets that hit table
+ * @deprecated since 1.15, suggest using the Builder class.
+ */
+ @Deprecated
+ public DefaultTableStatisticsEntry(DeviceId deviceId,
+ int tableId,
+ long activeFlowEntries,
+ long packetsLookedupCount,
+ long packetsMatchedCount) {
+ this.deviceId = checkNotNull(deviceId);
+ this.tableId = IndexTableId.of(tableId);
+ this.activeFlowEntries = activeFlowEntries;
+ this.packetsLookedupCount = packetsLookedupCount;
+ this.packetsMatchedCount = packetsMatchedCount;
+ this.maxSize = NOT_PRESENT;
+ }
/**
* Default table statistics constructor.
@@ -37,17 +63,20 @@
* @param activeFlowEntries number of active flow entries in the table
* @param packetsLookedupCount number of packets looked up in table
* @param packetsMatchedCount number of packets that hit table
+ * @param maxSize maximum size of this table
*/
- public DefaultTableStatisticsEntry(DeviceId deviceId,
- int tableId,
- long activeFlowEntries,
- long packetsLookedupCount,
- long packetsMatchedCount) {
+ private DefaultTableStatisticsEntry(DeviceId deviceId,
+ TableId tableId,
+ long activeFlowEntries,
+ long packetsLookedupCount,
+ long packetsMatchedCount,
+ long maxSize) {
this.deviceId = checkNotNull(deviceId);
this.tableId = tableId;
this.activeFlowEntries = activeFlowEntries;
this.packetsLookedupCount = packetsLookedupCount;
this.packetsMatchedCount = packetsMatchedCount;
+ this.maxSize = maxSize;
}
@Override
@@ -61,6 +90,12 @@
@Override
public int tableId() {
+ return tableId.type() == TableId.Type.INDEX ? ((IndexTableId) tableId).id() : tableId.hashCode();
+ }
+
+ @Override
+ public TableId table() {
+ //TODO: this is a temporary method, should implement tableId() like this method.
return tableId;
}
@@ -83,4 +118,73 @@
public DeviceId deviceId() {
return deviceId;
}
-}
+
+ @Override
+ public long maxSize() {
+ return maxSize;
+ }
+
+ @Override
+ public boolean hasPacketsLookedup() {
+ return packetsLookedupCount == NOT_PRESENT ? false : true;
+ }
+
+ @Override
+ public boolean hasMaxSize() {
+ return maxSize == NOT_PRESENT ? false : true;
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private DeviceId deviceId;
+ private TableId tableId;
+ private Long activeFlowEntries;
+ private Long packetsMatchedCount;
+ private Long packetsLookedUpCount = NOT_PRESENT;
+ private Long maxSize = NOT_PRESENT;
+
+ public Builder withDeviceId(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ public Builder withTableId(TableId tableId) {
+ this.tableId = tableId;
+ return this;
+ }
+
+ public Builder withActiveFlowEntries(long activeFlowEntries) {
+ this.activeFlowEntries = activeFlowEntries;
+ return this;
+ }
+
+ public Builder withPacketsLookedUpCount(long packetsLookedUpCount) {
+ this.packetsLookedUpCount = packetsLookedUpCount;
+ return this;
+ }
+
+ public Builder withPacketsMatchedCount(long packetsMatchedCount) {
+ this.packetsMatchedCount = packetsMatchedCount;
+ return this;
+ }
+
+ public Builder withMaxSize(long maxSize) {
+ this.maxSize = maxSize;
+ return this;
+ }
+
+ public TableStatisticsEntry build() {
+ checkNotNull(deviceId, "DeviceId cannot be null");
+ checkNotNull(tableId, "TableId cannot be null");
+ checkNotNull(activeFlowEntries, "ActiveFlowEntries cannot be null");
+ checkNotNull(packetsMatchedCount, "PacketsMatchedCount cannot be null");
+
+ return new DefaultTableStatisticsEntry(deviceId, tableId, activeFlowEntries, packetsLookedUpCount,
+ packetsMatchedCount, maxSize);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/flow/TableStatisticsEntry.java b/core/api/src/main/java/org/onosproject/net/flow/TableStatisticsEntry.java
index 505d535..1b39146 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/TableStatisticsEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/TableStatisticsEntry.java
@@ -30,13 +30,21 @@
DeviceId deviceId();
/**
- * Returns the table number.
+ * Returns the integer table id.
*
- * @return table number
+ * @return integer table id
*/
+ @Deprecated
int tableId();
/**
+ * Returns the table id.
+ *
+ * @return table id
+ */
+ TableId table();
+
+ /**
* Returns the number of active flow entries in this table.
*
* @return the number of active flow entries
@@ -56,4 +64,26 @@
* @return the number of packets that successfully matched in the table
*/
long packetsMatched();
-}
+
+ /**
+ * Returns the maximum size of this table.
+ *
+ * @return the maximum size of this table
+ */
+ long maxSize();
+
+ /**
+ * To check whether packetLookedUp is present in this TableStatisticsEntry.
+ *
+ * @return true if packetLookedUp is present, otherwise false;
+ */
+ boolean hasPacketsLookedup();
+
+ /**
+ * To check whether maxSize is present in this TableStatisticsEntry.
+ *
+ * @return true if maxSize is present, otherwise false;
+ */
+ boolean hasMaxSize();
+
+}
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/net/pi/model/DefaultPiPipeconf.java b/core/api/src/main/java/org/onosproject/net/pi/model/DefaultPiPipeconf.java
index 7d9dd28..cff8248 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/model/DefaultPiPipeconf.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/DefaultPiPipeconf.java
@@ -17,11 +17,15 @@
package org.onosproject.net.pi.model;
import com.google.common.collect.ImmutableMap;
+import org.apache.commons.io.IOUtils;
import org.onosproject.net.driver.Behaviour;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
@@ -37,14 +41,16 @@
private final PiPipeconfId id;
private final PiPipelineModel pipelineModel;
+ private final long fingerprint;
private final Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours;
private final Map<ExtensionType, URL> extensions;
- private DefaultPiPipeconf(PiPipeconfId id, PiPipelineModel pipelineModel,
+ private DefaultPiPipeconf(PiPipeconfId id, PiPipelineModel pipelineModel, long fingerprint,
Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours,
Map<ExtensionType, URL> extensions) {
this.id = id;
this.pipelineModel = pipelineModel;
+ this.fingerprint = fingerprint;
this.behaviours = behaviours;
this.extensions = extensions;
}
@@ -60,6 +66,11 @@
}
@Override
+ public long fingerprint() {
+ return fingerprint;
+ }
+
+ @Override
public Collection<Class<? extends Behaviour>> behaviours() {
return behaviours.keySet();
}
@@ -175,8 +186,23 @@
public PiPipeconf build() {
checkNotNull(id);
checkNotNull(pipelineModel);
- return new DefaultPiPipeconf(id, pipelineModel, behaviourMapBuilder.build(), extensionMapBuilder.build());
+
+ Map<ExtensionType, URL> extensions = extensionMapBuilder.build();
+ return new DefaultPiPipeconf(id, pipelineModel, generateFingerprint(extensions),
+ behaviourMapBuilder.build(), extensions);
}
+ private long generateFingerprint(Map<ExtensionType, URL> extensions) {
+ Collection<Integer> hashArray = new ArrayList<>();
+ for (Map.Entry<ExtensionType, URL> pair : extensions.entrySet()) {
+ try {
+ hashArray.add(Arrays.hashCode(ByteBuffer.wrap(IOUtils.toByteArray(
+ pair.getValue().openStream())).array()));
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ return Arrays.hashCode(hashArray.toArray());
+ }
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java b/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java
index 5fedaf7..e3664e1 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/model/PiPipeconf.java
@@ -45,6 +45,13 @@
PiPipelineModel pipelineModel();
/**
+ * Returns the fingerprint of pipeconf.
+ *
+ * @return a fingerprint
+ */
+ long fingerprint();
+
+ /**
* Returns all pipeline-specific behaviour interfaces defined by this configuration.
*
* @return a collection of behaviours
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java
new file mode 100644
index 0000000..9508cbc
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCell.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2017-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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+/**
+ * Counter cell of a protocol-independent pipeline.
+ */
+@Beta
+public final class PiCounterCell {
+
+ private final PiCounterCellId cellId;
+ private final PiCounterCellData counterData;
+
+ /**
+ * Creates a new counter cell for the given cell identifier and counter cell data.
+ *
+ * @param cellId counter cell identifier
+ * @param piCounterCellData counter cell data
+ */
+ public PiCounterCell(PiCounterCellId cellId, PiCounterCellData piCounterCellData) {
+ this.cellId = cellId;
+ this.counterData = piCounterCellData;
+ }
+
+ /**
+ * Creates a new counter cell for the given cell identifier, number of packets and bytes.
+ *
+ * @param cellId counter cell identifier
+ * @param packets number of packets
+ * @param bytes number of bytes
+ */
+ public PiCounterCell(PiCounterCellId cellId, long packets, long bytes) {
+ this.cellId = cellId;
+ this.counterData = new PiCounterCellData(packets, bytes);
+ }
+
+ /**
+ * Returns the cell identifier.
+ *
+ * @return cell identifier
+ */
+ public PiCounterCellId cellId() {
+ return cellId;
+ }
+
+ /**
+ * Returns the data contained by this cell.
+ *
+ * @return counter cell data
+ */
+ public PiCounterCellData data() {
+ return counterData;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof PiCounterCell)) {
+ return false;
+ }
+ PiCounterCell that = (PiCounterCell) o;
+ return Objects.equal(cellId, that.cellId) &&
+ Objects.equal(counterData, that.counterData);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(cellId, counterData);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("cellId", cellId)
+ .add("counterData", counterData)
+ .toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCellData.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCellData.java
index f0aada5..b640970 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCellData.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiCounterCellData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-present Open Networking Foundation
+ * 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.
@@ -23,37 +23,26 @@
/**
* Data of a counter cell of a protocol-independent pipeline.
*/
+
@Beta
public final class PiCounterCellData {
- private final PiCounterCellId cellId;
private final long packets;
private final long bytes;
/**
- * Creates a new counter cell data for the given cell identifier, number of packets and bytes.
+ * Creates a new counter cell data for the given number of packets and bytes.
*
- * @param cellId counter cell identifier
- * @param packets number of packets
- * @param bytes number of bytes
+ * @param packets number of packets
+ * @param bytes number of bytes
*/
- public PiCounterCellData(PiCounterCellId cellId, long packets, long bytes) {
- this.cellId = cellId;
+ public PiCounterCellData(long packets, long bytes) {
this.packets = packets;
this.bytes = bytes;
}
/**
- * Returns the cell identifier.
- *
- * @return cell identifier
- */
- public PiCounterCellId cellId() {
- return cellId;
- }
-
- /**
- * Returns the packet count value contained by this cell.
+ * Returns the packet count value contained by this counter data.
*
* @return number of packets
*/
@@ -62,7 +51,7 @@
}
/**
- * Returns the byte count value contained by this cell.
+ * Returns the byte count value contained by this counter data.
*
* @return number of bytes
*/
@@ -80,19 +69,17 @@
}
PiCounterCellData that = (PiCounterCellData) o;
return packets == that.packets &&
- bytes == that.bytes &&
- Objects.equal(cellId, that.cellId);
+ bytes == that.bytes;
}
@Override
public int hashCode() {
- return Objects.hashCode(cellId, packets, bytes);
+ return Objects.hashCode(packets, bytes);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
- .add("cellId", cellId)
.add("packets", packets)
.add("bytes", bytes)
.toString();
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java
index f8a1460..ac73bbe 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiTableEntry.java
@@ -42,10 +42,11 @@
private final long cookie;
private final int priority;
private final double timeout;
+ private final PiCounterCellData counterData;
private PiTableEntry(PiTableId tableId, PiMatchKey matchKey,
PiTableAction tableAction, boolean isDefaultAction,
- long cookie, int priority, double timeout) {
+ long cookie, int priority, double timeout, PiCounterCellData data) {
this.tableId = tableId;
this.matchKey = matchKey;
this.tableAction = tableAction;
@@ -53,6 +54,7 @@
this.cookie = cookie;
this.priority = priority;
this.timeout = timeout;
+ this.counterData = data;
}
/**
@@ -125,6 +127,18 @@
return timeout == NO_TIMEOUT ? Optional.empty() : Optional.of(timeout);
}
+ /**
+ * Returns the data of the counter cell associated with this table entry.
+ * This method is meaningful only if the table entry was read from the
+ * infrastructure device and the table has direct counters, otherwise
+ * returns null.
+ *
+ * @return counter cell data
+ */
+ public PiCounterCellData counter() {
+ return counterData;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -197,6 +211,7 @@
private long cookie = 0;
private int priority = NO_PRIORITY;
private double timeout = NO_TIMEOUT;
+ private PiCounterCellData counterData;
private Builder() {
// Hides constructor.
@@ -272,6 +287,17 @@
}
/**
+ * Sets the counter cell data of this table entry.
+ *
+ * @param data counter cell data
+ * @return this
+ */
+ public Builder withCounterCellData(PiCounterCellData data) {
+ this.counterData = checkNotNull(data, "Counter cell data cannot be null");
+ return this;
+ }
+
+ /**
* Builds the table entry.
*
* @return a new table entry
@@ -281,7 +307,7 @@
checkNotNull(matchKey);
final boolean isDefaultAction = matchKey.equals(PiMatchKey.EMPTY);
return new PiTableEntry(tableId, matchKey, tableAction,
- isDefaultAction, cookie, priority, timeout);
+ isDefaultAction, cookie, priority, timeout, counterData);
}
}
}
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellDataTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellDataTest.java
index 6676470..bfb8782 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellDataTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellDataTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-present Open Networking Foundation
+ * 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.
@@ -18,48 +18,25 @@
import com.google.common.testing.EqualsTester;
import org.junit.Test;
-import org.onosproject.net.pi.model.PiActionId;
-import org.onosproject.net.pi.model.PiTableId;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
-import static org.onosproject.net.pi.runtime.PiConstantsTest.DROP;
/**
- * Unit tests for PiCounterCellData class.
+ * Unit tests for PiCounterData class.
*/
public class PiCounterCellDataTest {
- private static final PiTableEntry PI_TABLE_ENTRY_1 = PiTableEntry.builder()
- .forTable(PiTableId.of("T10"))
- .withCookie(0xac)
- .withPriority(10)
- .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
- .withTimeout(100)
- .build();
- private static final PiTableEntry PI_TABLE_ENTRY_2 = PiTableEntry.builder()
- .forTable(PiTableId.of("T20"))
- .withCookie(0xac)
- .withPriority(10)
- .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
- .withTimeout(1000)
- .build();
-
- private static final PiCounterCellId PI_COUNTER_CELL_ID_1 =
- PiCounterCellId.ofDirect(PI_TABLE_ENTRY_1);
- private static final PiCounterCellId PI_COUNTER_CELL_ID_2 =
- PiCounterCellId.ofDirect(PI_TABLE_ENTRY_2);
-
private static final long PACKETS_1 = 10;
private static final long PACKETS_2 = 20;
private static final long BYTES_1 = 100;
private static final long BYTES_2 = 200;
- private static final PiCounterCellData PI_COUNTER_CELL_DATA_1 =
- new PiCounterCellData(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
- private static final PiCounterCellData SAME_AS_PI_COUNTER_CELL_DATA_1 =
- new PiCounterCellData(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
- private static final PiCounterCellData PI_COUNTER_CELL_DATA_2 =
- new PiCounterCellData(PI_COUNTER_CELL_ID_2, PACKETS_2, BYTES_2);
+ private static final PiCounterCellData PI_COUNTER_DATA_1 =
+ new PiCounterCellData(PACKETS_1, BYTES_1);
+ private static final PiCounterCellData SAME_AS_PI_COUNTER_DATA_1 =
+ new PiCounterCellData(PACKETS_1, BYTES_1);
+ private static final PiCounterCellData PI_COUNTER_DATA_2 =
+ new PiCounterCellData(PACKETS_2, BYTES_2);
/**
* Checks that the PiCounterCellData class is immutable.
@@ -75,8 +52,8 @@
@Test
public void testEquals() {
new EqualsTester()
- .addEqualityGroup(PI_COUNTER_CELL_DATA_1, SAME_AS_PI_COUNTER_CELL_DATA_1)
- .addEqualityGroup(PI_COUNTER_CELL_DATA_2)
+ .addEqualityGroup(PI_COUNTER_DATA_1, SAME_AS_PI_COUNTER_DATA_1)
+ .addEqualityGroup(PI_COUNTER_DATA_2)
.testEquals();
}
}
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellTest.java
new file mode 100644
index 0000000..ab65efe
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiCounterCellTest.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2017-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.net.pi.runtime;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiActionId;
+import org.onosproject.net.pi.model.PiTableId;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onosproject.net.pi.runtime.PiConstantsTest.DROP;
+
+/**
+ * Unit tests for PiCounterCell class.
+ */
+public class PiCounterCellTest {
+
+ private static final PiTableEntry PI_TABLE_ENTRY_1 = PiTableEntry.builder()
+ .forTable(PiTableId.of("T10"))
+ .withCookie(0xac)
+ .withPriority(10)
+ .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
+ .withTimeout(100)
+ .build();
+ private static final PiTableEntry PI_TABLE_ENTRY_2 = PiTableEntry.builder()
+ .forTable(PiTableId.of("T20"))
+ .withCookie(0xac)
+ .withPriority(10)
+ .withAction(PiAction.builder().withId(PiActionId.of(DROP)).build())
+ .withTimeout(1000)
+ .build();
+
+ private static final PiCounterCellId PI_COUNTER_CELL_ID_1 =
+ PiCounterCellId.ofDirect(PI_TABLE_ENTRY_1);
+ private static final PiCounterCellId PI_COUNTER_CELL_ID_2 =
+ PiCounterCellId.ofDirect(PI_TABLE_ENTRY_2);
+
+ private static final long PACKETS_1 = 10;
+ private static final long PACKETS_2 = 20;
+ private static final long BYTES_1 = 100;
+ private static final long BYTES_2 = 200;
+
+ private static final PiCounterCell PI_COUNTER_CELL_1 =
+ new PiCounterCell(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
+ private static final PiCounterCell SAME_AS_PI_COUNTER_CELL_1 =
+ new PiCounterCell(PI_COUNTER_CELL_ID_1, PACKETS_1, BYTES_1);
+ private static final PiCounterCell PI_COUNTER_CELL_2 =
+ new PiCounterCell(PI_COUNTER_CELL_ID_2, PACKETS_2, BYTES_2);
+
+ /**
+ * Checks that the PiCounterCell class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PiCounterCell.class);
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(PI_COUNTER_CELL_1, SAME_AS_PI_COUNTER_CELL_1)
+ .addEqualityGroup(PI_COUNTER_CELL_2)
+ .testEquals();
+ }
+}
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/TableStatisticsEntryCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/TableStatisticsEntryCodec.java
index efd1d2c..f1af62b 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/TableStatisticsEntryCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/TableStatisticsEntryCodec.java
@@ -33,7 +33,7 @@
checkNotNull(entry, "Table Statistics entry cannot be null");
final ObjectNode result = context.mapper().createObjectNode()
- .put("tableId", entry.tableId())
+ .put("tableId", entry.table().toString())
.put("deviceId", entry.deviceId().toString())
.put("activeEntries", entry.activeFlowEntries())
.put("packetsLookedUp", entry.packetsLookedup())
@@ -43,4 +43,3 @@
}
}
-
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
index b6a5dbe..fa10d33 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiPipeconfManager.java
@@ -186,7 +186,7 @@
deviceId, BasicDeviceConfig.class);
if (basicDeviceConfig == null) {
log.warn("Unable to get basic device config for {}, " +
- "aborting pipeconf driver merge");
+ "aborting pipeconf driver merge", deviceId);
return null;
}
String baseDriverName = basicDeviceConfig.driver();
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 0e684fe..0fd964e 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -231,6 +231,7 @@
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiControlMetadata;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiEntity;
@@ -692,6 +693,7 @@
PiActionGroupMemberId.class,
PiActionParam.class,
PiControlMetadata.class,
+ PiCounterCell.class,
PiCounterCellData.class,
PiCounterCellId.class,
PiEntity.class,
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
index c5204ce..2521daf 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
@@ -692,6 +692,7 @@
MacAddress dstMac = readEthDstFromSelector(nextObj.meta());
if (dstMac != null && dstMac.isMulticast()) {
processL2MulticastNextObjective(nextObj);
+ return;
}
List<GroupInfo> groupInfos = prepareL2InterfaceGroup(nextObj, assignedVlan);
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
index d0acdee..5a233ef 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeFlowRuleProgrammable.java
@@ -31,6 +31,7 @@
import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.model.PiTableModel;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiTableEntry;
@@ -89,11 +90,11 @@
private static final String SUPPORT_TABLE_COUNTERS = "supportTableCounters";
private static final boolean DEFAULT_SUPPORT_TABLE_COUNTERS = true;
- // If true, we read all direct counters of a table with one request.
- // Otherwise, we send as many requests as the number of table entries.
- private static final String READ_ALL_DIRECT_COUNTERS = "tableReadAllDirectCounters";
- // FIXME: set to true as soon as the feature is implemented in P4Runtime.
- private static final boolean DEFAULT_READ_ALL_DIRECT_COUNTERS = false;
+ // If true, assumes that the device returns table entry message populated
+ // with direct counter values. If false, we issue a second P4Runtime request
+ // to read the direct counter values.
+ private static final String READ_COUNTERS_WITH_TABLE_ENTRIES = "tableReadCountersWithTableEntries";
+ private static final boolean DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES = true;
// For default entries, P4Runtime mandates that only MODIFY messages are
// allowed. If true, treats default entries as normal table entries,
@@ -153,7 +154,6 @@
// Synchronize mirror with the device state.
syncMirror(deviceEntries);
- // TODO: ONOS-7596 read counters with table entries
final Map<PiTableEntry, PiCounterCellData> counterCellMap =
readEntryCounters(deviceEntries);
// Forge flow entries with counter values.
@@ -461,25 +461,22 @@
return Collections.emptyMap();
}
- Collection<PiCounterCellData> cellDatas;
-
- if (driverBoolProperty(READ_ALL_DIRECT_COUNTERS,
- DEFAULT_READ_ALL_DIRECT_COUNTERS)) {
- // FIXME: read counters when dumping table entries ONOS-7596
- cellDatas = Collections.emptyList();
+ if (driverBoolProperty(READ_COUNTERS_WITH_TABLE_ENTRIES,
+ DEFAULT_READ_COUNTERS_WITH_TABLE_ENTRIES)) {
+ return tableEntries.stream().collect(Collectors.toMap(c -> c, PiTableEntry::counter));
} else {
+ Collection<PiCounterCell> cells;
Set<PiCounterCellId> cellIds = tableEntries.stream()
// Ignore counter for default entry.
.filter(e -> !e.isDefaultAction())
.filter(e -> tableHasCounter(e.table()))
.map(PiCounterCellId::ofDirect)
.collect(Collectors.toSet());
- cellDatas = getFutureWithDeadline(client.readCounterCells(cellIds, pipeconf),
+ cells = getFutureWithDeadline(client.readCounterCells(cellIds, pipeconf),
"reading table counters", Collections.emptyList());
+ return cells.stream()
+ .collect(Collectors.toMap(c -> c.cellId().tableEntry(), PiCounterCell::data));
}
- return cellDatas.stream()
- .collect(Collectors.toMap(c -> c.cellId().tableEntry(), c -> c));
-
}
private boolean tableHasCounter(PiTableId tableId) {
diff --git a/pipelines/basic/src/main/java/org/onosproject/pipelines/basic/PortStatisticsDiscoveryImpl.java b/pipelines/basic/src/main/java/org/onosproject/pipelines/basic/PortStatisticsDiscoveryImpl.java
index ec8d5cf..0e39230 100644
--- a/pipelines/basic/src/main/java/org/onosproject/pipelines/basic/PortStatisticsDiscoveryImpl.java
+++ b/pipelines/basic/src/main/java/org/onosproject/pipelines/basic/PortStatisticsDiscoveryImpl.java
@@ -28,7 +28,7 @@
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.pi.model.PiCounterId;
import org.onosproject.net.pi.model.PiPipeconf;
-import org.onosproject.net.pi.runtime.PiCounterCellData;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.service.PiPipeconfService;
import org.onosproject.p4runtime.api.P4RuntimeClient;
@@ -112,7 +112,7 @@
counterCellIds.add(PiCounterCellId.ofIndirect(egressCounterId(), p));
});
- Collection<PiCounterCellData> counterEntryResponse;
+ Collection<PiCounterCell> counterEntryResponse;
try {
counterEntryResponse = client.readCounterCells(counterCellIds, pipeconf).get();
} catch (InterruptedException | ExecutionException e) {
@@ -121,25 +121,25 @@
return Collections.emptyList();
}
- counterEntryResponse.forEach(counterData -> {
- if (counterData.cellId().counterType() != INDIRECT) {
- log.warn("Invalid counter data type {}, skipping", counterData.cellId().counterType());
+ counterEntryResponse.forEach(counterCell -> {
+ if (counterCell.cellId().counterType() != INDIRECT) {
+ log.warn("Invalid counter data type {}, skipping", counterCell.cellId().counterType());
return;
}
- PiCounterCellId indCellId = counterData.cellId();
+ PiCounterCellId indCellId = counterCell.cellId();
if (!portStatBuilders.containsKey(indCellId.index())) {
- log.warn("Unrecognized counter index {}, skipping", counterData);
+ log.warn("Unrecognized counter index {}, skipping", counterCell);
return;
}
DefaultPortStatistics.Builder statsBuilder = portStatBuilders.get(indCellId.index());
- if (counterData.cellId().counterId().equals(ingressCounterId())) {
- statsBuilder.setPacketsReceived(counterData.packets());
- statsBuilder.setBytesReceived(counterData.bytes());
- } else if (counterData.cellId().counterId().equals(egressCounterId())) {
- statsBuilder.setPacketsSent(counterData.packets());
- statsBuilder.setBytesSent(counterData.bytes());
+ if (counterCell.cellId().counterId().equals(ingressCounterId())) {
+ statsBuilder.setPacketsReceived(counterCell.data().packets());
+ statsBuilder.setBytesReceived(counterCell.data().bytes());
+ } else if (counterCell.cellId().counterId().equals(egressCounterId())) {
+ statsBuilder.setPacketsSent(counterCell.data().packets());
+ statsBuilder.setBytesSent(counterCell.data().bytes());
} else {
- log.warn("Unrecognized counter ID {}, skipping", counterData);
+ log.warn("Unrecognized counter ID {}, skipping", counterCell);
}
});
diff --git a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipeliner.java b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipeliner.java
index 7cd154b..7b3006d 100644
--- a/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipeliner.java
+++ b/pipelines/fabric/src/main/java/org/onosproject/pipelines/fabric/pipeliner/FabricPipeliner.java
@@ -242,6 +242,9 @@
}
FlowRuleOperations ops = buildFlowRuleOps(objective, flowRules);
+ if (ops == null) {
+ return;
+ }
flowRuleService.apply(ops);
flowRules.forEach(flow -> {
diff --git a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java
index 8c1d7d9..f30ec28 100644
--- a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java
@@ -25,7 +25,7 @@
import org.onosproject.net.pi.runtime.PiActionGroup;
import org.onosproject.net.pi.runtime.PiActionGroupMember;
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
-import org.onosproject.net.pi.runtime.PiCounterCellData;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
import org.onosproject.net.pi.runtime.PiMeterCellId;
@@ -178,7 +178,7 @@
* @param pipeconf pipeconf
* @return list of counter data
*/
- CompletableFuture<List<PiCounterCellData>> readAllCounterCells(
+ CompletableFuture<List<PiCounterCell>> readAllCounterCells(
Set<PiCounterId> counterIds, PiPipeconf pipeconf);
/**
@@ -189,7 +189,7 @@
* @param pipeconf pipeconf
* @return list of counter data
*/
- CompletableFuture<List<PiCounterCellData>> readCounterCells(
+ CompletableFuture<List<PiCounterCell>> readCounterCells(
Set<PiCounterCellId> cellIds, PiPipeconf pipeconf);
/**
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/CounterEntryCodec.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/CounterEntryCodec.java
index e883821..6c29062 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/CounterEntryCodec.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/CounterEntryCodec.java
@@ -20,7 +20,7 @@
import org.onosproject.net.pi.model.PiCounterType;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiTableId;
-import org.onosproject.net.pi.runtime.PiCounterCellData;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.slf4j.Logger;
@@ -135,8 +135,8 @@
* @param pipeconf pipeconf
* @return collection of PI counter cell data
*/
- static List<PiCounterCellData> decodeCounterEntities(List<Entity> entities,
- PiPipeconf pipeconf) {
+ static List<PiCounterCell> decodeCounterEntities(List<Entity> entities,
+ PiPipeconf pipeconf) {
final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
@@ -248,9 +248,9 @@
}
}
- private static PiCounterCellData decodeCounterEntity(Entity entity,
- PiPipeconf pipeconf,
- P4InfoBrowser browser)
+ private static PiCounterCell decodeCounterEntity(Entity entity,
+ PiPipeconf pipeconf,
+ P4InfoBrowser browser)
throws EncodeException, P4InfoBrowser.NotFoundException {
CounterData counterData;
@@ -276,8 +276,8 @@
entity.getEntityCase().name()));
}
- return new PiCounterCellData(piCellId,
- counterData.getPacketCount(),
- counterData.getByteCount());
+ return new PiCounterCell(piCellId,
+ counterData.getPacketCount(),
+ counterData.getByteCount());
}
}
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
index c291db4..a06d67e 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
@@ -43,7 +43,7 @@
import org.onosproject.net.pi.runtime.PiActionGroup;
import org.onosproject.net.pi.runtime.PiActionGroupMember;
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
-import org.onosproject.net.pi.runtime.PiCounterCellData;
+import org.onosproject.net.pi.runtime.PiCounterCell;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiMeterCellConfig;
import org.onosproject.net.pi.runtime.PiMeterCellId;
@@ -281,15 +281,15 @@
}
@Override
- public CompletableFuture<List<PiCounterCellData>> readCounterCells(Set<PiCounterCellId> cellIds,
- PiPipeconf pipeconf) {
+ public CompletableFuture<List<PiCounterCell>> readCounterCells(Set<PiCounterCellId> cellIds,
+ PiPipeconf pipeconf) {
return supplyInContext(() -> doReadCounterCells(Lists.newArrayList(cellIds), pipeconf),
"readCounterCells-" + cellIds.hashCode());
}
@Override
- public CompletableFuture<List<PiCounterCellData>> readAllCounterCells(Set<PiCounterId> counterIds,
- PiPipeconf pipeconf) {
+ public CompletableFuture<List<PiCounterCell>> readAllCounterCells(Set<PiCounterId> counterIds,
+ PiPipeconf pipeconf) {
return supplyInContext(() -> doReadAllCounterCells(Lists.newArrayList(counterIds), pipeconf),
"readAllCounterCells-" + counterIds.hashCode());
}
@@ -408,6 +408,11 @@
return null;
}
+ ForwardingPipelineConfig.Cookie pipeconfCookie = ForwardingPipelineConfig.Cookie
+ .newBuilder()
+ .setCookie(pipeconf.fingerprint())
+ .build();
+
// FIXME: This is specific to PI P4Runtime implementation.
P4Config.P4DeviceConfig p4DeviceConfigMsg = P4Config.P4DeviceConfig
.newBuilder()
@@ -420,6 +425,7 @@
.newBuilder()
.setP4Info(p4Info)
.setP4DeviceConfig(p4DeviceConfigMsg.toByteString())
+ .setCookie(pipeconfCookie)
.build();
}
@@ -428,6 +434,8 @@
GetForwardingPipelineConfigRequest request = GetForwardingPipelineConfigRequest
.newBuilder()
.setDeviceId(p4DeviceId)
+ .setResponseType(GetForwardingPipelineConfigRequest
+ .ResponseType.COOKIE_ONLY)
.build();
GetForwardingPipelineConfigResponse resp;
@@ -445,33 +453,14 @@
}
return false;
}
-
- ForwardingPipelineConfig expectedConfig = getPipelineConfig(
- pipeconf, deviceData);
-
- if (expectedConfig == null) {
- return false;
- }
- if (!resp.hasConfig()) {
+ if (!resp.getConfig().hasCookie()) {
log.warn("{} returned GetForwardingPipelineConfigResponse " +
- "with 'config' field unset",
+ "with 'cookie' field unset",
deviceId);
return false;
}
- if (resp.getConfig().getP4DeviceConfig().isEmpty()
- && !expectedConfig.getP4DeviceConfig().isEmpty()) {
- // Don't bother with a warn or error since we don't really allow
- // updating the pipeline to a different one. So the P4Info should be
- // enough for us.
- log.debug("{} returned GetForwardingPipelineConfigResponse " +
- "with empty 'p4_device_config' field, " +
- "equality will be based only on P4Info",
- deviceId);
- return resp.getConfig().getP4Info().equals(
- expectedConfig.getP4Info());
- } else {
- return resp.getConfig().equals(expectedConfig);
- }
+
+ return resp.getConfig().getCookie().getCookie() == pipeconf.fingerprint();
}
private boolean doSetPipelineConfig(PiPipeconf pipeconf, ByteBuffer deviceData) {
@@ -570,6 +559,7 @@
TableEntry.newBuilder()
.setTableId(tableId)
.setIsDefaultAction(defaultEntries)
+ .setCounterData(P4RuntimeOuterClass.CounterData.getDefaultInstance())
.build())
.build())
.build());
@@ -662,21 +652,21 @@
isClientMaster.set(isMaster);
}
- private List<PiCounterCellData> doReadAllCounterCells(
+ private List<PiCounterCell> doReadAllCounterCells(
List<PiCounterId> counterIds, PiPipeconf pipeconf) {
return doReadCounterEntities(
CounterEntryCodec.readAllCellsEntities(counterIds, pipeconf),
pipeconf);
}
- private List<PiCounterCellData> doReadCounterCells(
+ private List<PiCounterCell> doReadCounterCells(
List<PiCounterCellId> cellIds, PiPipeconf pipeconf) {
return doReadCounterEntities(
CounterEntryCodec.encodePiCounterCellIds(cellIds, pipeconf),
pipeconf);
}
- private List<PiCounterCellData> doReadCounterEntities(
+ private List<PiCounterCell> doReadCounterEntities(
List<Entity> counterEntities, PiPipeconf pipeconf) {
if (counterEntities.size() == 0) {
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
index d5d909f..7e2df98 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
@@ -29,6 +29,7 @@
import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
import org.onosproject.net.pi.runtime.PiActionParam;
+import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
import org.onosproject.net.pi.runtime.PiFieldMatch;
import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
@@ -40,6 +41,7 @@
import org.slf4j.Logger;
import p4.config.v1.P4InfoOuterClass;
import p4.v1.P4RuntimeOuterClass.Action;
+import p4.v1.P4RuntimeOuterClass.CounterData;
import p4.v1.P4RuntimeOuterClass.FieldMatch;
import p4.v1.P4RuntimeOuterClass.TableAction;
import p4.v1.P4RuntimeOuterClass.TableEntry;
@@ -249,6 +251,11 @@
}
}
+ // Counter.
+ if (piTableEntry.counter() != null) {
+ tableEntryMsgBuilder.setCounterData(encodeCounter(piTableEntry.counter()));
+ }
+
return tableEntryMsgBuilder.build();
}
@@ -281,6 +288,9 @@
// Match key for field matches.
piTableEntryBuilder.withMatchKey(decodeFieldMatchMsgs(tableEntryMsg.getMatchList(), tableInfo, browser));
+ // Counter.
+ piTableEntryBuilder.withCounterCellData(decodeCounter(tableEntryMsg.getCounterData()));
+
return piTableEntryBuilder.build();
}
@@ -505,4 +515,13 @@
}
return PiAction.builder().withId(id).withParameters(params).build();
}
-}
+
+ static CounterData encodeCounter(PiCounterCellData piCounterCellData) {
+ return CounterData.newBuilder().setPacketCount(piCounterCellData.packets())
+ .setByteCount(piCounterCellData.bytes()).build();
+ }
+
+ static PiCounterCellData decodeCounter(CounterData counterData) {
+ return new PiCounterCellData(counterData.getPacketCount(), counterData.getByteCount());
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
index 0799108..d9e5f9a 100644
--- a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
@@ -32,11 +32,13 @@
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionParam;
+import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
import org.onosproject.net.pi.runtime.PiMatchKey;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
import p4.v1.P4RuntimeOuterClass.Action;
+import p4.v1.P4RuntimeOuterClass.CounterData;
import p4.v1.P4RuntimeOuterClass.TableEntry;
import java.net.URL;
@@ -72,6 +74,9 @@
private static final String ETHER_TYPE = "etherType";
private static final String ECMP_GROUP_ID = "ecmp_group_id";
+ private static final long PACKETS = 10;
+ private static final long BYTES = 100;
+
private final Random rand = new Random();
private final URL p4InfoUrl = this.getClass().getResource("/test.p4info");
@@ -94,6 +99,7 @@
private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
private final PiTableId tableId = PiTableId.of(TABLE_0);
private final PiTableId ecmpTableId = PiTableId.of(TABLE_ECMP);
+ private final PiCounterCellData counterCellData = new PiCounterCellData(PACKETS, BYTES);
private final PiTableEntry piTableEntry = PiTableEntry
.builder()
@@ -111,6 +117,7 @@
.build())
.withPriority(1)
.withCookie(2)
+ .withCounterCellData(counterCellData)
.build();
private final PiTableEntry piTableEntryWithoutAction = PiTableEntry
@@ -124,6 +131,7 @@
.build())
.withPriority(1)
.withCookie(2)
+ .withCounterCellData(counterCellData)
.build();
private final PiTableEntry piTableEntryWithGroupAction = PiTableEntry
@@ -135,6 +143,7 @@
.withAction(PiActionGroupId.of(1))
.withPriority(1)
.withCookie(2)
+ .withCounterCellData(counterCellData)
.build();
public TableEntryEncoderTest() throws ImmutableByteSequence.ByteSequenceTrimException {
@@ -198,6 +207,12 @@
byte[] encodedActionParam = actionMsg.getParams(0).getValue().toByteArray();
assertThat(encodedActionParam, is(portValue.asArray()));
+ // Counter
+ CounterData counterData = tableEntryMsg.getCounterData();
+ PiCounterCellData encodedCounterData = new PiCounterCellData(counterData.getPacketCount(),
+ counterData.getByteCount());
+ assertThat(encodedCounterData, is(counterCellData));
+
// TODO: improve, assert other field match types (ternary, LPM)
}
@@ -257,6 +272,12 @@
// no action
assertThat(tableEntryMsg.hasAction(), is(false));
+ // Counter
+ CounterData counterData = tableEntryMsg.getCounterData();
+ PiCounterCellData encodedCounterData = new PiCounterCellData(counterData.getPacketCount(),
+ counterData.getByteCount());
+ assertThat(encodedCounterData, is(counterCellData));
+
// TODO: improve, assert other field match types (ternary, LPM)
}
}
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index bc06fe6..22b5246 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -51,6 +51,7 @@
import org.onosproject.net.flow.FlowRuleProviderRegistry;
import org.onosproject.net.flow.FlowRuleProviderService;
import org.onosproject.net.flow.TableStatisticsEntry;
+import org.onosproject.net.flow.IndexTableId;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.statistic.DefaultLoad;
@@ -711,11 +712,25 @@
OFTableStatsEntry ofEntry) {
TableStatisticsEntry entry = null;
if (ofEntry != null) {
- entry = new DefaultTableStatisticsEntry(deviceId,
- ofEntry.getTableId().getValue(),
- ofEntry.getActiveCount(),
- ofEntry.getLookupCount().getValue(),
- ofEntry.getMatchedCount().getValue());
+ IndexTableId tid = IndexTableId.of(ofEntry.getTableId().getValue());
+
+ try {
+ entry = DefaultTableStatisticsEntry.builder()
+ .withDeviceId(deviceId)
+ .withTableId(tid)
+ .withActiveFlowEntries(ofEntry.getActiveCount())
+ .withPacketsLookedUpCount(ofEntry.getLookupCount().getValue())
+ .withPacketsMatchedCount(ofEntry.getMatchedCount().getValue())
+ .withMaxSize(ofEntry.getMaxEntries()).build();
+ } catch (UnsupportedOperationException e) {
+ // The exception "UnsupportedOperationException" is thrown by "getMaxEntries()".
+ entry = DefaultTableStatisticsEntry.builder()
+ .withDeviceId(deviceId)
+ .withTableId(tid)
+ .withActiveFlowEntries(ofEntry.getActiveCount())
+ .withPacketsLookedUpCount(ofEntry.getLookupCount().getValue())
+ .withPacketsMatchedCount(ofEntry.getMatchedCount().getValue()).build();
+ }
}
return entry;
@@ -777,4 +792,4 @@
}
}
-}
+}
\ No newline at end of file
diff --git a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
index c6a0ae9..56afd93 100644
--- a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
+++ b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
@@ -113,6 +113,7 @@
private static final String UNKNOWN = "unknown";
private static final int REST_TIMEOUT_SEC = 5;
private static final int EXECUTOR_THREAD_POOL_SIZE = 8;
+ private static final int DEVICE_POLL_SEC = 30;
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -148,6 +149,9 @@
private final SharedScheduledExecutorService portStatisticsExecutor =
SharedScheduledExecutors.getPoolThreadExecutor();
+ private final SharedScheduledExecutorService deviceConnectionExecutor =
+ SharedScheduledExecutors.getPoolThreadExecutor();
+ private ScheduledFuture<?> devicePollTask;
private final List<ConfigFactory> factories = ImmutableList.of(
new ConfigFactory<DeviceId, RestDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY,
RestDeviceConfig.class,
@@ -175,6 +179,7 @@
netCfgService.addListener(configListener);
executor.execute(RestDeviceProvider.this::createAndConnectDevices);
scheduledTask = schedulePolling();
+ devicePollTask = scheduleDevicePolling();
log.info("Started");
}
@@ -206,6 +211,7 @@
factories.forEach(netCfgService::unregisterConfigFactory);
scheduledTask.cancel(true);
executor.shutdown();
+ devicePollTask.cancel(true);
log.info("Stopped");
}
@@ -221,23 +227,91 @@
@Override
public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
- // TODO: This will be implemented later.
+ log.debug("Received role {} request for device {}", newRole, deviceId);
+ RestSBDevice device = controller.getDevice(deviceId);
+ if (device != null && testDeviceConnection(device)) {
+ providerService.receivedRoleReply(deviceId, newRole, newRole);
+ } else {
+ log.warn("Device not present or available {}", deviceId);
+ providerService.receivedRoleReply(deviceId, newRole, MastershipRole.NONE);
+ }
}
@Override
public boolean isReachable(DeviceId deviceId) {
RestSBDevice restDevice = controller.getDevice(deviceId);
- if (restDevice == null) {
- restDevice = controller.getProxySBDevice(deviceId);
- if (restDevice == null) {
- log.debug("the requested device id: " +
- deviceId.toString() +
- " is not associated to any REST or REST " +
- "proxy Device");
- return false;
+ return restDevice != null ? restDevice.isActive() : false;
+ }
+
+ private ScheduledFuture scheduleDevicePolling() {
+ return deviceConnectionExecutor.scheduleWithFixedDelay(() -> {
+ try {
+ controller.getDevices().values().stream().forEach(restSBDevice -> {
+ DeviceId deviceId = restSBDevice.deviceId();
+ if (deviceService.getDevice(deviceId) != null) {
+ boolean connected = testDeviceConnection(restSBDevice);
+ restSBDevice.setActive(connected);
+ if (deviceService.isAvailable(deviceId) && (!connected)) {
+ providerService.deviceDisconnected(deviceId);
+ } else if (!deviceService.isAvailable(deviceId) && connected) {
+ DeviceDescription devDesc = getDesc(restSBDevice);
+ checkNotNull(devDesc, "deviceDescription cannot be null");
+ providerService.deviceConnected(
+ deviceId, mergeAnn(deviceId, devDesc));
+ }
+ }
+ }
+ );
+ } catch (Exception e) {
+ log.error("Exception at schedule Device polling", e);
+ }
+ }, 1, DEVICE_POLL_SEC, TimeUnit.SECONDS);
+ }
+
+ private DeviceDescription getDesc(RestSBDevice restSBDev) {
+ DeviceId deviceId = restSBDev.deviceId();
+ if (restSBDev.isProxy()) {
+ Driver driver = driverService.getDriver(restSBDev.manufacturer().get(),
+ restSBDev.hwVersion().get(),
+ restSBDev.swVersion().get());
+
+ if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
+
+ //Creates the driver to communicate with the server
+ DevicesDiscovery devicesDiscovery =
+ devicesDiscovery(restSBDev, driver);
+ return devicesDiscovery.deviceDetails(deviceId);
+ } else {
+ log.warn("Driver not found for {}", restSBDev);
+ return null;
}
}
- return restDevice.isActive();
+ ChassisId cid = new ChassisId();
+ String ipAddress = restSBDev.ip().toString();
+ SparseAnnotations annotations = DefaultAnnotations.builder()
+ .set(IPADDRESS, ipAddress)
+ .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
+ .build();
+ String manufacturer = UNKNOWN;
+ String hwVersion = UNKNOWN;
+ String swVersion = UNKNOWN;
+ String serialNumber = UNKNOWN;
+
+ Device device = deviceService.getDevice(deviceId);
+ if (device != null) {
+ manufacturer = device.manufacturer();
+ hwVersion = device.hwVersion();
+ swVersion = device.swVersion();
+ serialNumber = device.serialNumber();
+ }
+
+ return new DefaultDeviceDescription(
+ deviceId.uri(),
+ Device.Type.SWITCH,
+ manufacturer, hwVersion,
+ swVersion, serialNumber,
+ cid,
+ annotations);
}
private void deviceAdded(RestSBDevice restSBDev) {
@@ -272,6 +346,7 @@
}
} else {
DeviceId deviceId = restSBDev.deviceId();
+
if (driver != null && driver.hasBehaviour(DevicesDiscovery.class)) {
restSBDev.setActive(true);
DevicesDiscovery devicesDiscovery = devicesDiscovery(restSBDev, driver);
@@ -285,23 +360,10 @@
providerService.updatePorts(deviceId, deviceDiscovery.discoverPortDetails());
}
} else {
- ChassisId cid = new ChassisId();
- String ipAddress = restSBDev.ip().toString();
- SparseAnnotations annotations = DefaultAnnotations.builder()
- .set(IPADDRESS, ipAddress)
- .set(AnnotationKeys.PROTOCOL, REST.toUpperCase())
- .build();
- DeviceDescription deviceDescription = new DefaultDeviceDescription(
- deviceId.uri(),
- Device.Type.SWITCH,
- UNKNOWN, UNKNOWN,
- UNKNOWN, UNKNOWN,
- cid,
- annotations);
+ DeviceDescription deviceDescription = getDesc(restSBDev);
restSBDev.setActive(true);
providerService.deviceConnected(deviceId, deviceDescription);
}
-
checkAndUpdateDevice(deviceId);
}
}
@@ -371,6 +433,7 @@
private void deviceRemoved(DeviceId deviceId) {
checkNotNull(deviceId, ISNOTNULL);
+ log.debug("Device removed called for {}", deviceId);
providerService.deviceDisconnected(deviceId);
controller.getProxiedDevices(deviceId).forEach(device -> {
controller.removeProxiedDevice(device);
@@ -383,6 +446,8 @@
private void createAndConnectDevices() {
Set<DeviceId> deviceSubjects =
netCfgService.getSubjects(DeviceId.class, RestDeviceConfig.class);
+ log.debug("Connecting and configuring devices with received configuration:{}",
+ deviceSubjects);
connectDevices(deviceSubjects.stream()
.filter(deviceId -> deviceService.getDevice(deviceId) == null)
.map(deviceId -> {
@@ -510,10 +575,14 @@
ExecutorService bg = SharedExecutors.getSingleThreadExecutor();
if (event.type() == CONFIG_REMOVED) {
+ log.debug("Config {} event for rest device provider for {}",
+ event.type(), event.prevConfig().get().subject());
DeviceId did = (DeviceId) event.subject();
bg.execute(() -> deviceRemoved(did));
} else {
- // CONFIG_ADDED or CONFIG_UPDATED
+ //CONFIG_ADDED or CONFIG_UPDATED
+ log.debug("Config {} event for rest device provider for {}",
+ event.type(), event.config().get().subject());
RestDeviceConfig cfg = (RestDeviceConfig) event.config().get();
RestSBDevice restSBDevice = toInactiveRestSBDevice(cfg);
bg.execute(() -> connectDevice(restSBDevice));
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/MetersWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/MetersWebResource.java
index 6fbe1b3..814b351 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/MetersWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/MetersWebResource.java
@@ -183,7 +183,11 @@
final Meter tmpMeter = meterService.getMeter(did, mid);
if (tmpMeter != null) {
final MeterRequest meterRequest = meterToMeterRequest(tmpMeter, "REMOVE");
- meterService.withdraw(meterRequest, tmpMeter.id());
+ if (meterRequest != null) {
+ meterService.withdraw(meterRequest, tmpMeter.id());
+ }
+ } else {
+ log.warn("Meter {}, is not present", tmpMeter);
}
return Response.noContent().build();
}