ONOS-688 (ONOS-1835,1836,1837) :
- Implements features to create and remove tunnels and tunnel flow policies.
- Implements REST API to create/show/delete tunnels and policies.
- Supports only single instance for now.
- Fix "apply" actions to "write" actions of all flow rules
Change-Id: I3740ed82fed8eab4ab8b03839192da72d3e223f1
diff --git a/apps/segmentrouting/pom.xml b/apps/segmentrouting/pom.xml
index 71f888d..9b1eb57 100644
--- a/apps/segmentrouting/pom.xml
+++ b/apps/segmentrouting/pom.xml
@@ -32,6 +32,96 @@
<properties>
<onos.app.name>org.onosproject.segmentrouting</onos.app.name>
+ <web.context>/onos/segmentrouting</web.context>
</properties>
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <_wab>src/main/webapp/</_wab>
+ <Bundle-SymbolicName>
+ ${project.groupId}.${project.artifactId}
+ </Bundle-SymbolicName>
+ <Import-Package>
+ org.slf4j,
+ org.osgi.framework,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ com.sun.jersey.api.core,
+ com.sun.jersey.spi.container.servlet,
+ com.sun.jersey.server.impl.container.servlet,
+ com.fasterxml.jackson.databind,
+ com.fasterxml.jackson.databind.node,
+ com.fasterxml.jackson.core,
+ org.apache.karaf.shell.commands,
+ org.apache.commons.lang.math.*,
+ com.google.common.*,
+ org.onlab.packet.*,
+ org.onlab.rest.*,
+ org.onosproject.*,
+ org.onlab.util.*,
+ org.jboss.netty.util.*
+ </Import-Package>
+ <Web-ContextPath>${web.context}</Web-ContextPath>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
new file mode 100644
index 0000000..f1c0216
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.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 static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Tunnel class.
+ */
+public class DefaultTunnel implements Tunnel {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(DefaultTunnel.class);
+
+ private final String tunnelId;
+ 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;
+ }
+
+ /**
+ * Creates a Tunnel reference.
+ *
+ * @param tid Tunnel ID
+ * @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.groupId = -1;
+ }
+
+ /**
+ * Creates a new DefaultTunnel reference using the tunnel reference.
+ *
+ * @param tunnel DefaultTunnel reference
+ */
+ public DefaultTunnel(DefaultTunnel tunnel) {
+ this.srManager = tunnel.srManager;
+ this.tunnelId = tunnel.tunnelId;
+ this.labelIds = tunnel.labelIds;
+ this.config = tunnel.config;
+ this.groupId = tunnel.groupId;
+ }
+
+ @Override
+ public String id() {
+ return this.tunnelId;
+ }
+
+ @Override
+ public List<Integer> labelIds() {
+ return this.labelIds;
+ }
+
+ @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));
+ }
+
+ 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;
+ }
+ 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());
+ }
+ }
+ }
+ } else {
+ deviceIds.add(config.getDeviceId(sid));
+ }
+
+ NeighborSet ns = new NeighborSet(deviceIds, labelIds.get(2));
+ groupId = srManager.getNextObjectiveId(deviceId, ns);
+
+ return groupId;
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
index ad8c0a3..d82eb5e 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
@@ -1,5 +1,6 @@
package org.onosproject.segmentrouting;
+import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.IpPrefix;
@@ -44,6 +45,7 @@
boolean isEdge;
HashMap<PortNumber, Ip4Address> gatewayIps;
HashMap<PortNumber, Ip4Prefix> subnets;
+ List<SegmentRouterConfig.AdjacencySid> adjacencySids;
}
/**
@@ -80,8 +82,10 @@
info.gatewayIps.put(PortNumber.portNumber(s.getPortNo()),
Ip4Address.valueOf(gatewayIp));
}
+ info.adjacencySids = ((SegmentRouterConfig) cfg).getAdjacencySids();
this.deviceConfigMap.put(info.deviceId, info);
this.allSegmentIds.add(info.nodeSid);
+
}
}
@@ -352,4 +356,49 @@
return false;
}
+
+ /**
+ * Returns the ports corresponding to the adjacency Sid given.
+ *
+ * @param deviceId device identification of the router
+ * @param sid adjacency Sid
+ * @return list of port numbers
+ */
+ public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
+ if (deviceConfigMap.get(deviceId) != null) {
+ for (SegmentRouterConfig.AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
+ if (asid.getAdjSid() == sid) {
+ return asid.getPorts();
+ }
+ }
+ }
+
+ return Lists.newArrayList();
+ }
+
+ /**
+ * Check if the Sid given is whether adjacency Sid of the router device or not.
+ *
+ * @param deviceId device identification of the router
+ * @param sid Sid to check
+ * @return true if the Sid given is the adjacency Sid of the device,
+ * otherwise false
+ */
+ public boolean isAdjacencySid(DeviceId deviceId, int sid) {
+ if (deviceConfigMap.get(deviceId) != null) {
+ if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
+ return false;
+ } else {
+ for (SegmentRouterConfig.AdjacencySid asid:
+ deviceConfigMap.get(deviceId).adjacencySids) {
+ if (asid.getAdjSid() == sid) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/Policy.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/Policy.java
new file mode 100644
index 0000000..d47bc2e
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/Policy.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting;
+
+import org.onosproject.net.flow.TrafficSelector;
+
+/**
+ * Interface for Segment Routing Policy.
+ */
+public interface Policy {
+ /**
+ * Enums for policy type.
+ */
+ enum Type {
+ // Tunnel flow policy type
+ TUNNEL_FLOW,
+
+ // Load balancing policy type
+ LOADBALANCE,
+
+ // policy to avoid specific routers or links
+ AVOID,
+
+ // Access Control policy type
+ DENY
+ }
+
+ /**
+ * Returns the policy ID.
+ *
+ * @return policy ID
+ */
+ String id();
+
+ /**
+ * Returns the traffic selector object.
+ *
+ * @return TrafficSelector object
+ */
+ TrafficSelector selector();
+
+ /**
+ * Returns the priority of the policy.
+ *
+ * @return priority
+ */
+ int priority();
+
+ /**
+ * Returns the policy type.
+ *
+ * @return policy type
+ */
+ Type type();
+
+ /**
+ * Creates a policy.
+ *
+ * @return true if succeeds, false otherwise
+ */
+ boolean create();
+
+ /**
+ * Removes the policy.
+ *
+ * @return true if succeeds, false otherwise
+ */
+ boolean remove();
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
new file mode 100644
index 0000000..234dd20
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/PolicyHandler.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting;
+
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Segment Routing Policy Handler.
+ */
+public class PolicyHandler {
+
+ protected final Logger log = getLogger(getClass());
+
+ private final HashMap<String, Policy> policyMap;
+
+ /**
+ * Creates a reference.
+ */
+ public PolicyHandler() {
+ policyMap = new HashMap<>();
+ }
+
+ /**
+ * Returns the policies.
+ *
+ * @return policy list
+ */
+ public List<Policy> getPolicies() {
+ List<Policy> policies = new ArrayList<>();
+ policyMap.values().forEach(policy -> policies.add(
+ new TunnelPolicy((TunnelPolicy) policy)));
+
+ return policies;
+ }
+
+ /**
+ * Creates a policy using the policy information given.
+ *
+ * @param policy policy reference to create
+ */
+ public void createPolicy(Policy policy) {
+ policy.create();
+ policyMap.put(policy.id(), policy);
+ }
+
+ /**
+ * Removes the policy given.
+ *
+ * @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());
+ }
+ } else {
+ log.warn("Policy {} was not found", policyInfo.id());
+ }
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index 7092093..8c84e39a 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -98,7 +98,8 @@
sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32));
sbuilder.matchEthType(Ethernet.TYPE_IPV4);
- tbuilder.setEthDst(hostMac)
+ tbuilder.deferred()
+ .setEthDst(hostMac)
.setEthSrc(config.getDeviceMac(deviceId))
.setOutput(outPort);
@@ -163,10 +164,10 @@
// If the next hop is the same as the final destination, then MPLS label
// is not set.
if (nextHops.size() == 1 && nextHops.toArray()[0].equals(destSw)) {
- tbuilder.decNwTtl();
+ tbuilder.deferred().decNwTtl();
ns = new NeighborSet(nextHops);
} else {
- tbuilder.copyTtlOut();
+ tbuilder.deferred().copyTtlOut();
ns = new NeighborSet(nextHops, config.getSegmentId(destSw));
}
@@ -295,15 +296,15 @@
if (phpRequired) {
log.debug("getMplsForwardingObjective: php required");
- tbuilder.copyTtlIn();
+ tbuilder.deferred().copyTtlIn();
if (isBos) {
- tbuilder.popMpls(Ethernet.TYPE_IPV4).decNwTtl();
+ tbuilder.deferred().popMpls(Ethernet.TYPE_IPV4).decNwTtl();
} else {
- tbuilder.popMpls(Ethernet.MPLS_UNICAST).decMplsTtl();
+ tbuilder.deferred().popMpls(Ethernet.MPLS_UNICAST).decMplsTtl();
}
} else {
log.debug("getMplsForwardingObjective: php not required");
- tbuilder.decMplsTtl();
+ tbuilder.deferred().decMplsTtl();
}
if (!isECMPSupportedInTransitRouter() && !config.isEdgeDevice(deviceId)) {
@@ -313,7 +314,8 @@
log.warn("No link from {} to {}", deviceId, nextHops);
return null;
}
- tbuilder.setEthSrc(config.getDeviceMac(deviceId))
+ tbuilder.deferred()
+ .setEthSrc(config.getDeviceMac(deviceId))
.setEthDst(config.getDeviceMac(nextHop))
.setOutput(port);
fwdBuilder.withTreatment(tbuilder.build());
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 87282b4..23eb668 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -20,6 +20,7 @@
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.util.KryoNamespace;
@@ -60,6 +61,7 @@
import java.net.URI;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -69,8 +71,9 @@
import java.util.concurrent.TimeUnit;
@SuppressWarnings("ALL")
+@Service
@Component(immediate = true)
-public class SegmentRoutingManager {
+public class SegmentRoutingManager implements SegmentRoutingService {
private static Logger log = LoggerFactory
.getLogger(SegmentRoutingManager.class);
@@ -101,6 +104,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
+
protected ArpHandler arpHandler = null;
protected IcmpHandler icmpHandler = null;
protected IpHandler ipHandler = null;
@@ -108,7 +112,10 @@
protected ApplicationId appId;
protected DeviceConfiguration deviceConfiguration = null;
+
private DefaultRoutingHandler defaultRoutingHandler = null;
+ private TunnelHandler tunnelHandler = null;
+ private PolicyHandler policyHandler = null;
private InternalPacketProcessor processor = new InternalPacketProcessor();
private InternalEventHandler eventHandler = new InternalEventHandler();
@@ -165,6 +172,8 @@
ipHandler = new IpHandler(this);
routingRulePopulator = new RoutingRulePopulator(this);
defaultRoutingHandler = new DefaultRoutingHandler(this);
+ tunnelHandler = new TunnelHandler();
+ policyHandler = new PolicyHandler();
packetService.addProcessor(processor, PacketProcessor.ADVISOR_MAX + 2);
linkService.addListener(new InternalLinkListener());
@@ -187,6 +196,7 @@
defaultRoutingHandler.startPopulationProcess();
log.info("Started");
+
}
@Deactivate
@@ -196,6 +206,51 @@
log.info("Stopped");
}
+
+ @Override
+ public List<Tunnel> getTunnels() {
+ return tunnelHandler.getTunnels();
+ }
+
+ @Override
+ public void createTunnel(Tunnel tunnel) {
+ tunnelHandler.createTunnel(tunnel);
+ }
+
+ @Override
+ public void removeTunnel(Tunnel tunnel) {
+ for (Policy policy: policyHandler.getPolicies()) {
+ if (policy.type() == Policy.Type.TUNNEL_FLOW) {
+ TunnelPolicy tunnelPolicy = (TunnelPolicy) policy;
+ if (tunnelPolicy.tunnelId().equals(tunnel.id())) {
+ log.warn("Cannot remove the tunnel used by a policy");
+ return;
+ }
+ }
+ }
+ tunnelHandler.removeTunnel(tunnel);
+ }
+
+ @Override
+ public void removePolicy(Policy policy) {
+ policyHandler.removePolicy(policy);
+
+ }
+
+ @Override
+ public void createPolicy(Policy policy) {
+ policyHandler.createPolicy(policy);
+ }
+
+ @Override
+ public List<Policy> getPolicies() {
+ return policyHandler.getPolicies();
+ }
+
+ public Tunnel getTunnel(String tunnelId) {
+ return tunnelHandler.getTunnel(tunnelId);
+ }
+
/**
* Returns the GrouopKey object for the device and the NighborSet given.
*
@@ -211,6 +266,12 @@
return null;
}
+ /**
+ *
+ * @param deviceId
+ * @param ns
+ * @return
+ */
public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
if (groupHandlerMap.get(deviceId) != null) {
@@ -223,6 +284,16 @@
}
}
+ /**
+ *
+ * @param deviceId
+ * @param objectiveId
+ * @return
+ */
+ public boolean removeNextObjective(DeviceId deviceId, int objectiveId) {
+ return groupHandlerMap.get(deviceId).removeGroup(objectiveId);
+ }
+
private class InternalPacketProcessor implements PacketProcessor {
@Override
@@ -295,7 +366,7 @@
}
log.trace("numOfEvents {}, numOfEventHanlderScheduled {}", numOfEvents,
- numOfHandlerScheduled);
+ numOfHandlerScheduled);
}
@@ -403,4 +474,7 @@
groupHandler.portDown(port.number());
}
}
+
+
+
}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
new file mode 100644
index 0000000..2484369
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingService.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting;
+
+import java.util.List;
+
+/**
+ * Segment Routing Service for REST API.
+ */
+public interface SegmentRoutingService {
+
+ /**
+ * Returns all tunnels.
+ *
+ * @return list of tunnels
+ */
+ List<Tunnel> getTunnels();
+
+ /**
+ * Creates a tunnel.
+ *
+ * @param tunnel tunnel reference to create
+ */
+ void createTunnel(Tunnel tunnel);
+
+ /**
+ * Returns all policies.
+ *
+ * @return list of policy
+ */
+ List<Policy> getPolicies();
+
+ /**
+ * Creates a policy.
+ *
+ * @param policy policy reference to create
+ */
+ void createPolicy(Policy policy);
+
+ /**
+ * Removes a tunnel.
+ *
+ * @param tunnel tunnel reference to remove
+ */
+ void removeTunnel(Tunnel tunnel);
+
+ /**
+ * Removes a policy.
+ *
+ * @param policy policy reference to remove
+ */
+ void removePolicy(Policy policy);
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/Tunnel.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/Tunnel.java
new file mode 100644
index 0000000..0c35fba
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/Tunnel.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting;
+
+import org.onosproject.net.DeviceId;
+
+import java.util.List;
+
+/**
+ * Tunnel interface.
+ */
+public interface Tunnel {
+
+ /**
+ * Returns the tunnel ID.
+ *
+ * @return tunnel ID
+ */
+ String id();
+
+ /**
+ * Returns Segment IDs for the tunnel including source and destination.
+ *
+ * @return List of Node ID
+ */
+ 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
+ */
+ int groupId();
+
+ /**
+ * Returns the source device Id of the tunnel.
+ *
+ * @return source device Id
+ */
+ DeviceId source();
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
new file mode 100644
index 0000000..4a498c6
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting;
+
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Tunnel Handler.
+ */
+public class TunnelHandler {
+ protected final Logger log = getLogger(getClass());
+
+ private final HashMap<String, Tunnel> tunnelMap;
+
+ public TunnelHandler() {
+ tunnelMap = new HashMap<>();
+ }
+
+ /**
+ * Creates a tunnel.
+ *
+ * @param tunnel tunnel reference to create a tunnel
+ */
+ public void createTunnel(Tunnel tunnel) {
+ tunnel.create();
+ tunnelMap.put(tunnel.id(), tunnel);
+ }
+
+ /**
+ * Removes the tunnel with the tunnel ID given.
+ *
+ * @param tunnelInfo tunnel information to delete tunnels
+ */
+ public void removeTunnel(Tunnel tunnelInfo) {
+
+ Tunnel tunnel = tunnelMap.get(tunnelInfo.id());
+ if (tunnel != null) {
+ tunnel.remove();
+ tunnelMap.remove(tunnel.id());
+ } else {
+ log.warn("No tunnel found for tunnel ID {}", tunnelInfo.id());
+ }
+ }
+
+ /**
+ * Returns the tunnel with the tunnel ID given.
+ *
+ * @param tid Tunnel ID
+ * @return Tunnel reference
+ */
+ public Tunnel getTunnel(String tid) {
+ return tunnelMap.get(tid);
+ }
+
+ /**
+ * Returns all tunnels.
+ *
+ * @return list of Tunnels
+ */
+ public List<Tunnel> getTunnels() {
+ List<Tunnel> tunnels = new ArrayList<>();
+ tunnelMap.values().forEach(tunnel -> tunnels.add(
+ new DefaultTunnel((DefaultTunnel) tunnel)));
+
+ return tunnels;
+ }
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
new file mode 100644
index 0000000..c96c1f9
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelPolicy.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting;
+
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Tunnel Policy.
+ */
+public final class TunnelPolicy implements Policy {
+
+ 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 TunnelPolicy(SegmentRoutingManager srm, String policyId, Type type,
+ TrafficSelector selector, int priority, String tunnelId) {
+ this.srManager = srm;
+ this.id = checkNotNull(policyId);
+ this.type = type;
+ this.tunnelId = tunnelId;
+ this.priority = priority;
+ this.selector = selector;
+ }
+
+ /**
+ * Creates a TunnelPolicy reference.
+ *
+ * @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 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;
+ }
+
+ /**
+ * Returns the TunnelPolicy builder reference.
+ *
+ * @return TunnelPolicy builder
+ */
+ public static TunnelPolicy.Builder builder() {
+ return new Builder();
+ }
+
+ @Override
+ public String id() {
+ return this.id;
+ }
+
+ @Override
+ public TrafficSelector selector() {
+ return selector;
+ }
+
+ @Override
+ public int priority() {
+ return priority;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @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;
+ }
+
+ @Override
+ public boolean remove() {
+
+ Tunnel tunnel = srManager.getTunnel(tunnelId);
+
+ ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
+ .builder()
+ .fromApp(srManager.appId)
+ .makePermanent()
+ .withSelector(selector)
+ .withPriority(priority)
+ .nextStep(tunnel.groupId())
+ .withFlag(ForwardingObjective.Flag.VERSATILE);
+
+ srManager.flowObjectiveService.forward(tunnel.source(), fwdBuilder.remove());
+
+ return true;
+ }
+
+ /**
+ * Returns the tunnel ID of the policy.
+ *
+ * @return Tunnel ID
+ */
+ public String tunnelId() {
+ 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;
+
+ /**
+ * Sets the policy Id.
+ *
+ * @param id policy Id
+ * @return Builder object
+ */
+ public Builder setPolicyId(String id) {
+ this.id = id;
+
+ return this;
+ }
+
+ /**
+ * Sets the policy type.
+ *
+ * @param type policy type
+ * @return Builder object
+ */
+ public Builder setType(Type type) {
+ this.type = type;
+
+ return this;
+ }
+
+ /**
+ * Sets the TrafficSelector.
+ *
+ * @param selector TrafficSelector
+ * @return Builder object
+ */
+ public Builder setSelector(TrafficSelector selector) {
+ this.selector = selector;
+
+ return this;
+ }
+
+ /**
+ * Sets the priority of the policy.
+ *
+ * @param p priority
+ * @return Builder object
+ */
+ public Builder setPriority(int p) {
+ this.priority = p;
+
+ return this;
+ }
+
+ /**
+ * Sets the tunnel Id.
+ *
+ * @param tunnelId tunnel Id
+ * @return Builder object
+ */
+ public Builder setTunnelId(String tunnelId) {
+ this.tunnelId = tunnelId;
+
+ return this;
+ }
+
+ /**
+ * 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);
+ }
+ }
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index 1993d3f..4a25438 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
@@ -418,7 +419,12 @@
return nsSegmentIds;
}
- protected void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) {
+ /**
+ * Creates Groups from a set of NeighborSet given.
+ *
+ * @param nsSet a set of NeighborSet
+ */
+ public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) {
for (NeighborSet ns : nsSet) {
int nextId = flowObjectiveService.allocateNextId();
NextObjective.Builder nextObjBuilder = DefaultNextObjective
@@ -451,7 +457,7 @@
NextObjective nextObj = nextObjBuilder.add();
flowObjectiveService.next(deviceId, nextObj);
log.debug("createGroupsFromNeighborsets: Submited "
- + "next objective {} in device {}",
+ + "next objective {} in device {}",
nextId, deviceId);
nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns),
nextId);
@@ -462,4 +468,29 @@
return new DefaultGroupKey(kryo.build().serialize(obj));
}
+ /**
+ * Removes groups for the next objective ID given.
+ *
+ * @param objectiveId next objective ID to remove
+ * @return true if succeeds, false otherwise
+ */
+ public boolean removeGroup(int objectiveId) {
+
+ if (nsNextObjStore.containsValue(objectiveId)) {
+ NextObjective.Builder nextObjBuilder = DefaultNextObjective
+ .builder().withId(objectiveId)
+ .withType(NextObjective.Type.HASHED).fromApp(appId);
+ NextObjective nextObjective = nextObjBuilder.remove();
+ flowObjectiveService.next(deviceId, nextObjective);
+
+ for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: nsNextObjStore.entrySet()) {
+ if (entry.getValue().equals(objectiveId)) {
+ nsNextObjStore.remove(entry.getKey());
+ break;
+ }
+ }
+ }
+
+ return false;
+ }
}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
new file mode 100644
index 0000000..1f9e576
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyCodec.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.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.segmentrouting.Policy;
+import org.onosproject.segmentrouting.TunnelPolicy;
+
+public final class PolicyCodec extends JsonCodec<Policy> {
+
+ // JSON field names
+ private static final String POLICY_ID = "policy_id";
+ private static final String PRIORITY = "priority";
+ private static final String TYPE = "policy_type";
+ private static final String TUNNEL_ID = "tunnel_id";
+ private static final String DST_IP = "dst_ip";
+ private static final String SRC_IP = "src_ip";
+ private static final String PROTO_TYPE = "proto_type";
+
+ @Override
+ public ObjectNode encode(Policy policy, CodecContext context) {
+ final ObjectNode result = context.mapper().createObjectNode()
+ .put(POLICY_ID, policy.id());
+
+ 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.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.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.type() == Policy.Type.TUNNEL_FLOW) {
+ result.put(TUNNEL_ID, ((TunnelPolicy) policy).tunnelId());
+ }
+
+ return result;
+ }
+
+ @Override
+ public Policy decode(ObjectNode json, CodecContext context) {
+
+ String pid = json.path(POLICY_ID).asText();
+ String type = json.path(TYPE).asText();
+ int priority = json.path(PRIORITY).asInt();
+ String dstIp = json.path(DST_IP).asText();
+ String srcIp = json.path(SRC_IP).asText();
+ String tunnelId = json.path(TUNNEL_ID).asText();
+ String protoType = json.path(PROTO_TYPE).asText();
+
+ 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());
+ }
+
+ 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
+ return null;
+ }
+
+
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
new file mode 100644
index 0000000..97e836a
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/PolicyWebResource.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+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;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+@Path("policy")
+public class PolicyWebResource extends AbstractWebResource {
+
+ private static final PolicyCodec POLICY_CODEC = new PolicyCodec();
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPolicy() {
+ SegmentRoutingService srService = get(SegmentRoutingService.class);
+ List<Policy> policies = srService.getPolicies();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("policy", new PolicyCodec().encode(policies, this));
+
+ return ok(result.toString()).build();
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response createPolicy(InputStream input) throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ 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);
+
+ return Response.ok().build();
+ } else {
+ return Response.serverError().build();
+ }
+ }
+
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response removePolicy(InputStream input) throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode policyJson = (ObjectNode) mapper.readTree(input);
+ SegmentRoutingService srService = get(SegmentRoutingService.class);
+ Policy policyInfo = POLICY_CODEC.decode(policyJson, this);
+ // TODO: Check the result
+ srService.removePolicy(policyInfo);
+ return Response.ok().build();
+
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java
new file mode 100644
index 0000000..2f85afd
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelCodec.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.segmentrouting.DefaultTunnel;
+import org.onosproject.segmentrouting.Tunnel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public final class TunnelCodec extends JsonCodec<Tunnel> {
+
+ // JSON field names
+ private static final String TUNNEL_ID = "tunnel_id";
+ private static final String GROUP_ID = "group_id";
+ private static final String LABEL_PATH = "label_path";
+
+ @Override
+ public ObjectNode encode(Tunnel tunnel, CodecContext context) {
+ final ObjectNode result = context.mapper().createObjectNode()
+ .put(TUNNEL_ID, tunnel.id());
+
+ result.put(GROUP_ID, tunnel.groupId());
+
+ final ArrayNode jsonLabelIds = result.putArray(LABEL_PATH);
+
+ tunnel.labelIds().forEach(label -> jsonLabelIds.add(label.intValue()));
+
+ return result;
+ }
+
+ @Override
+ public DefaultTunnel decode(ObjectNode json, CodecContext context) {
+
+ String tid = json.path(TUNNEL_ID).asText();
+ List<Integer> labels = new ArrayList<>();
+
+ if (!json.path(LABEL_PATH).isMissingNode()) {
+ ArrayNode labelArray = (ArrayNode) json.path(LABEL_PATH);
+ for (JsonNode o : labelArray) {
+ labels.add(o.asInt());
+ }
+ }
+
+ return new DefaultTunnel(tid, labels);
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
new file mode 100644
index 0000000..c531e3f
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/web/TunnelWebResource.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * 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.segmentrouting.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+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;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+@Path("tunnel")
+public class TunnelWebResource extends AbstractWebResource {
+
+ private static final TunnelCodec TUNNEL_CODEC = new TunnelCodec();
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getTunnel() {
+ SegmentRoutingService srService = get(SegmentRoutingService.class);
+ List<Tunnel> tunnels = srService.getTunnels();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("tunnel", new TunnelCodec().encode(tunnels, this));
+
+ return ok(result.toString()).build();
+ }
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response createTunnel(InputStream input) throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ 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);
+
+ return Response.ok().build();
+ }
+
+ @DELETE
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response removeTunnel(InputStream input) throws IOException {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode tunnelJson = (ObjectNode) mapper.readTree(input);
+ SegmentRoutingService srService = get(SegmentRoutingService.class);
+ Tunnel tunnelInfo = TUNNEL_CODEC.decode(tunnelJson, this);
+ srService.removeTunnel(tunnelInfo);
+
+ return Response.ok().build();
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/webapp/WEB-INF/web.xml b/apps/segmentrouting/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..94c0d7d
--- /dev/null
+++ b/apps/segmentrouting/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ 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.
+ -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ id="ONOS" version="2.5">
+ <display-name>Segment Routing REST API v1.0</display-name>
+
+ <servlet>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
+ <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
+ </init-param>
+ <init-param>
+ <param-name>com.sun.jersey.config.property.classnames</param-name>
+ <param-value>
+ org.onosproject.segmentrouting.web.TunnelWebResource,
+ org.onosproject.segmentrouting.web.PolicyWebResource
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>