ONOS-1930 : Tunnel and policy failover with multi-instances
- Prevents tunnel delete from removing groups used for default flows
- Removes SegmentRoutingManager reference from Tunnel and Policy class
- Adds some error checks such as duplicates tunnel IDs or duplicate polices
Change-Id: I0e7d5e2eff0aea6dad13137a872fee58e083b11c
diff --git a/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java b/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
index 234dd20..5913e5b 100644
--- a/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
@@ -16,10 +16,18 @@
package org.onosproject.segmentrouting;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.cli.net.IpProtocol;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import static org.slf4j.LoggerFactory.getLogger;
@@ -31,13 +39,17 @@
protected final Logger log = getLogger(getClass());
- private final HashMap<String, Policy> policyMap;
+ private final SegmentRoutingManager srManager;
+ private final EventuallyConsistentMap<String, Policy> policyStore;
/**
* Creates a reference.
+ * @param policyStore
*/
- public PolicyHandler() {
- policyMap = new HashMap<>();
+ public PolicyHandler(SegmentRoutingManager srManager,
+ EventuallyConsistentMap<String, Policy> policyStore) {
+ this.srManager = srManager;
+ this.policyStore = policyStore;
}
/**
@@ -47,7 +59,7 @@
*/
public List<Policy> getPolicies() {
List<Policy> policies = new ArrayList<>();
- policyMap.values().forEach(policy -> policies.add(
+ policyStore.values().forEach(policy -> policies.add(
new TunnelPolicy((TunnelPolicy) policy)));
return policies;
@@ -59,8 +71,43 @@
* @param policy policy reference to create
*/
public void createPolicy(Policy policy) {
- policy.create();
- policyMap.put(policy.id(), policy);
+
+ if (policyStore.containsKey(policy.id())) {
+ log.warn("The policy id {} exists already", policy.id());
+ return;
+ }
+
+ if (policyStore.containsValue(policy)) {
+ log.warn("The same policy exists already");
+ return;
+ }
+
+ if (policy.type() == Policy.Type.TUNNEL_FLOW) {
+
+ TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
+ Tunnel tunnel = srManager.getTunnel(tunnelPolicy.tunnelId());
+ if (tunnel == null) {
+ log.error("Tunnel {} does not exists");
+ return;
+ }
+
+ ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+ .builder()
+ .fromApp(srManager.appId)
+ .makePermanent()
+ .nextStep(tunnel.groupId())
+ .withPriority(tunnelPolicy.priority())
+ .withSelector(buildSelector(policy))
+ .withFlag(ForwardingObjective.Flag.VERSATILE);
+
+ DeviceId source = srManager.deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
+ srManager.flowObjectiveService.forward(source, fwdBuilder.add());
+
+ } else {
+ log.warn("Policy type {} is not supported yet.", policy.type());
+ }
+
+ policyStore.put(policy.id(), policy);
}
/**
@@ -69,15 +116,64 @@
* @param policyInfo policy information to remove
*/
public void removePolicy(Policy policyInfo) {
- if (policyMap.get(policyInfo.id()) != null) {
- if (policyMap.get(policyInfo.id()).remove()) {
- policyMap.remove(policyInfo.id());
- } else {
- log.error("Failed to remove the policy {}", policyInfo.id());
+
+ if (policyStore.get(policyInfo.id()) != null) {
+ Policy policy = policyStore.get(policyInfo.id());
+ if (policy.type() == Policy.Type.TUNNEL_FLOW) {
+ TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
+ Tunnel tunnel = srManager.getTunnel(tunnelPolicy.tunnelId());
+
+ ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+ .builder()
+ .fromApp(srManager.appId)
+ .makePermanent()
+ .withSelector(buildSelector(policy))
+ .withPriority(tunnelPolicy.priority())
+ .nextStep(tunnel.groupId())
+ .withFlag(ForwardingObjective.Flag.VERSATILE);
+
+ DeviceId source = srManager.deviceConfiguration.getDeviceId(tunnel.labelIds().get(0));
+ srManager.flowObjectiveService.forward(source, fwdBuilder.remove());
+
+ policyStore.remove(policyInfo.id());
}
} else {
log.warn("Policy {} was not found", policyInfo.id());
}
}
+
+ private TrafficSelector buildSelector(Policy policy) {
+
+ TrafficSelector.Builder tsb = DefaultTrafficSelector.builder();
+ tsb.matchEthType(Ethernet.TYPE_IPV4);
+ if (policy.dstIp() != null && !policy.dstIp().isEmpty()) {
+ tsb.matchIPDst(IpPrefix.valueOf(policy.dstIp()));
+ }
+ if (policy.srcIp() != null && !policy.srcIp().isEmpty()) {
+ tsb.matchIPSrc(IpPrefix.valueOf(policy.srcIp()));
+ }
+ if (policy.ipProto() != null && !policy.ipProto().isEmpty()) {
+ Short ipProto = Short.valueOf(IpProtocol.valueOf(policy.ipProto()).value());
+ tsb.matchIPProtocol(ipProto.byteValue());
+ if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.TCP)) {
+ if (policy.srcPort() != 0) {
+ tsb.matchTcpSrc(policy.srcPort());
+ }
+ if (policy.dstPort() != 0) {
+ tsb.matchTcpDst(policy.dstPort());
+ }
+ } else if (IpProtocol.valueOf(policy.ipProto()).equals(IpProtocol.UDP)) {
+ if (policy.srcPort() != 0) {
+ tsb.matchUdpSrc(policy.srcPort());
+ }
+ if (policy.dstPort() != 0) {
+ tsb.matchUdpDst(policy.dstPort());
+ }
+ }
+ }
+
+ return tsb.build();
+ }
+
}