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/DefaultTunnel.java b/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
index f1c0216..8c6fbe8 100644
--- a/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
+++ b/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
@@ -16,16 +16,8 @@
package org.onosproject.segmentrouting;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
-import org.onosproject.segmentrouting.grouphandler.NeighborSet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
+import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -34,31 +26,11 @@
*/
public class DefaultTunnel implements Tunnel {
- private static final Logger log = LoggerFactory
- .getLogger(DefaultTunnel.class);
-
- private final String tunnelId;
+ private final String id;
private final List<Integer> labelIds;
- private final SegmentRoutingManager srManager;
- private final DeviceConfiguration config;
private int groupId;
-
- /**
- * Creates a Tunnel reference.
- *
- * @param srm SegmentRoutingManager object
- * @param tid Tunnel ID
- * @param labelIds Label stack of the tunnel
- */
- public DefaultTunnel(SegmentRoutingManager srm, String tid,
- List<Integer> labelIds) {
- this.srManager = checkNotNull(srm);
- this.tunnelId = checkNotNull(tid);
- this.labelIds = Collections.unmodifiableList(labelIds);
- this.config = srManager.deviceConfiguration;
- this.groupId = -1;
- }
+ private boolean allowedToRemoveGroup;
/**
* Creates a Tunnel reference.
@@ -67,10 +39,10 @@
* @param labelIds Label stack of the tunnel
*/
public DefaultTunnel(String tid, List<Integer> labelIds) {
- this.srManager = null;
- this.tunnelId = checkNotNull(tid);
- this.labelIds = Collections.unmodifiableList(labelIds);
- this.config = null;
+ this.id = checkNotNull(tid);
+ this.labelIds = labelIds;
+ //TODO: need to register the class in Kryo for this
+ //this.labelIds = Collections.unmodifiableList(labelIds);
this.groupId = -1;
}
@@ -80,16 +52,14 @@
* @param tunnel DefaultTunnel reference
*/
public DefaultTunnel(DefaultTunnel tunnel) {
- this.srManager = tunnel.srManager;
- this.tunnelId = tunnel.tunnelId;
+ this.id = tunnel.id;
this.labelIds = tunnel.labelIds;
- this.config = tunnel.config;
this.groupId = tunnel.groupId;
}
@Override
public String id() {
- return this.tunnelId;
+ return this.id;
}
@Override
@@ -98,71 +68,44 @@
}
@Override
- public boolean create() {
-
- if (labelIds.isEmpty() || labelIds.size() < 3) {
- log.error("More than one router needs to specified to created a tunnel");
- return false;
- }
-
- groupId = createGroupsForTunnel();
- if (groupId < 0) {
- log.error("Failed to create groups for the tunnel");
- return false;
- }
-
- return true;
- }
-
- @Override
- public boolean remove() {
-
- DeviceId deviceId = config.getDeviceId(labelIds.get(0));
- srManager.removeNextObjective(deviceId, groupId);
-
- return true;
- }
-
- @Override
public int groupId() {
return this.groupId;
}
@Override
- public DeviceId source() {
- return config.getDeviceId(labelIds.get(0));
+ public void setGroupId(int id) {
+ this.groupId = id;
}
- private int createGroupsForTunnel() {
-
- List<Integer> portNumbers;
-
- int groupId;
-
- DeviceId deviceId = config.getDeviceId(labelIds.get(0));
- if (deviceId == null) {
- log.warn("No device found for SID {}", labelIds.get(0));
- return -1;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
}
- Set<DeviceId> deviceIds = new HashSet<>();
- int sid = labelIds.get(1);
- if (config.isAdjacencySid(deviceId, sid)) {
- portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
- for (Link link: srManager.linkService.getDeviceEgressLinks(deviceId)) {
- for (Integer port: portNumbers) {
- if (link.src().port().toLong() == port) {
- deviceIds.add(link.dst().deviceId());
- }
- }
+
+ if (o instanceof DefaultTunnel) {
+ DefaultTunnel tunnel = (DefaultTunnel) o;
+ // We compare only the tunnel paths.
+ if (tunnel.labelIds.equals(this.labelIds)) {
+ return true;
}
- } else {
- deviceIds.add(config.getDeviceId(sid));
}
- NeighborSet ns = new NeighborSet(deviceIds, labelIds.get(2));
- groupId = srManager.getNextObjectiveId(deviceId, ns);
-
- return groupId;
+ return false;
}
+ @Override
+ public int hashCode() {
+ return Objects.hash(labelIds);
+ }
+
+ @Override
+ public boolean isAllowedToRemoveGroup() {
+ return this.allowedToRemoveGroup;
+ }
+
+ @Override
+ public void allowToRemoveGroup(boolean b) {
+ this.allowedToRemoveGroup = b;
+ }
}
diff --git a/src/main/java/org/onosproject/segmentrouting/Policy.java b/src/main/java/org/onosproject/segmentrouting/Policy.java
index d47bc2e..2e41795 100644
--- a/src/main/java/org/onosproject/segmentrouting/Policy.java
+++ b/src/main/java/org/onosproject/segmentrouting/Policy.java
@@ -16,8 +16,6 @@
package org.onosproject.segmentrouting;
-import org.onosproject.net.flow.TrafficSelector;
-
/**
* Interface for Segment Routing Policy.
*/
@@ -47,13 +45,6 @@
String id();
/**
- * Returns the traffic selector object.
- *
- * @return TrafficSelector object
- */
- TrafficSelector selector();
-
- /**
* Returns the priority of the policy.
*
* @return priority
@@ -68,16 +59,38 @@
Type type();
/**
- * Creates a policy.
+ * Returns the source IP address of the policy.
*
- * @return true if succeeds, false otherwise
+ * @return source IP address
*/
- boolean create();
+ String srcIp();
/**
- * Removes the policy.
+ * Returns the destination IP address of the policy.
*
- * @return true if succeeds, false otherwise
+ * @return destination IP address
*/
- boolean remove();
+ String dstIp();
+
+ /**
+ * Returns the IP protocol of the policy.
+ *
+ * @return IP protocol
+ */
+ String ipProto();
+
+ /**
+ * Returns the source port of the policy.
+ *
+ * @return source port
+ */
+ short srcPort();
+
+ /**
+ * Returns the destination of the policy.
+ *
+ * @return destination port
+ */
+ short dstPort();
+
}
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();
+ }
+
}
diff --git a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 02ed88a..8a7aae9 100644
--- a/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -128,6 +128,9 @@
// Per device next objective ID store with (device id + neighbor set) as key
private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
Integer> nsNextObjStore = null;
+ private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
+ private EventuallyConsistentMap<String, Policy> policyStore = null;
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@@ -148,13 +151,18 @@
kryoBuilder = new KryoNamespace.Builder()
.register(NeighborSetNextObjectiveStoreKey.class,
- NeighborSet.class,
- DeviceId.class,
- URI.class,
- WallClockTimestamp.class,
- org.onosproject.cluster.NodeId.class,
- HashSet.class
- );
+ NeighborSet.class,
+ DeviceId.class,
+ URI.class,
+ WallClockTimestamp.class,
+ org.onosproject.cluster.NodeId.class,
+ HashSet.class,
+ Tunnel.class,
+ DefaultTunnel.class,
+ Policy.class,
+ TunnelPolicy.class,
+ Policy.Type.class
+ );
log.debug("Creating EC map nsnextobjectivestore");
EventuallyConsistentMapBuilder<NeighborSetNextObjectiveStoreKey, Integer>
@@ -167,6 +175,24 @@
.build();
log.trace("Current size {}", nsNextObjStore.size());
+ EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
+ storageService.eventuallyConsistentMapBuilder();
+
+ tunnelStore = tunnelMapBuilder
+ .withName("tunnelstore")
+ .withSerializer(kryoBuilder)
+ .withClockService(new WallclockClockManager<>())
+ .build();
+
+ EventuallyConsistentMapBuilder<String, Policy> policyMapBuilder =
+ storageService.eventuallyConsistentMapBuilder();
+
+ policyStore = policyMapBuilder
+ .withName("policystore")
+ .withSerializer(kryoBuilder)
+ .withClockService(new WallclockClockManager<>())
+ .build();
+
networkConfigService.init();
deviceConfiguration = new DeviceConfiguration(networkConfigService);
arpHandler = new ArpHandler(this);
@@ -174,8 +200,8 @@
ipHandler = new IpHandler(this);
routingRulePopulator = new RoutingRulePopulator(this);
defaultRoutingHandler = new DefaultRoutingHandler(this);
- tunnelHandler = new TunnelHandler();
- policyHandler = new PolicyHandler();
+ tunnelHandler = new TunnelHandler(this, tunnelStore);
+ policyHandler = new PolicyHandler(this, policyStore);
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
linkService.addListener(new InternalLinkListener());
@@ -295,6 +321,24 @@
}
/**
+ * Checks if the next objective ID (group) for the neighbor set exists or not in the device.
+ *
+ * @param deviceId Device ID to check
+ * @param ns neighbor set to check
+ * @return true if it exists, false otherwise
+ */
+ public boolean hasNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
+ if (groupHandlerMap.get(deviceId) != null) {
+ log.trace("getNextObjectiveId query in device {}", deviceId);
+ return groupHandlerMap
+ .get(deviceId).hasNextObjectiveId(ns);
+ } else {
+ log.warn("getNextObjectiveId query in device {} not found", deviceId);
+ return false;
+ }
+ }
+
+ /**
* Removes the next objective ID.
*
* @param deviceId Device ID
diff --git a/src/main/java/org/onosproject/segmentrouting/Tunnel.java b/src/main/java/org/onosproject/segmentrouting/Tunnel.java
index 0c35fba..c56ae70 100644
--- a/src/main/java/org/onosproject/segmentrouting/Tunnel.java
+++ b/src/main/java/org/onosproject/segmentrouting/Tunnel.java
@@ -16,8 +16,6 @@
package org.onosproject.segmentrouting;
-import org.onosproject.net.DeviceId;
-
import java.util.List;
/**
@@ -40,20 +38,6 @@
List<Integer> labelIds();
/**
- * Creates a tunnel.
- *
- * @return true if succeeds, false otherwise
- */
- boolean create();
-
- /**
- * Removes the tunnel.
- *
- * @return true if succeeds, false otherwise.
- */
- boolean remove();
-
- /**
* Returns the group ID for the tunnel.
*
* @return group ID
@@ -61,9 +45,22 @@
int groupId();
/**
- * Returns the source device Id of the tunnel.
+ * Sets group ID for the tunnel.
*
- * @return source device Id
*/
- DeviceId source();
+ void setGroupId(int groupId);
+
+ /**
+ * Sets the flag to allow to remove the group or not.
+ *
+ * @param ok the flag; true - allow to remove
+ */
+ void allowToRemoveGroup(boolean ok);
+
+ /**
+ * Checks if it is allowed to remove the group for the tunnel.
+ *
+ * @return true if allowed, false otherwise
+ */
+ boolean isAllowedToRemoveGroup();
}
diff --git a/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
index 4a498c6..1c07093 100644
--- a/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
@@ -15,12 +15,18 @@
*/
package org.onosproject.segmentrouting;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.segmentrouting.grouphandler.NeighborSet;
+import org.onosproject.store.service.EventuallyConsistentMap;
import org.slf4j.Logger;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
-import java.util.HashMap;
+import java.util.Set;
+import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -29,10 +35,15 @@
public class TunnelHandler {
protected final Logger log = getLogger(getClass());
- private final HashMap<String, Tunnel> tunnelMap;
+ private final SegmentRoutingManager srManager;
+ private final DeviceConfiguration config;
+ private final EventuallyConsistentMap<String, Tunnel> tunnelStore;
- public TunnelHandler() {
- tunnelMap = new HashMap<>();
+ public TunnelHandler(SegmentRoutingManager srm,
+ EventuallyConsistentMap<String, Tunnel> tunnelStore) {
+ this.srManager = checkNotNull(srm);
+ this.config = srm.deviceConfiguration;
+ this.tunnelStore = tunnelStore;
}
/**
@@ -40,9 +51,33 @@
*
* @param tunnel tunnel reference to create a tunnel
*/
- public void createTunnel(Tunnel tunnel) {
- tunnel.create();
- tunnelMap.put(tunnel.id(), tunnel);
+ public boolean createTunnel(Tunnel tunnel) {
+
+ if (tunnel.labelIds().isEmpty() || tunnel.labelIds().size() < 3) {
+ log.error("More than one router needs to specified to created a tunnel");
+ return false;
+ }
+
+ if (tunnelStore.containsKey(tunnel.id())) {
+ log.warn("The same tunnel ID exists already");
+ return false;
+ }
+
+ if (tunnelStore.containsValue(tunnel)) {
+ log.warn("The same tunnel exists already");
+ return false;
+ }
+
+ int groupId = createGroupsForTunnel(tunnel);
+ if (groupId < 0) {
+ log.error("Failed to create groups for the tunnel");
+ return false;
+ }
+
+ tunnel.setGroupId(groupId);
+ tunnelStore.put(tunnel.id(), tunnel);
+
+ return true;
}
/**
@@ -52,10 +87,19 @@
*/
public void removeTunnel(Tunnel tunnelInfo) {
- Tunnel tunnel = tunnelMap.get(tunnelInfo.id());
+ Tunnel tunnel = tunnelStore.get(tunnelInfo.id());
if (tunnel != null) {
- tunnel.remove();
- tunnelMap.remove(tunnel.id());
+ DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
+ if (tunnel.isAllowedToRemoveGroup()) {
+ if (srManager.removeNextObjective(deviceId, tunnel.groupId())) {
+ tunnelStore.remove(tunnel.id());
+ } else {
+ log.error("Failed to remove the tunnel {}", tunnelInfo.id());
+ }
+ } else {
+ log.debug("The group is not removed because it is being used.");
+ tunnelStore.remove(tunnel.id());
+ }
} else {
log.warn("No tunnel found for tunnel ID {}", tunnelInfo.id());
}
@@ -68,7 +112,7 @@
* @return Tunnel reference
*/
public Tunnel getTunnel(String tid) {
- return tunnelMap.get(tid);
+ return tunnelStore.get(tid);
}
/**
@@ -78,9 +122,50 @@
*/
public List<Tunnel> getTunnels() {
List<Tunnel> tunnels = new ArrayList<>();
- tunnelMap.values().forEach(tunnel -> tunnels.add(
+ tunnelStore.values().forEach(tunnel -> tunnels.add(
new DefaultTunnel((DefaultTunnel) tunnel)));
return tunnels;
}
+
+ private int createGroupsForTunnel(Tunnel tunnel) {
+
+ List<Integer> portNumbers;
+
+ int groupId;
+
+ DeviceId deviceId = config.getDeviceId(tunnel.labelIds().get(0));
+ if (deviceId == null) {
+ log.warn("No device found for SID {}", tunnel.labelIds().get(0));
+ return -1;
+ }
+ Set<DeviceId> deviceIds = new HashSet<>();
+ int sid = tunnel.labelIds().get(1);
+ if (config.isAdjacencySid(deviceId, sid)) {
+ portNumbers = config.getPortsForAdjacencySid(deviceId, sid);
+ for (Link link: srManager.linkService.getDeviceEgressLinks(deviceId)) {
+ for (Integer port: portNumbers) {
+ if (link.src().port().toLong() == port) {
+ deviceIds.add(link.dst().deviceId());
+ }
+ }
+ }
+ } else {
+ deviceIds.add(config.getDeviceId(sid));
+ }
+
+ NeighborSet ns = new NeighborSet(deviceIds, tunnel.labelIds().get(2));
+
+ // If the tunnel reuses any existing groups, then tunnel handler
+ // should not remove the group.
+ if (srManager.hasNextObjectiveId(deviceId, ns)) {
+ tunnel.allowToRemoveGroup(false);
+ } else {
+ tunnel.allowToRemoveGroup(true);
+ }
+ groupId = srManager.getNextObjectiveId(deviceId, ns);
+
+ return groupId;
+ }
+
}
diff --git a/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java b/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
index 134828b..06dbdb2 100644
--- a/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
+++ b/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
@@ -16,9 +16,7 @@
package org.onosproject.segmentrouting;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.ForwardingObjective;
+import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -27,24 +25,28 @@
*/
public final class TunnelPolicy implements Policy {
- // FIXME: We should avoid passing around references to implementation objects
- // Instead, if some operational context is required, we should abstract it to
- // a bare minimum.
- private final SegmentRoutingManager srManager;
private final Type type;
private final String id;
- private final TrafficSelector selector;
private final int priority;
private final String tunnelId;
+ private String dstIp;
+ private String srcIp;
+ private String ipProto;
+ private short srcPort;
+ private short dstPort;
- private TunnelPolicy(SegmentRoutingManager srm, String policyId, Type type,
- TrafficSelector selector, int priority, String tunnelId) {
- this.srManager = srm;
+ private TunnelPolicy(String policyId, Type type, int priority, String tunnelId, String srcIp,
+ String dstIp, String ipProto, short srcPort, short dstPort) {
this.id = checkNotNull(policyId);
this.type = type;
this.tunnelId = tunnelId;
this.priority = priority;
- this.selector = selector;
+ this.dstIp = dstIp;
+ this.srcIp = srcIp;
+ this.ipProto = ipProto;
+ this.srcPort = srcPort;
+ this.dstPort = dstPort;
+
}
/**
@@ -53,27 +55,15 @@
* @param p TunnelPolicy reference
*/
public TunnelPolicy(TunnelPolicy p) {
- this.srManager = p.srManager;
this.id = p.id;
this.type = p.type;
this.tunnelId = p.tunnelId;
this.priority = p.priority;
- this.selector = p.selector;
- }
-
- /**
- * Creates a TunnelPolicy reference.
- *
- * @param srm reference to the segment routing component
- * @param p TunnelPolicy reference
- */
- public TunnelPolicy(SegmentRoutingManager srm, TunnelPolicy p) {
- this.srManager = srm;
- this.id = p.id;
- this.type = p.type;
- this.tunnelId = p.tunnelId;
- this.priority = p.priority;
- this.selector = p.selector;
+ this.srcIp = p.srcIp;
+ this.dstIp = p.dstIp;
+ this.ipProto = p.ipProto;
+ this.srcPort = p.srcPort;
+ this.dstPort = p.dstPort;
}
/**
@@ -91,11 +81,6 @@
}
@Override
- public TrafficSelector selector() {
- return selector;
- }
-
- @Override
public int priority() {
return priority;
}
@@ -106,41 +91,58 @@
}
@Override
- public boolean create() {
-
- Tunnel tunnel = srManager.getTunnel(tunnelId);
-
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder()
- .fromApp(srManager.appId)
- .makePermanent()
- .nextStep(tunnel.groupId())
- .withPriority(priority)
- .withSelector(selector)
- .withFlag(ForwardingObjective.Flag.VERSATILE);
-
- srManager.flowObjectiveService.forward(tunnel.source(), fwdBuilder.add());
-
- return true;
+ public String srcIp() {
+ return srcIp;
}
@Override
- public boolean remove() {
+ public String dstIp() {
+ return dstIp;
+ }
- Tunnel tunnel = srManager.getTunnel(tunnelId);
+ @Override
+ public String ipProto() {
+ return ipProto;
+ }
- ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
- .builder()
- .fromApp(srManager.appId)
- .makePermanent()
- .withSelector(selector)
- .withPriority(priority)
- .nextStep(tunnel.groupId())
- .withFlag(ForwardingObjective.Flag.VERSATILE);
+ @Override
+ public short srcPort() {
+ return srcPort;
+ }
- srManager.flowObjectiveService.forward(tunnel.source(), fwdBuilder.remove());
+ @Override
+ public short dstPort() {
+ return dstPort;
+ }
- return true;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o instanceof TunnelPolicy) {
+ TunnelPolicy that = (TunnelPolicy) o;
+ // We do not compare the policy ID
+ if (this.type.equals(that.type) &&
+ this.tunnelId.equals(that.tunnelId) &&
+ this.priority == that.priority &&
+ this.srcIp.equals(that.srcIp) &&
+ this.dstIp.equals(that.dstIp) &&
+ this.srcPort == that.srcPort &&
+ this.dstPort == that.dstPort &&
+ this.ipProto.equals(that.ipProto)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, tunnelId, srcIp, dstIp, ipProto,
+ srcPort, dstPort, priority);
}
/**
@@ -152,17 +154,21 @@
return this.tunnelId;
}
+
/**
* Tunnel Policy Builder.
*/
public static final class Builder {
- private SegmentRoutingManager srManager;
private String id;
private Type type;
- private TrafficSelector selector;
private int priority;
private String tunnelId;
+ private String dstIp;
+ private String srcIp;
+ private String ipProto;
+ private short srcPort;
+ private short dstPort;
/**
* Sets the policy Id.
@@ -189,13 +195,61 @@
}
/**
- * Sets the TrafficSelector.
+ * Sets the source IP address.
*
- * @param selector TrafficSelector
+ * @param srcIp source IP address
* @return Builder object
*/
- public Builder setSelector(TrafficSelector selector) {
- this.selector = selector;
+ public Builder setSrcIp(String srcIp) {
+ this.srcIp = srcIp;
+
+ return this;
+ }
+
+ /**
+ * Sets the destination IP address.
+ *
+ * @param dstIp destination IP address
+ * @return Builder object
+ */
+ public Builder setDstIp(String dstIp) {
+ this.dstIp = dstIp;
+
+ return this;
+ }
+
+ /**
+ * Sets the IP protocol.
+ *
+ * @param proto IP protocol
+ * @return Builder object
+ */
+ public Builder setIpProto(String proto) {
+ this.ipProto = proto;
+
+ return this;
+ }
+
+ /**
+ * Sets the source port.
+ *
+ * @param srcPort source port
+ * @return Builder object
+ */
+ public Builder setSrcPort(short srcPort) {
+ this.srcPort = srcPort;
+
+ return this;
+ }
+
+ /**
+ * Sets the destination port.
+ *
+ * @param dstPort destination port
+ * @return Builder object
+ */
+ public Builder setDstPort(short dstPort) {
+ this.dstPort = dstPort;
return this;
}
@@ -225,24 +279,13 @@
}
/**
- * Sets the Segment Routing Manager reference.
- *
- * @param srm Segment Routing Manager reference
- * @return Builder object
- */
- public Builder setManager(SegmentRoutingManager srm) {
- this.srManager = srm;
-
- return this;
- }
-
- /**
* Builds the policy.
*
* @return Tunnel Policy reference
*/
public Policy build() {
- return new TunnelPolicy(srManager, id, type, selector, priority, tunnelId);
+ return new TunnelPolicy(id, type, priority, tunnelId, srcIp, dstIp,
+ ipProto, srcPort, dstPort);
}
}
}
diff --git a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 4a25438..7226fd8 100644
--- a/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -181,8 +181,8 @@
.contains(newLink.dst().deviceId())))
.collect(Collectors.toSet());
log.trace("linkUp: nsNextObjStore contents for device {}:",
- deviceId,
- nsSet);
+ deviceId,
+ nsSet);
for (NeighborSet ns : nsSet) {
// Create the new bucket to be updated
TrafficTreatment.Builder tBuilder =
@@ -317,6 +317,22 @@
return nextId.intValue();
}
+ /**
+ * Checks if the next objective ID (group) for the neighbor set exists or not.
+ *
+ * @param ns neighbor set to check
+ * @return true if it exists, false otherwise
+ */
+ public boolean hasNextObjectiveId(NeighborSet ns) {
+ Integer nextId = nsNextObjStore.
+ get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
+ if (nextId == null) {
+ return false;
+ }
+
+ return true;
+ }
+
// Empty implementation
protected void newNeighbor(Link newLink) {
}
@@ -489,6 +505,7 @@
break;
}
}
+ return true;
}
return false;
diff --git a/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java b/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
index 3e2524d..8e50887 100644
--- a/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
+++ b/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
@@ -15,19 +15,9 @@
*/
package org.onosproject.segmentrouting.web;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IpPrefix;
-import org.onosproject.cli.net.IpProtocol;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.IPCriterion;
-import org.onosproject.net.flow.criteria.IPProtocolCriterion;
-import org.onosproject.net.flow.criteria.TcpPortCriterion;
-import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.segmentrouting.Policy;
import org.onosproject.segmentrouting.TunnelPolicy;
@@ -52,45 +42,24 @@
result.put(PRIORITY, policy.priority());
result.put(TYPE, policy.type().toString());
- if (policy.selector().getCriterion(Criterion.Type.IPV4_DST) != null) {
- IPCriterion criterion = (IPCriterion) policy.selector().getCriterion(
- Criterion.Type.IPV4_DST);
- result.put(DST_IP, criterion.ip().toString());
+ if (policy.dstIp() != null) {
+ result.put(DST_IP, policy.dstIp());
}
- if (policy.selector().getCriterion(Criterion.Type.IPV4_SRC) != null) {
- IPCriterion criterion = (IPCriterion) policy.selector().getCriterion(
- Criterion.Type.IPV4_SRC);
- result.put(SRC_IP, criterion.ip().toString());
+ if (policy.srcIp() != null) {
+ result.put(SRC_IP, policy.srcIp());
}
- if (policy.selector().getCriterion(Criterion.Type.IP_PROTO) != null) {
- IPProtocolCriterion protocolCriterion =
- (IPProtocolCriterion) policy.selector().getCriterion(Criterion.Type.IP_PROTO);
- result.put(PROTO_TYPE, protocolCriterion.protocol());
- }
- if (policy.selector().getCriterion(Criterion.Type.TCP_SRC) != null) {
- TcpPortCriterion tcpPortCriterion =
- (TcpPortCriterion) policy.selector().getCriterion(Criterion.Type.TCP_SRC);
- result.put(SRC_PORT, tcpPortCriterion.toString());
- } else if (policy.selector().getCriterion(Criterion.Type.UDP_SRC) != null) {
- UdpPortCriterion udpPortCriterion =
- (UdpPortCriterion) policy.selector().getCriterion(Criterion.Type.UDP_SRC);
- result.put(SRC_PORT, udpPortCriterion.toString());
- }
- if (policy.selector().getCriterion(Criterion.Type.TCP_DST) != null) {
- TcpPortCriterion tcpPortCriterion =
- (TcpPortCriterion) policy.selector().getCriterion(Criterion.Type.TCP_DST);
- result.put(DST_PORT, tcpPortCriterion.toString());
- } else if (policy.selector().getCriterion(Criterion.Type.UDP_DST) != null) {
- UdpPortCriterion udpPortCriterion =
- (UdpPortCriterion) policy.selector().getCriterion(Criterion.Type.UDP_DST);
- result.put(DST_PORT, udpPortCriterion.toString());
- }
- if (policy.selector().getCriterion(Criterion.Type.IP_PROTO) != null) {
- IPProtocolCriterion protocolCriterion =
- (IPProtocolCriterion) policy.selector().getCriterion(Criterion.Type.IP_PROTO);
- result.put(PROTO_TYPE, protocolCriterion.toString());
+ if (policy.ipProto() != null) {
+ result.put(PROTO_TYPE, policy.ipProto());
}
+ int srcPort = policy.srcPort() & 0xffff;
+ if (policy.srcPort() != 0) {
+ result.put(SRC_PORT, srcPort);
+ }
+ int dstPort = policy.dstPort() & 0xffff;
+ if (policy.dstPort() != 0) {
+ result.put(DST_PORT, dstPort);
+ }
if (policy.type() == Policy.Type.TUNNEL_FLOW) {
result.put(TUNNEL_ID, ((TunnelPolicy) policy).tunnelId());
}
@@ -111,53 +80,43 @@
short srcPort = json.path(SRC_PORT).shortValue();
short dstPort = json.path(DST_PORT).shortValue();
- if (tunnelId != null) {
- TrafficSelector.Builder tsb = DefaultTrafficSelector.builder();
- tsb.matchEthType(Ethernet.TYPE_IPV4);
- if (dstIp != null && !dstIp.isEmpty()) {
- tsb.matchIPDst(IpPrefix.valueOf(dstIp));
- }
- if (srcIp != null && !srcIp.isEmpty()) {
- tsb.matchIPSrc(IpPrefix.valueOf(srcIp));
- }
- if (protoType != null && !protoType.isEmpty()) {
- Short ipProto = Short.valueOf(IpProtocol.valueOf(protoType).value());
- tsb.matchIPProtocol(ipProto.byteValue());
- if (IpProtocol.valueOf(protoType).equals(IpProtocol.TCP)) {
- if (srcPort != 0) {
- tsb.matchTcpSrc(srcPort);
- }
- if (dstPort != 0) {
- tsb.matchTcpDst(dstPort);
- }
- } else if (IpProtocol.valueOf(protoType).equals(IpProtocol.UDP)) {
- if (srcPort != 0) {
- tsb.matchUdpSrc(srcPort);
- }
- if (dstPort != 0) {
- tsb.matchUdpDst(dstPort);
- }
- }
- }
- TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(pid);
- if (tunnelId != null) {
- tpb.setTunnelId(tunnelId);
- }
- if (!json.path(PRIORITY).isMissingNode()) {
- tpb.setPriority(priority);
- }
- if (!json.path(TYPE).isMissingNode()) {
- tpb.setType(Policy.Type.valueOf(type));
- }
- tpb.setSelector(tsb.build());
-
- return tpb.build();
- } else {
- // TODO: handle more policy types
+ if (json.path(POLICY_ID).isMissingNode() || pid == null) {
+ // TODO: handle errors
return null;
}
+ TunnelPolicy.Builder tpb = TunnelPolicy.builder().setPolicyId(pid);
+ if (!json.path(TYPE).isMissingNode() && type != null &&
+ Policy.Type.valueOf(type).equals(Policy.Type.TUNNEL_FLOW)) {
+ if (json.path(TUNNEL_ID).isMissingNode() || tunnelId == null) {
+ return null;
+ }
+
+ tpb.setTunnelId(tunnelId);
+ tpb.setType(Policy.Type.valueOf(type));
+
+ if (!json.path(PRIORITY).isMissingNode()) {
+ tpb.setPriority(priority);
+ }
+ if (dstIp != null) {
+ tpb.setDstIp(dstIp);
+ }
+ if (srcIp != null) {
+ tpb.setSrcIp(srcIp);
+ }
+ if (protoType != null) {
+ tpb.setIpProto(protoType);
+ }
+ if (dstPort != 0) {
+ tpb.setDstPort(dstPort);
+ }
+ if (srcPort != 0) {
+ tpb.setSrcPort(srcPort);
+ }
+ }
+
+ return tpb.build();
}
}
diff --git a/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java b/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
index 97e836a..384ff0f 100644
--- a/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
+++ b/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
@@ -20,9 +20,7 @@
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.segmentrouting.Policy;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
import org.onosproject.segmentrouting.SegmentRoutingService;
-import org.onosproject.segmentrouting.TunnelPolicy;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -59,10 +57,9 @@
ObjectNode policyJson = (ObjectNode) mapper.readTree(input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
- if (policyInfo.type() == Policy.Type.TUNNEL_FLOW) {
- TunnelPolicy policy = new TunnelPolicy((SegmentRoutingManager) srService, (TunnelPolicy) policyInfo);
- srService.createPolicy(policy);
+ if (policyInfo.type() == Policy.Type.TUNNEL_FLOW) {
+ srService.createPolicy(policyInfo);
return Response.ok().build();
} else {
return Response.serverError().build();
@@ -78,6 +75,7 @@
Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
// TODO: Check the result
srService.removePolicy(policyInfo);
+
return Response.ok().build();
}
diff --git a/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java b/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
index c531e3f..4ed4b8c 100644
--- a/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
+++ b/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
@@ -19,8 +19,6 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.rest.AbstractWebResource;
-import org.onosproject.segmentrouting.DefaultTunnel;
-import org.onosproject.segmentrouting.SegmentRoutingManager;
import org.onosproject.segmentrouting.SegmentRoutingService;
import org.onosproject.segmentrouting.Tunnel;
@@ -59,9 +57,7 @@
ObjectNode tunnelJson = (ObjectNode) mapper.readTree(input);
SegmentRoutingService srService = get(SegmentRoutingService.class);
Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this);
- Tunnel tunnel = new DefaultTunnel((SegmentRoutingManager) srService,
- tunnelInfo.id(), tunnelInfo.labelIds());
- srService.createTunnel(tunnel);
+ srService.createTunnel(tunnelInfo);
return Response.ok().build();
}