aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps
diff options
context:
space:
mode:
authorAshlee Young <ashlee@wildernessvoice.com>2015-11-05 14:00:42 -0800
committerAshlee Young <ashlee@wildernessvoice.com>2015-11-05 14:00:42 -0800
commitb34f82bf11934fc6b938ef997d536a7ccea76c36 (patch)
tree10559ebf65962abb741883ca9d23aec241ced504 /framework/src/onos/apps
parent2cdecb8c41956d7dd8ab5d59591ebc21f3c64a9e (diff)
Updates ONOS tree to checkin id ca9cc8e28eba18da77f4fa021fb7c3a3f76e5d44
upstream. Change-Id: I49f8e41733afea8101ec50c0102213c8d18949ae Signed-off-by: Ashlee Young <ashlee@wildernessvoice.com>
Diffstat (limited to 'framework/src/onos/apps')
-rw-r--r--framework/src/onos/apps/bgprouter/src/main/java/org/onosproject/bgprouter/NextHopGroupKey.java2
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/cli/PIMShowCommand.java22
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMComponent.java121
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java339
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java260
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfacesCodec.java (renamed from framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighborsCodec.java)15
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java52
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbors.java395
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMPacketHandler.java229
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMTimer.java19
-rw-r--r--framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteEntry.java2
-rw-r--r--framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java42
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java4
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java68
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/BindingHostId.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java7
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PhysicalNetwork.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java22
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java23
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SecurityGroup.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SegmentationId.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SubnetId.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantId.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantNetworkId.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/VirtualPortId.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.java32
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java146
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java80
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java146
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/package-info.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/package-info.java)4
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java146
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java8
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/PortChainIdTest.java65
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/PortPairIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupIdTest.java66
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java8
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java157
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java163
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java161
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.java)6
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java6
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java94
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml4
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java94
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java77
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json9
51 files changed, 2676 insertions, 673 deletions
diff --git a/framework/src/onos/apps/bgprouter/src/main/java/org/onosproject/bgprouter/NextHopGroupKey.java b/framework/src/onos/apps/bgprouter/src/main/java/org/onosproject/bgprouter/NextHopGroupKey.java
index 82a45a08..cd4c4e9a 100644
--- a/framework/src/onos/apps/bgprouter/src/main/java/org/onosproject/bgprouter/NextHopGroupKey.java
+++ b/framework/src/onos/apps/bgprouter/src/main/java/org/onosproject/bgprouter/NextHopGroupKey.java
@@ -61,7 +61,7 @@ public class NextHopGroupKey {
@Override
public int hashCode() {
- return Objects.hash(address);
+ return address.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/cli/PIMShowCommand.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/cli/PIMShowCommand.java
index 0ef7e389..6bd563b6 100644
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/cli/PIMShowCommand.java
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/cli/PIMShowCommand.java
@@ -18,30 +18,30 @@ package org.onosproject.pim.cli;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.pim.impl.PIMNeighbors;
-import org.onosproject.pim.impl.PIMNeighborsCodec;
+import org.onosproject.pim.impl.PIMInterface;
+import org.onosproject.pim.impl.PIMInterfaces;
+import org.onosproject.pim.impl.PIMInterfacesCodec;
-import java.util.HashMap;
+import java.util.Collection;
-@Command(scope = "onos", name = "pim-neighbors", description = "Displays the pim neighbors")
+@Command(scope = "onos", name = "pim-interfaces", description = "Displays the pim interfaces")
public class PIMShowCommand extends AbstractShellCommand {
// prints either the json or cli version of the hash map connect point
- // neighbors from the PIMNeighbors class.
+ // neighbors from the PIMInterfaces class.
@Override
protected void execute() {
// grab connect point neighbors hash map to send in to json encoder.
- HashMap<ConnectPoint, PIMNeighbors> pimNbrs = PIMNeighbors.getConnectPointNeighbors();
+ Collection<PIMInterface> pimIntfs = PIMInterfaces.getInstance().getInterfaces();
if (outputJson()) {
- print("%s", json(pimNbrs));
+ print("%s", json(pimIntfs));
} else {
- print(PIMNeighbors.printPimNeighbors());
+ print(PIMInterfaces.getInstance().printInterfaces());
}
}
- private JsonNode json(HashMap<ConnectPoint, PIMNeighbors> pimNbrs) {
- return new PIMNeighborsCodec().encode(pimNbrs, this);
+ private JsonNode json(Collection<PIMInterface> pimIntfs) {
+ return new PIMInterfacesCodec().encode(pimIntfs, this);
}
} \ No newline at end of file
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMComponent.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMComponent.java
index bd5e1486..1a2d6f54 100644
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMComponent.java
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMComponent.java
@@ -22,132 +22,61 @@ import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.PIM;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketPriority;
-import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
/**
- * Protocol Independent Multicast Emulation.
+ * Protocol Independent Multicast (PIM) Emulation. This component is responsible
+ * for reference the services this PIM module is going to need, then initializing
+ * the corresponding utility classes.
*/
@Component(immediate = true)
public class PIMComponent {
private final Logger log = getLogger(getClass());
+ // Register to receive PIM packets, used to send packets as well
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
+ // Get the appId
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
- private PIMPacketProcessor processor = new PIMPacketProcessor();
+ // Get the network configuration updates
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ // Access defined network (IP) interfaces
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected InterfaceService interfaceService;
+
private static ApplicationId appId;
+ private PIMInterfaces pimInterfaces;
+ private PIMPacketHandler pimPacketHandler;
+
@Activate
public void activate() {
appId = coreService.registerApplication("org.onosproject.pim");
- packetService.addProcessor(processor, PacketProcessor.director(1));
+ // Initialize the Packet Handler class
+ pimPacketHandler = PIMPacketHandler.getInstance();
+ pimPacketHandler.initialize(packetService, appId);
- // Build a traffic selector for all multicast traffic
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPProtocol(IPv4.PROTOCOL_PIM);
- packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
+ // Initialize the Interface class
+ pimInterfaces = PIMInterfaces.getInstance();
+ pimInterfaces.initialize(configService, interfaceService);
log.info("Started");
}
@Deactivate
public void deactivate() {
- packetService.removeProcessor(processor);
- processor = null;
+ PIMPacketHandler.getInstance().stop();
log.info("Stopped");
}
-
- /**
- * Packet processor responsible for handling IGMP packets.
- */
- private class PIMPacketProcessor implements PacketProcessor {
-
- @Override
- public void process(PacketContext context) {
- // Stop processing if the packet has been handled, since we
- // can't do any more to it.
- if (context.isHandled()) {
- return;
- }
-
- InboundPacket pkt = context.inPacket();
- if (pkt == null) {
- return;
- }
-
- Ethernet ethPkt = pkt.parsed();
- if (ethPkt == null) {
- return;
- }
-
- /*
- * IPv6 MLD packets are handled by ICMP6. We'll only deal
- * with IPv4.
- */
- if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
- return;
- }
-
- IPv4 ip = (IPv4) ethPkt.getPayload();
- IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
- IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
- log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
- "\tingress port: " + context.inPacket().receivedFrom().toString());
-
- if (ip.getProtocol() != IPv4.PROTOCOL_PIM) {
- log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol());
- return;
- }
-
- // TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address.
- IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
- IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
-
- PIM pim = (PIM) ip.getPayload();
- switch (pim.getPimMsgType()) {
-
- case PIM.TYPE_HELLO:
- PIMNeighbors.processHello(ethPkt, context.inPacket().receivedFrom());
- break;
-
- case PIM.TYPE_JOIN_PRUNE_REQUEST:
- // Create the function
- break;
-
- case PIM.TYPE_ASSERT:
- case PIM.TYPE_BOOTSTRAP:
- case PIM.TYPE_CANDIDATE_RP_ADV:
- case PIM.TYPE_GRAFT:
- case PIM.TYPE_GRAFT_ACK:
- case PIM.TYPE_REGISTER:
- case PIM.TYPE_REGISTER_STOP:
- log.debug("Unsupported PIM message type: " + pim.getPimMsgType());
- break;
-
- default:
- log.debug("Unkown PIM message type: " + pim.getPimMsgType());
- break;
- }
- }
- }
}
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
new file mode 100644
index 00000000..28d1e8ba
--- /dev/null
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterface.java
@@ -0,0 +1,339 @@
+/*
+ * 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.pim.impl;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.PIM;
+import org.onlab.packet.pim.PIMHello;
+import org.onlab.packet.pim.PIMHelloOption;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.host.InterfaceIpAddress;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * The PIM Interface is a wrapper around a ConnectPoint and used to provide
+ * hello options values when "talking" with PIM other PIM routers.
+ */
+public class PIMInterface {
+ private static Logger log = LoggerFactory.getLogger("PIMInterfaces");
+
+ // Interface from the interface subsystem
+ private Interface theInterface;
+
+ // The list of PIM neighbors adjacent to this interface
+ private Map<IpAddress, PIMNeighbor> neighbors = new HashMap<>();
+
+ // The designatedRouter for this LAN
+ private PIMNeighbor designatedRouter;
+
+ // The priority we use on this ConnectPoint.
+ private int priority = PIMHelloOption.DEFAULT_PRIORITY;
+
+ // The holdtime we are sending out.
+ private int holdtime = PIMHelloOption.DEFAULT_HOLDTIME;
+
+ // Then generation ID we are sending out. 0 means we need to generate a new random ID
+ private int genid = PIMHelloOption.DEFAULT_GENID;
+
+ // Our default prune delay
+ private int prunedelay = PIMHelloOption.DEFAULT_PRUNEDELAY;
+
+ /**
+ * Create a PIMInterface.
+ */
+ public PIMInterface(Interface intf) {
+
+ log.debug("Adding an interface: " + intf.toString() + "\n");
+ this.theInterface = intf;
+
+ // Send a hello to let our neighbors know we are alive
+ sendHello();
+ }
+
+ /**
+ * Get the PIM Interface.
+ *
+ * @return the PIM Interface
+ */
+ public Interface getInterface() {
+ return theInterface;
+ }
+
+ /**
+ * Getter for our IP address.
+ *
+ * @return our IP address.
+ */
+ public IpAddress getIpAddress() {
+ if (theInterface.ipAddresses().isEmpty()) {
+ return null;
+ }
+
+ // We will just assume the first interface on the list
+ IpAddress ipaddr = null;
+ for (InterfaceIpAddress ifipaddr : theInterface.ipAddresses()) {
+ ipaddr = ifipaddr.ipAddress();
+ break;
+ }
+ return ipaddr;
+ }
+
+ /**
+ * Get our priority.
+ *
+ * @return our priority.
+ */
+ public int getPriority() {
+ return this.priority;
+ }
+
+ /**
+ * Get the designated router on this connection.
+ *
+ * @return the PIMNeighbor representing the DR
+ */
+ public PIMNeighbor getDesignatedRouter() {
+ return designatedRouter;
+ }
+
+ /**
+ * Are we the DR on this CP?
+ *
+ * @return true if we are, false if not
+ */
+ public boolean areWeDr() {
+ return (designatedRouter != null &&
+ designatedRouter.getPrimaryAddr().equals(this.getIpAddress()));
+ }
+
+ /**
+ * Return a collection of PIM Neighbors.
+ *
+ * @return the collection of PIM Neighbors
+ */
+ public Collection<PIMNeighbor> getNeighbors() {
+ return this.neighbors.values();
+ }
+
+ /**
+ * Find the neighbor with the given IP address on this CP.
+ *
+ * @param ipaddr the IP address of the neighbor we are interested in
+ * @return the pim neighbor if it exists
+ */
+ public PIMNeighbor findNeighbor(IpAddress ipaddr) {
+ PIMNeighbor nbr = neighbors.get(ipaddr);
+ return nbr;
+ }
+
+ /**
+ * Add a new PIM neighbor to this list.
+ *
+ * @param nbr the neighbor to be added.
+ */
+ public void addNeighbor(PIMNeighbor nbr) {
+ if (neighbors.containsKey(nbr.getPrimaryAddr())) {
+
+ log.debug("We are adding a neighbor that already exists: {}", nbr.toString());
+ neighbors.remove(nbr.getPrimaryAddr());
+ }
+ neighbors.put(nbr.getPrimaryAddr(), nbr);
+ }
+
+ /**
+ * Remove the neighbor from our neighbor list.
+ *
+ * @param ipaddr the IP address of the neighbor to remove
+ */
+ public void removeNeighbor(IpAddress ipaddr) {
+
+ if (neighbors.containsKey(ipaddr)) {
+ neighbors.remove(ipaddr);
+ }
+ this.electDR();
+ }
+
+ /**
+ * Remove the given neighbor from the neighbor list.
+ *
+ * @param nbr the nbr to be removed.
+ */
+ public void removeNeighbor(PIMNeighbor nbr) {
+
+ neighbors.remove(nbr.getPrimaryAddr(), nbr);
+ this.electDR();
+ }
+
+ /**
+ * Elect a new DR on this ConnectPoint.
+ *
+ * @return the PIM Neighbor that wins
+ */
+ public PIMNeighbor electDR() {
+
+ for (PIMNeighbor nbr : this.neighbors.values()) {
+ if (this.designatedRouter == null) {
+ this.designatedRouter = nbr;
+ continue;
+ }
+
+ if (nbr.getPriority() > this.designatedRouter.getPriority()) {
+ this.designatedRouter = nbr;
+ continue;
+ }
+
+ // We could sort in ascending order
+ if (this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) {
+ this.designatedRouter = nbr;
+ continue;
+ }
+ }
+
+ return this.designatedRouter;
+ }
+
+ /**
+ * Elect a new DR given the new neighbor.
+ *
+ * @param nbr the new neighbor to use in DR election.
+ * @return the PIM Neighbor that wins DR election
+ */
+ public PIMNeighbor electDR(PIMNeighbor nbr) {
+
+ // Make sure I have
+ if (this.designatedRouter == null ||
+ this.designatedRouter.getPriority() < nbr.getPriority() ||
+ this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) {
+ this.designatedRouter = nbr;
+ }
+ return this.designatedRouter;
+ }
+
+ /**
+ * Find or create a pim neighbor with a given ip address and connect point.
+ *
+ * @param ipaddr of the pim neighbor
+ * @param mac The mac address of our sending neighbor
+ * @return an existing or new PIM neighbor
+ */
+ public PIMNeighbor findOrCreate(IpAddress ipaddr, MacAddress mac) {
+ PIMNeighbor nbr = this.findNeighbor(ipaddr);
+ if (nbr == null) {
+ nbr = new PIMNeighbor(ipaddr, mac, this);
+ this.addNeighbor(nbr);
+ this.electDR(nbr);
+ }
+ return nbr;
+ }
+
+ /**
+ * Process a hello packet received on this Interface.
+ *
+ * @param ethPkt the ethernet packet containing the hello message
+ * @param cp the ConnectPoint of this interface
+ */
+ public void processHello(Ethernet ethPkt, ConnectPoint cp) {
+ checkNotNull(ethPkt);
+ checkNotNull(cp);
+
+ MacAddress srcmac = ethPkt.getSourceMAC();
+ IPv4 ip = (IPv4) ethPkt.getPayload();
+ Ip4Address srcip = Ip4Address.valueOf(ip.getSourceAddress());
+
+ PIM pim = (PIM) ip.getPayload();
+ checkNotNull(pim);
+
+ PIMHello hello = (PIMHello) pim.getPayload();
+ checkNotNull(hello);
+
+ PIMNeighbor nbr = this.findOrCreate(srcip, srcmac);
+ if (nbr == null) {
+ log.error("Could not create a neighbor for: {1}", srcip.toString());
+ return;
+ }
+
+ ConnectPoint icp = theInterface.connectPoint();
+ checkNotNull(icp);
+ if (!cp.equals(icp)) {
+ log.error("PIM Hello message received from {} on incorrect interface {}",
+ nbr.getPrimaryAddr(), this.toString());
+ return;
+ }
+ nbr.refresh(hello);
+ }
+
+ /**
+ * Send a hello packet from this interface.
+ */
+ public void sendHello() {
+ PIM pim = new PIM();
+ PIMHello hello = new PIMHello();
+
+ // Create a PIM Hello
+ pim = new PIM();
+ pim.setVersion((byte) 2);
+ pim.setPIMType((byte) PIM.TYPE_HELLO);
+ pim.setChecksum((short) 0);
+
+ hello = new PIMHello();
+ hello.createDefaultOptions();
+ pim.setPayload(hello);
+ hello.setParent(pim);
+
+ log.debug("Sending hello: \n");
+ PIMPacketHandler.getInstance().sendPacket(pim, this);
+ }
+
+ /**
+ * prints the connectPointNeighbors list with each neighbor list.
+ *
+ * @return string of neighbors.
+ */
+ public String printNeighbors() {
+ String out = "PIM Neighbors Table: \n";
+ for (PIMNeighbor nbr : this.neighbors.values()) {
+ out += "\t" + nbr.toString();
+ }
+ return out;
+ }
+
+ @Override
+ public String toString() {
+ IpAddress ipaddr = this.getIpAddress();
+ String out = "PIM Neighbors: ";
+ if (ipaddr != null) {
+ out += "IP: " + ipaddr.toString();
+ } else {
+ out += "IP: *Null*";
+ }
+ out += "\tPR: " + String.valueOf(this.priority) + "\n";
+ return out;
+ }
+
+}
+
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java
new file mode 100644
index 00000000..e33d5aa1
--- /dev/null
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java
@@ -0,0 +1,260 @@
+/*
+ * 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.pim.impl;
+
+import org.jboss.netty.util.Timeout;
+import org.jboss.netty.util.TimerTask;
+import org.onosproject.incubator.net.config.basics.ConfigException;
+import org.onosproject.incubator.net.config.basics.InterfaceConfig;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.incubator.net.intf.InterfaceService;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * PIMInterfaces is a collection of all neighbors we have received
+ * PIM hello messages from. The main structure is a HashMap indexed
+ * by ConnectPoint with another HashMap indexed on the PIM neighbors
+ * IPAddress, it contains all PIM neighbors attached on that ConnectPoint.
+ */
+public final class PIMInterfaces {
+
+ private Logger log = LoggerFactory.getLogger("PIMInterfaces");
+
+ private static PIMInterfaces instance = null;
+
+ // Used to listen to network configuration changes
+ private NetworkConfigService configService;
+
+ // Used to access IP Interface definitions for our segment
+ private InterfaceService interfaceService;
+
+ // Internal class used to listen for network configuration changes
+ private InternalConfigListener configListener = new InternalConfigListener();
+
+ // This is the global container for all PIM Interfaces indexed by ConnectPoints.
+ private Map<ConnectPoint, PIMInterface> interfaces = new HashMap<>();
+
+ // Default hello message interval
+ private int helloMessageInterval = 60;
+
+ // Timer used to send hello messages on this interface
+ private Timeout helloTimer;
+
+ // Required by a utility class
+ private PIMInterfaces() {}
+
+ /**
+ * Get the instance of PIMInterfaces. Create the instance if needed.
+ *
+ * @return PIMInterface instance
+ */
+ public static PIMInterfaces getInstance() {
+ if (null == instance) {
+ instance = new PIMInterfaces();
+ }
+ return instance;
+ }
+
+ // Initialize the services
+ public void initialize(NetworkConfigService cs, InterfaceService is) {
+ configService = cs;
+ interfaceService = is;
+
+ // Initialize interfaces if they already exist
+ initInterfaces();
+
+ // Listen for network config changes
+ configService.addListener(configListener);
+ }
+
+ /**
+ * Listener for network config events.
+ */
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ private void updateInterfaces(InterfaceConfig config) {
+ Set<Interface> intfs;
+ try {
+ intfs = config.getInterfaces();
+ } catch (ConfigException e) {
+ log.error(e.toString());
+ return;
+ }
+ for (Interface intf : intfs) {
+ addInterface(intf);
+ }
+ }
+
+ /**
+ * Remove the PIMInterface represented by the ConnectPoint. If the
+ * PIMInterface does not exist this function is a no-op.
+ *
+ * @param cp The connectPoint representing the PIMInterface to be removed.
+ */
+ private void removeInterface(ConnectPoint cp) {
+ removeInterface(cp);
+ }
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ log.debug("Config updated: " + event.toString() + "\n");
+ if (event.configClass() == InterfaceConfig.class) {
+ InterfaceConfig config =
+ configService.getConfig((ConnectPoint) event.subject(), InterfaceConfig.class);
+ updateInterfaces(config);
+ }
+ break;
+ case CONFIG_REMOVED:
+ if (event.configClass() == InterfaceConfig.class) {
+ removeInterface((ConnectPoint) event.subject());
+ }
+ break;
+ case CONFIG_REGISTERED:
+ case CONFIG_UNREGISTERED:
+ default:
+ break;
+ }
+ }
+ }
+
+ // Configure interfaces if they already exist.
+ private void initInterfaces() {
+ Set<Interface> intfs = interfaceService.getInterfaces();
+ for (Interface intf : intfs) {
+ log.debug("Adding interface: " + intf.toString() + "\n");
+ addInterface(intf);
+ }
+ }
+
+ /**
+ * Create a PIM Interface and add to our interfaces list.
+ *
+ * @param intf the interface to add
+ * @return the PIMInterface
+ */
+ public PIMInterface addInterface(Interface intf) {
+ PIMInterface pif = new PIMInterface(intf);
+ interfaces.put(intf.connectPoint(), pif);
+
+ // If we have added our first interface start the hello timer.
+ if (interfaces.size() == 1) {
+ startHelloTimer();
+ }
+
+ // Return this interface
+ return pif;
+ }
+
+ /**
+ * Remove the PIMInterface from the given ConnectPoint.
+ *
+ * @param cp the ConnectPoint indexing the PIMInterface to be removed.
+ */
+ public void removeInterface(ConnectPoint cp) {
+ if (interfaces.containsKey(cp)) {
+ interfaces.remove(cp);
+ }
+
+ if (interfaces.size() == 0) {
+ PIMTimer.stop();
+ }
+ }
+
+ /**
+ * Return a collection of PIMInterfaces for use by the PIM Interface codec.
+ *
+ * @return the collection of PIMInterfaces
+ */
+ public Collection<PIMInterface> getInterfaces() {
+ return interfaces.values();
+ }
+
+ /**
+ * Get the PIM Interface indexed by the given ConnectPoint.
+ *
+ * @param cp the connect point
+ * @return the PIMInterface if it exists, NULL if not
+ */
+ public PIMInterface getInterface(ConnectPoint cp) {
+ return interfaces.get(cp);
+ }
+
+ /**
+ * Return a string of PIMInterfaces for the cli command.
+ *
+ * @return a string representing PIM interfaces
+ */
+ public String printInterfaces() {
+ String str = "";
+ for (PIMInterface pi : interfaces.values()) {
+ str += pi.toString();
+ }
+ return str;
+ }
+
+ /* ---------------------------------- PIM Hello Timer ----------------------------------- */
+
+ /**
+ * Start a new hello timer for this interface.
+ */
+ private void startHelloTimer() {
+ helloTimer = PIMTimer.getTimer().newTimeout(
+ new HelloTimer(),
+ helloMessageInterval,
+ TimeUnit.SECONDS);
+
+ log.debug("Started Hello Timer");
+ }
+
+ /**
+ * This inner class handles transmitting a PIM hello message on this ConnectPoint.
+ */
+ private final class HelloTimer implements TimerTask {
+
+ HelloTimer() {
+ }
+
+ @Override
+ public void run(Timeout timeout) throws Exception {
+
+ log.debug("Running Hello Timer\n");
+ // Technically we should not send all hello's in synch..
+ for (PIMInterface pi : interfaces.values()) {
+ pi.sendHello();
+ }
+
+ // restart the hello timer
+ if (interfaces.size() > 0) {
+ startHelloTimer();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighborsCodec.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfacesCodec.java
index ee62eb79..ddd7a597 100644
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighborsCodec.java
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfacesCodec.java
@@ -19,16 +19,15 @@ import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
-import org.onosproject.net.ConnectPoint;
-import java.util.HashMap;
+import java.util.Collection;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* PIM neighbors Codec.
*/
-public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighbors>> {
+public class PIMInterfacesCodec extends JsonCodec<Collection<PIMInterface>> {
// JSON field names
//Return Name
private static final String CPNBRLIST = "connect_point_list";
@@ -53,22 +52,22 @@ public class PIMNeighborsCodec extends JsonCodec<HashMap<ConnectPoint, PIMNeighb
* @return Encoded neighbors used by CLI and REST
*/
@Override
- public ObjectNode encode(HashMap<ConnectPoint, PIMNeighbors> cpn, CodecContext context) {
+ public ObjectNode encode(Collection<PIMInterface> cpn, CodecContext context) {
checkNotNull(cpn, "Pim Neighbors cannot be null");
ObjectNode pimNbrJsonCodec = context.mapper().createObjectNode();
ArrayNode cpnList = context.mapper().createArrayNode();
- for (PIMNeighbors pn: cpn.values()) {
+ for (PIMInterface pn: cpn) {
// get the PimNeighbors Obj, contains Neighbors list
// create the json object for a single Entry in the Neighbors list
ObjectNode cp = context.mapper().createObjectNode();
- cp.put(IP, pn.getOurIpAddress().toString());
- cp.put(PRIORITY, String.valueOf(pn.getOurPriority()));
+ cp.put(IP, pn.getIpAddress().toString());
+ cp.put(PRIORITY, String.valueOf(pn.getPriority()));
// create the array for the neighbors list
ArrayNode nbrsList = context.mapper().createArrayNode();
- for (PIMNeighbor nbr : pn.getOurNeighborsList().values()) {
+ for (PIMNeighbor nbr : pn.getNeighbors()) {
nbrsList.add(neighbor(nbr, context));
}
// adds pim neighbor to list
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java
index 1a96138f..73d1598a 100644
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbor.java
@@ -60,22 +60,20 @@ public class PIMNeighbor {
// Timeout for this neighbor
private volatile Timeout timeout;
- private boolean reelect = false;
-
// A back pointer the neighbors list this neighbor belongs to.
- private PIMNeighbors neighbors;
+ private PIMInterface pimInterface;
/**
* Construct this neighbor from the address and connect point.
*
* @param ipaddr IP Address of neighbor
* @param macaddr MAC Address of the neighbor
- * @param cp The ConnectPoint of this neighbor
+ * @param pimInterface The PIMInterface of this neighbor
*/
- public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, ConnectPoint cp) {
+ public PIMNeighbor(IpAddress ipaddr, MacAddress macaddr, PIMInterface pimInterface) {
this.macAddress = macaddr;
this.primaryAddr = ipaddr;
- this.connectPoint = cp;
+ this.pimInterface = pimInterface;
this.resetTimeout();
}
@@ -174,30 +172,12 @@ public class PIMNeighbor {
*
* @return the ConnectPoint
*/
- public ConnectPoint getConnectPoint() {
- return connectPoint;
- }
-
- /**
- * Set the ConnectPoint this router is connected to.
- *
- * @param connectPoint the ConnectPoint this router is connected to.
- */
- public void setConnectPoint(ConnectPoint connectPoint) {
- this.connectPoint = connectPoint;
+ public PIMInterface getPimInterface() {
+ return pimInterface;
}
/**
- * Set a back pointer to the neighbors list this neighbor is a member of.
- *
- * @param neighbors the neighbor list this neighbor belongs to
- */
- public void setNeighbors(PIMNeighbors neighbors) {
- this.neighbors = neighbors;
- }
-
- /**
- * We have received a fresh hello from a neighbor, now we need to process it.
+ * We have received a fresh hello from this neighbor, now we need to process it.
* Depending on the values received in the the hello options may force a
* re-election process.
*
@@ -208,17 +188,19 @@ public class PIMNeighbor {
public void refresh(PIMHello hello) {
checkNotNull(hello);
+ boolean reelect = false;
for (PIMHelloOption opt : hello.getOptions().values()) {
int len = opt.getOptLength();
- byte [] value = new byte[len];
- ByteBuffer bb = ByteBuffer.wrap(value);
+ ByteBuffer bb = ByteBuffer.wrap(opt.getValue());
switch (opt.getOptType()) {
case PIMHelloOption.OPT_GENID:
int newid = bb.getInt();
if (this.genId != newid) {
- // TODO: we have a newly rebooted neighbor. Send them our joins.
+
+ // We have a newly rebooted neighbor, this is where we would
+ // send them our joins.
this.genId = newid;
}
break;
@@ -228,7 +210,7 @@ public class PIMNeighbor {
if (this.priority != newpri) {
// The priorities have changed. We may need to re-elect a new DR?
- if (this.isDr || this.neighbors.getDesignatedRouter().getPriority() < priority) {
+ if (this.isDr || pimInterface.getDesignatedRouter().getPriority() < priority) {
reelect = true;
}
this.priority = newpri;
@@ -242,7 +224,6 @@ public class PIMNeighbor {
if (holdtime == 0) {
// We have a neighbor going down. We can remove all joins
// we have learned from them.
- // TODO: What else do we need to do when a neighbor goes down?
log.debug("PIM Neighbor has timed out: {}", this.primaryAddr.toString());
return;
@@ -261,7 +242,7 @@ public class PIMNeighbor {
}
if (reelect) {
- this.neighbors.electDR(this);
+ pimInterface.electDR(this);
}
// Reset the next timeout timer
@@ -307,9 +288,8 @@ public class PIMNeighbor {
@Override
public void run(Timeout timeout) throws Exception {
- // TODO: log.debug;
- PIMNeighbors neighbors = nbr.neighbors;
- neighbors.removeNeighbor(nbr.getPrimaryAddr());
+ log.debug("PIM Neighbor {} has timed out: ", nbr.toString());
+ nbr.pimInterface.removeNeighbor(nbr);
}
}
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbors.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbors.java
deleted file mode 100644
index cad90768..00000000
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMNeighbors.java
+++ /dev/null
@@ -1,395 +0,0 @@
-
-package org.onosproject.pim.impl;
-
-import org.jboss.netty.util.Timeout;
-import org.jboss.netty.util.TimerTask;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.IpAddress;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.PIM;
-import org.onlab.packet.pim.PIMHello;
-import org.onosproject.net.ConnectPoint;
-import java.util.HashMap;
-import java.util.concurrent.TimeUnit;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * PIMNeighbors is a collection of all neighbors we have received
- * PIM hello messages from. The main structure is a HashMap indexed
- * by ConnectPoint with another HashMap indexed on the PIM neighbors
- * IPAddress, it contains all PIM neighbors attached on that ConnectPoint.
- */
-public final class PIMNeighbors {
-
- private static Logger log = LoggerFactory.getLogger("PIMNeighbors");
-
- /**
- * This is the global container for all PIM neighbors indexed by ConnectPoints.
- *
- * NOTE: We'll have a problem if the same neighbor can show up on two interfaces
- * but that should never happen.
- */
- private static HashMap<ConnectPoint, PIMNeighbors> connectPointNeighbors = new HashMap<>();
-
- // The connect point these neighbors are connected to.
- private ConnectPoint connectPoint;
-
- // Pointer to the current designated router on this ConnectPoint.
- private PIMNeighbor designatedRouter;
-
- // The list of neighbors we have learned on this ConnectPoint.
- private HashMap<IpAddress, PIMNeighbor> neighbors = new HashMap<>();
-
- /*
- * TODO: turn ourIpAddress, ourPriority and OurHoldTime into config options.
- */
- // The IP address we are using to source our PIM hello messages on this connect Point.
- private IpAddress ourIpAddress;
-
- // The priority we use on this ConnectPoint.
- private int ourPriority = 1;
-
- // The holdtime we are sending out.
- private int ourHoldtime = 105;
-
- // Then generation ID we are sending out. 0 means we need to generate a new random ID
- private int ourGenid = 0;
-
- // Hello Timer for sending hello messages per ConnectPoint with neighbors.
- private volatile Timeout helloTimer;
-
- // The period of which we will be sending out PIM hello messages.
- private final int defaultPimHelloInterval = 30; // seconds
-
- /**
- * Create PIMNeighbors object per ConnectPoint.
- *
- * @param cp the ConnectPoint.
- * @return PIMNeighbors structure
- */
- public static PIMNeighbors getConnectPointNeighbors(ConnectPoint cp) {
- return connectPointNeighbors.get(cp);
- }
-
- /**
- * Process incoming hello message, we will need the Macaddress and IP address of the sender.
- *
- * @param ethPkt the ethernet header
- * @param receivedFrom the connect point we recieved this message from
- */
- public static void processHello(Ethernet ethPkt, ConnectPoint receivedFrom) {
- checkNotNull(ethPkt);
- checkNotNull(ethPkt);
-
- MacAddress srcmac = ethPkt.getSourceMAC();
- IPv4 ip = (IPv4) ethPkt.getPayload();
- Ip4Address srcip = Ip4Address.valueOf(ip.getSourceAddress());
-
- PIM pim = (PIM) ip.getPayload();
- checkNotNull(pim);
-
- PIMHello hello = (PIMHello) pim.getPayload();
- checkNotNull(hello);
-
- PIMNeighbor nbr = PIMNeighbors.findOrCreate(srcip, srcmac, receivedFrom);
- if (nbr == null) {
- log.error("Could not create a neighbor for: {1}", srcip.toString());
- return;
- }
-
- nbr.setConnectPoint(receivedFrom);
- nbr.refresh(hello);
- }
-
- /**
- * Create a PIM Neighbor.
- *
- * @param cp The ConnectPoint this neighbor was found on
- */
- public PIMNeighbors(ConnectPoint cp) {
- this.connectPoint = cp;
-
- // TODO: use network config to assign address.
- this.ourIpAddress = IpAddress.valueOf("10.2.2.2");
- this.addIpAddress(this.ourIpAddress);
- }
-
- /**
- * Create a PIM neighbor.
- *
- * @param cp the ConnectPoint this neighbor was found on
- * @param ourIp the IP address of this neighbor
- */
- public PIMNeighbors(ConnectPoint cp, IpAddress ourIp) {
- this.connectPoint = cp;
- this.addIpAddress(ourIp);
- }
-
- /**
- * Start the hello timer when we have been given an IP address.
- *
- * @param ourIp our IP address.
- */
- public void addIpAddress(IpAddress ourIp) {
- this.startHelloTimer();
-
- // Kick off the first pim hello packet
- this.sendHelloPacket();
- }
-
- /**
- * Getter for our IP address.
- *
- * @return our IP address.
- */
- public IpAddress getOurIpAddress() {
- return this.ourIpAddress;
- }
-
- /**
- * Get our priority.
- *
- * @return our priority.
- */
- public int getOurPriority() {
- return this.ourPriority;
- }
-
- /**
- * Get the neighbor list for this specific connectPoint.
- *
- * @return PIM neighbors on this ConnectPoint
- */
- public HashMap<IpAddress, PIMNeighbor> getOurNeighborsList() {
- return this.neighbors;
- }
-
- /**
- * Get the designated router on this connection.
- *
- * @return the PIMNeighbor representing the DR
- */
- public PIMNeighbor getDesignatedRouter() {
- return designatedRouter;
- }
-
- /**
- * Are we the DR on this CP?
- *
- * @return true if we are, false if not
- */
- public boolean weAreTheDr() {
- return (designatedRouter != null &&
- designatedRouter.getPrimaryAddr().equals(ourIpAddress));
- }
-
- /**
- * Find the neighbor with the given IP address on this CP.
- *
- * @param ipaddr the IP address of the neighbor we are interested in
- * @return the pim neighbor if it exists
- */
- public PIMNeighbor findNeighbor(IpAddress ipaddr) {
- PIMNeighbor nbr = neighbors.get(ipaddr);
- return nbr;
- }
-
- /**
- * Add a new PIM neighbor to this list.
- *
- * @param nbr the neighbor to be added.
- */
- public void addNeighbor(PIMNeighbor nbr) {
- if (neighbors.containsKey(nbr.getPrimaryAddr())) {
-
- // TODO: Hmmm, how should this be handled?
- log.debug("We are adding a neighbor that already exists: {}", nbr.toString());
- neighbors.remove(nbr.getPrimaryAddr(), nbr);
- }
- nbr.setNeighbors(this);
- neighbors.put(nbr.getPrimaryAddr(), nbr);
- }
-
- /**
- * Remove the neighbor from our neighbor list.
- *
- * @param ipaddr the IP address of the neighbor to remove
- */
- public void removeNeighbor(IpAddress ipaddr) {
-
- boolean reelect = (designatedRouter == null || designatedRouter.getPrimaryAddr().equals(ipaddr));
- if (neighbors.containsKey(ipaddr)) {
- neighbors.remove(ipaddr);
- }
- this.electDR();
- }
-
- /**
- * Remove the given neighbor from the neighbor list.
- *
- * @param nbr the nbr to be removed.
- */
- public void removeNeighbor(PIMNeighbor nbr) {
-
- boolean reelect = (designatedRouter == null || nbr.isDr());
- neighbors.remove(nbr.getPrimaryAddr(), nbr);
- this.electDR();
- }
-
- /**
- * Elect a new DR on this ConnectPoint.
- *
- * @return the PIM Neighbor that wins
- */
- public PIMNeighbor electDR() {
-
- for (PIMNeighbor nbr : this.neighbors.values()) {
- if (this.designatedRouter == null) {
- this.designatedRouter = nbr;
- continue;
- }
-
- if (nbr.getPriority() > this.designatedRouter.getPriority()) {
- this.designatedRouter = nbr;
- continue;
- }
-
- // We could sort in ascending order
- if (this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) {
- this.designatedRouter = nbr;
- continue;
- }
- }
-
- return this.designatedRouter;
- }
-
- /**
- * Elect a new DR given the new neighbor.
- *
- * @param nbr the new neighbor to use in DR election.
- * @return the PIM Neighbor that wins DR election
- */
- public PIMNeighbor electDR(PIMNeighbor nbr) {
-
- // Make sure I have
- if (this.designatedRouter == null ||
- this.designatedRouter.getPriority() < nbr.getPriority() ||
- this.designatedRouter.getPrimaryAddr().compareTo(nbr.getPrimaryAddr()) > 0) {
- this.designatedRouter = nbr;
- }
- return this.designatedRouter;
- }
-
- /**
- * Find or create a pim neighbor with a given ip address and connect point.
- *
- * @param ipaddr of the pim neighbor
- * @param mac The mac address of our sending neighbor
- * @param cp the connect point the neighbor was learned from
- * @return an existing or new PIM neighbor
- */
- public static PIMNeighbor findOrCreate(IpAddress ipaddr, MacAddress mac, ConnectPoint cp) {
- PIMNeighbors neighbors = connectPointNeighbors.get(cp);
- if (neighbors == null) {
- neighbors = new PIMNeighbors(cp);
- connectPointNeighbors.put(cp, neighbors);
- }
-
- PIMNeighbor nbr = neighbors.findNeighbor(ipaddr);
- if (nbr == null) {
- nbr = new PIMNeighbor(ipaddr, mac, cp);
- neighbors.addNeighbor(nbr);
- neighbors.electDR(nbr);
- }
- return nbr;
- }
-
- // Returns the connect point neighbors hash map
- public static HashMap<ConnectPoint, PIMNeighbors> getConnectPointNeighbors() {
- return connectPointNeighbors;
- }
-
- /* ---------------------------------- PIM Hello Timer ----------------------------------- */
-
- /**
- * Start a new hello timer for this ConnectPoint.
- */
- private void startHelloTimer() {
- this.helloTimer = PIMTimer.getTimer().newTimeout(
- new HelloTimer(this),
- this.defaultPimHelloInterval,
- TimeUnit.SECONDS);
-
- log.trace("Started Hello Timer: " + this.ourIpAddress.toString());
- }
-
- /**
- * This inner class handles transmitting a PIM hello message on this ConnectPoint.
- */
- private final class HelloTimer implements TimerTask {
- PIMNeighbors neighbors;
-
- HelloTimer(PIMNeighbors neighbors) {
- this.neighbors = neighbors;
- }
-
- @Override
- public void run(Timeout timeout) throws Exception {
-
- // Send off a hello packet
- sendHelloPacket();
-
- // restart the hello timer
- neighbors.startHelloTimer();
- }
- }
-
- private void sendHelloPacket() {
- PIMHello hello = new PIMHello();
-
- // TODO: we will need to implement the network config service to assign ip addresses & options
- /*
- hello.createDefaultOptions();
-
- Ethernet eth = hello.createPIMHello(this.ourIpAddress);
- hello.sendPacket(this.connectPoint);
- */
- }
-
- /**
- * prints the connectPointNeighbors list with each neighbor list.
- *
- * @return string of neighbors.
- */
- public static String printPimNeighbors() {
- String out = "PIM Neighbors Table: \n";
-
- for (PIMNeighbors pn: connectPointNeighbors.values()) {
-
- out += "CP:\n " + pn.toString();
- for (PIMNeighbor nbr : pn.neighbors.values()) {
- out += "\t" + nbr.toString();
- }
- }
- return out;
- }
-
- @Override
- public String toString() {
- String out = "PIM Neighbors: ";
- if (this.ourIpAddress != null) {
- out += "IP: " + this.ourIpAddress.toString();
- } else {
- out += "IP: *Null*";
- }
- out += "\tPR: " + String.valueOf(this.ourPriority) + "\n";
- return out;
- }
-} \ No newline at end of file
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMPacketHandler.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMPacketHandler.java
new file mode 100644
index 00000000..c1ad2cfe
--- /dev/null
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMPacketHandler.java
@@ -0,0 +1,229 @@
+/*
+ * 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.pim.impl;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.PIM;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.incubator.net.intf.Interface;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketPriority;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.slf4j.Logger;
+
+import java.nio.ByteBuffer;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Handing Incoming and outgoing PIM packets.
+ */
+public final class PIMPacketHandler {
+ private final Logger log = getLogger(getClass());
+
+ private static PIMPacketHandler instance = null;
+
+ private PacketService packetService;
+ private PIMPacketProcessor processor = new PIMPacketProcessor();
+ private MacAddress pimDestinationMac = MacAddress.valueOf("01:00:5E:00:00:0d");
+
+ // Utility class
+ private PIMPacketHandler() {}
+
+ public static PIMPacketHandler getInstance() {
+ if (null == instance) {
+ instance = new PIMPacketHandler();
+ }
+ return instance;
+ }
+
+ /**
+ * Initialize the packet handling service.
+ *
+ * @param ps the packetService
+ * @param appId our application ID
+ */
+ public void initialize(PacketService ps, ApplicationId appId) {
+ packetService = ps;
+
+ // Build a traffic selector for all multicast traffic
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchIPProtocol(IPv4.PROTOCOL_PIM);
+ packetService.requestPackets(selector.build(), PacketPriority.REACTIVE, appId);
+
+ packetService.addProcessor(processor, PacketProcessor.director(1));
+ }
+
+ /**
+ * Shutdown the packet handling service.
+ */
+ public void stop() {
+ packetService.removeProcessor(processor);
+ processor = null;
+ }
+
+ /**
+ * Packet processor responsible for handling IGMP packets.
+ */
+ public class PIMPacketProcessor implements PacketProcessor {
+ private final Logger log = getLogger(getClass());
+
+ @Override
+ public void process(PacketContext context) {
+ // Stop processing if the packet has been handled, since we
+ // can't do any more to it.
+ if (context.isHandled()) {
+ return;
+ }
+
+ InboundPacket pkt = context.inPacket();
+ if (pkt == null) {
+ return;
+ }
+
+ Ethernet ethPkt = pkt.parsed();
+ if (ethPkt == null) {
+ return;
+ }
+
+ /*
+ * IPv6 MLD packets are handled by ICMP6. We'll only deal
+ * with IPv4.
+ */
+ if (ethPkt.getEtherType() != Ethernet.TYPE_IPV4) {
+ return;
+ }
+
+ IPv4 ip = (IPv4) ethPkt.getPayload();
+ IpAddress gaddr = IpAddress.valueOf(ip.getDestinationAddress());
+ IpAddress saddr = Ip4Address.valueOf(ip.getSourceAddress());
+ log.debug("Packet (" + saddr.toString() + ", " + gaddr.toString() +
+ "\tingress port: " + context.inPacket().receivedFrom().toString());
+
+ if (ip.getProtocol() != IPv4.PROTOCOL_PIM) {
+ log.debug("PIM Picked up a non PIM packet: IP protocol: " + ip.getProtocol());
+ return;
+ }
+
+ // TODO: check incoming to be PIM.PIM_ADDRESS or "Our" address.
+ IpPrefix spfx = IpPrefix.valueOf(saddr, 32);
+ IpPrefix gpfx = IpPrefix.valueOf(gaddr, 32);
+
+ PIM pim = (PIM) ip.getPayload();
+ switch (pim.getPimMsgType()) {
+
+ case PIM.TYPE_HELLO:
+ processHello(ethPkt, context.inPacket().receivedFrom());
+ break;
+
+ case PIM.TYPE_JOIN_PRUNE_REQUEST:
+ // Create the function
+ break;
+
+ case PIM.TYPE_ASSERT:
+ case PIM.TYPE_BOOTSTRAP:
+ case PIM.TYPE_CANDIDATE_RP_ADV:
+ case PIM.TYPE_GRAFT:
+ case PIM.TYPE_GRAFT_ACK:
+ case PIM.TYPE_REGISTER:
+ case PIM.TYPE_REGISTER_STOP:
+ log.debug("Unsupported PIM message type: " + pim.getPimMsgType());
+ break;
+
+ default:
+ log.debug("Unkown PIM message type: " + pim.getPimMsgType());
+ break;
+ }
+ }
+
+ /**
+ * Process incoming hello message, we will need the Macaddress and IP address of the sender.
+ *
+ * @param ethPkt the ethernet header
+ * @param receivedFrom the connect point we recieved this message from
+ */
+ private void processHello(Ethernet ethPkt, ConnectPoint receivedFrom) {
+ checkNotNull(ethPkt);
+ checkNotNull(receivedFrom);
+
+ // It is a problem if we don't have the
+ PIMInterfaces pintfs = PIMInterfaces.getInstance();
+ PIMInterface intf = pintfs.getInterface(receivedFrom);
+ if (intf == null) {
+ log.error("We received a PIM message on an interface we were not supposed to");
+ return;
+ }
+ intf.processHello(ethPkt, receivedFrom);
+ }
+ }
+
+ // Create an ethernet header and serialize then send
+ public void sendPacket(PIM pim, PIMInterface pimIntf) {
+
+ Interface theInterface = pimIntf.getInterface();
+
+ // Create the ethernet packet
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(pimDestinationMac);
+ eth.setSourceMACAddress(theInterface.mac());
+ eth.setEtherType(Ethernet.TYPE_IPV4);
+ if (theInterface.vlan() != VlanId.NONE) {
+ eth.setVlanID(theInterface.vlan().toShort());
+ }
+
+ // Create the IP Packet
+ IPv4 ip = new IPv4();
+ ip.setVersion((byte) 4);
+ ip.setTtl((byte) 20);
+ ip.setProtocol(IPv4.PROTOCOL_PIM);
+ ip.setChecksum((short) 0);
+ ip.setSourceAddress(checkNotNull(pimIntf.getIpAddress()).getIp4Address().toInt());
+ ip.setDestinationAddress(PIM.PIM_ADDRESS.getIp4Address().toInt());
+ eth.setPayload(ip);
+ ip.setParent(eth);
+
+ // Now set pim
+ ip.setPayload(pim);
+ pim.setParent(ip);
+
+ ConnectPoint cp = theInterface.connectPoint();
+ checkNotNull(cp);
+
+ TrafficTreatment treat = DefaultTrafficTreatment.builder().setOutput(cp.port()).build();
+ ByteBuffer bb = ByteBuffer.wrap(eth.serialize());
+ OutboundPacket packet = new DefaultOutboundPacket(cp.deviceId(), treat, bb);
+ checkNotNull(packet);
+
+ packetService.emit(packet);
+ }
+}
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMTimer.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMTimer.java
index c131a53b..c2a33033 100644
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMTimer.java
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMTimer.java
@@ -17,6 +17,8 @@ package org.onosproject.pim.impl;
import org.jboss.netty.util.HashedWheelTimer;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* PIM Timer used for PIM Neighbors.
*/
@@ -50,4 +52,21 @@ public final class PIMTimer {
PIMTimer.timer = hwTimer;
}
}
+
+ public static void start() {
+ if (PIMTimer.timer == null) {
+ getTimer();
+ }
+ checkNotNull(timer);
+ timer.start();
+ }
+
+ public static void stop() {
+ if (PIMTimer.timer == null) {
+ // No need to stop
+ return;
+ }
+ checkNotNull(timer);
+ timer.stop();
+ }
}
diff --git a/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteEntry.java b/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteEntry.java
index 974da808..24d1a8da 100644
--- a/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteEntry.java
+++ b/framework/src/onos/apps/routing/src/main/java/org/onosproject/routing/bgp/BgpRouteEntry.java
@@ -421,7 +421,7 @@ public class BgpRouteEntry extends RouteEntry {
@Override
public int hashCode() {
- return Objects.hash(pathSegments);
+ return pathSegments.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java
index eaabed33..f2d5b5e2 100644
--- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java
+++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/IntentSynchronizer.java
@@ -49,9 +49,9 @@ public class IntentSynchronizer implements IntentSynchronizationService {
private final Map<Key, Intent> intents;
//
- // State to deal with SDN-IP Leader election and pushing Intents
+ // State to deal with the Leader election and pushing Intents
//
- private final ExecutorService bgpIntentsSynchronizerExecutor;
+ private final ExecutorService intentsSynchronizerExecutor;
private volatile boolean isElectedLeader = false;
private volatile boolean isActivatedLeader = false;
@@ -61,9 +61,9 @@ public class IntentSynchronizer implements IntentSynchronizationService {
* @param appId the Application ID
* @param intentService the intent service
*/
- IntentSynchronizer(ApplicationId appId, IntentService intentService) {
+ public IntentSynchronizer(ApplicationId appId, IntentService intentService) {
this(appId, intentService,
- newSingleThreadExecutor(groupedThreads("onos/sdnip", "sync")));
+ newSingleThreadExecutor(groupedThreads("onos/" + appId, "sync")));
}
/**
@@ -80,7 +80,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
intents = new ConcurrentHashMap<>();
- bgpIntentsSynchronizerExecutor = executorService;
+ intentsSynchronizerExecutor = executorService;
}
/**
@@ -96,10 +96,10 @@ public class IntentSynchronizer implements IntentSynchronizationService {
public void stop() {
synchronized (this) {
// Stop the thread(s)
- bgpIntentsSynchronizerExecutor.shutdownNow();
+ intentsSynchronizerExecutor.shutdownNow();
//
- // Withdraw all SDN-IP intents
+ // Withdraw all app related intents
//
if (!isElectedLeader) {
return; // Nothing to do: not the leader anymore
@@ -115,7 +115,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
// Build a batch operation to withdraw all intents from this
// application.
//
- log.debug("SDN-IP Intent Synchronizer shutdown: " +
+ log.debug("Intent Synchronizer shutdown: " +
"withdrawing all intents...");
IntentOperations.Builder builder = IntentOperations.builder(appId);
for (Intent intent : intentService.getIntents()) {
@@ -133,7 +133,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
continue;
}
- log.trace("SDN-IP Intent Synchronizer withdrawing intent: {}",
+ log.trace("Intent Synchronizer withdrawing intent: {}",
intent);
builder.addWithdrawOperation(intent.id());
}
@@ -143,7 +143,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
peerIntents.clear();
routeIntents.clear();
- log.debug("SDN-IP Intent Synchronizer shutdown completed");
+ log.debug("Intent Synchronizer shutdown completed");
*/
}
}
@@ -153,7 +153,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
synchronized (this) {
intents.put(intent.key(), intent);
if (isElectedLeader && isActivatedLeader) {
- log.trace("SDN-IP Submitting intent: {}", intent);
+ log.trace("Submitting intent: {}", intent);
intentService.submit(intent);
}
}
@@ -164,19 +164,19 @@ public class IntentSynchronizer implements IntentSynchronizationService {
synchronized (this) {
intents.remove(intent.key(), intent);
if (isElectedLeader && isActivatedLeader) {
- log.trace("SDN-IP Withdrawing intent: {}", intent);
+ log.trace("Withdrawing intent: {}", intent);
intentService.withdraw(intent);
}
}
}
/**
- * Signals the synchronizer that the SDN-IP leadership has changed.
+ * Signals the synchronizer that the leadership has changed.
*
* @param isLeader true if this instance is now the leader, otherwise false
*/
public void leaderChanged(boolean isLeader) {
- log.debug("SDN-IP Leader changed: {}", isLeader);
+ log.debug("Leader changed: {}", isLeader);
if (!isLeader) {
this.isElectedLeader = false;
@@ -187,7 +187,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
this.isElectedLeader = true;
// Run the synchronization method off-thread
- bgpIntentsSynchronizerExecutor.execute(this::synchronizeIntents);
+ intentsSynchronizerExecutor.execute(this::synchronizeIntents);
}
private void synchronizeIntents() {
@@ -225,17 +225,17 @@ public class IntentSynchronizer implements IntentSynchronizationService {
}
}
- log.debug("SDN-IP Intent Synchronizer: submitting {}, withdrawing {}",
+ log.debug("Intent Synchronizer: submitting {}, withdrawing {}",
intentsToAdd.size(), intentsToRemove.size());
// Withdraw Intents
for (Intent intent : intentsToRemove) {
intentService.withdraw(intent);
- log.trace("SDN-IP Intent Synchronizer: withdrawing intent: {}",
+ log.trace("Intent Synchronizer: withdrawing intent: {}",
intent);
}
if (!isElectedLeader) {
- log.debug("SDN-IP Intent Synchronizer: cannot withdraw intents: " +
+ log.debug("Intent Synchronizer: cannot withdraw intents: " +
"not elected leader anymore");
isActivatedLeader = false;
return;
@@ -244,11 +244,11 @@ public class IntentSynchronizer implements IntentSynchronizationService {
// Add Intents
for (Intent intent : intentsToAdd) {
intentService.submit(intent);
- log.trace("SDN-IP Intent Synchronizer: submitting intent: {}",
+ log.trace("Intent Synchronizer: submitting intent: {}",
intent);
}
if (!isElectedLeader) {
- log.debug("SDN-IP Intent Synchronizer: cannot submit intents: " +
+ log.debug("Intent Synchronizer: cannot submit intents: " +
"not elected leader anymore");
isActivatedLeader = false;
return;
@@ -259,7 +259,7 @@ public class IntentSynchronizer implements IntentSynchronizationService {
} else {
isActivatedLeader = false;
}
- log.debug("SDN-IP intent synchronization completed");
+ log.debug("Intent synchronization completed");
}
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
index 8c6fbe8d..70161432 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultTunnel.java
@@ -17,8 +17,6 @@
package org.onosproject.segmentrouting;
import java.util.List;
-import java.util.Objects;
-
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -96,7 +94,7 @@ public class DefaultTunnel implements Tunnel {
@Override
public int hashCode() {
- return Objects.hash(labelIds);
+ return labelIds.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 9d60b279..b82752d6 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -596,29 +596,35 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private void processDeviceAdded(Device device) {
log.debug("A new device with ID {} was added", device.id());
+ if (deviceConfiguration == null) {
+ log.warn("Device configuration uploading. Device {} will be "
+ + "processed after config completes.", device.id());
+ return;
+ }
// Irrespective of whether the local is a MASTER or not for this device,
// we need to create a SR-group-handler instance. This is because in a
// multi-instance setup, any instance can initiate forwarding/next-objectives
// for any switch (even if this instance is a SLAVE or not even connected
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
- DefaultGroupHandler groupHandler = DefaultGroupHandler.
- createGroupHandler(device.id(),
- appId,
- deviceConfiguration,
- linkService,
- flowObjectiveService,
- nsNextObjStore,
- subnetNextObjStore);
- groupHandlerMap.put(device.id(), groupHandler);
-
- // Also, in some cases, drivers may need extra
- // information to process rules (eg. Router IP/MAC); and so, we send
- // port addressing rules to the driver as well irrespective of whether
- // this instance is the master or not.
- defaultRoutingHandler.populatePortAddressingRules(device.id());
-
+ if (groupHandlerMap.get(device.id()) == null) {
+ DefaultGroupHandler groupHandler = DefaultGroupHandler.
+ createGroupHandler(device.id(),
+ appId,
+ deviceConfiguration,
+ linkService,
+ flowObjectiveService,
+ nsNextObjStore,
+ subnetNextObjStore);
+ groupHandlerMap.put(device.id(), groupHandler);
+ // Also, in some cases, drivers may need extra
+ // information to process rules (eg. Router IP/MAC); and so, we send
+ // port addressing rules to the driver as well irrespective of whether
+ // this instance is the master or not.
+ defaultRoutingHandler.populatePortAddressingRules(device.id());
+ }
if (mastershipService.isLocalMaster(device.id())) {
+ DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
}
}
@@ -660,21 +666,23 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// for any switch (even if this instance is a SLAVE or not even connected
// to the switch). To handle this, a default-group-handler instance is necessary
// per switch.
- DefaultGroupHandler groupHandler = DefaultGroupHandler
- .createGroupHandler(device.id(), appId,
- deviceConfiguration, linkService,
- flowObjectiveService,
- nsNextObjStore,
- subnetNextObjStore);
- groupHandlerMap.put(device.id(), groupHandler);
-
- // Also, in some cases, drivers may need extra
- // information to process rules (eg. Router IP/MAC); and so, we send
- // port addressing rules to the driver as well, irrespective of whether
- // this instance is the master or not.
- defaultRoutingHandler.populatePortAddressingRules(device.id());
-
+ if (groupHandlerMap.get(device.id()) == null) {
+ DefaultGroupHandler groupHandler = DefaultGroupHandler
+ .createGroupHandler(device.id(), appId,
+ deviceConfiguration, linkService,
+ flowObjectiveService,
+ nsNextObjStore,
+ subnetNextObjStore);
+ groupHandlerMap.put(device.id(), groupHandler);
+
+ // Also, in some cases, drivers may need extra
+ // information to process rules (eg. Router IP/MAC); and so, we send
+ // port addressing rules to the driver as well, irrespective of whether
+ // this instance is the master or not.
+ defaultRoutingHandler.populatePortAddressingRules(device.id());
+ }
if (mastershipService.isLocalMaster(device.id())) {
+ DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
}
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/BindingHostId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/BindingHostId.java
index c715d08a..7dca32de 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/BindingHostId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/BindingHostId.java
@@ -49,7 +49,7 @@ public final class BindingHostId {
@Override
public int hashCode() {
- return Objects.hash(bindingHostId);
+ return bindingHostId.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java
index b789abe3..df180ebe 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.vtnrsc;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.base.MoreObjects;
import java.util.UUID;
@@ -33,6 +35,7 @@ public final class FlowClassifierId {
* @param flowClassifierId flow classifier id.
*/
private FlowClassifierId(final UUID flowClassifierId) {
+ checkNotNull(flowClassifierId, "Flow classifier id can not be null");
this.flowClassifierId = flowClassifierId;
}
@@ -42,7 +45,7 @@ public final class FlowClassifierId {
* @param flowClassifierId flow classifier id
* @return new flow classifier id
*/
- public static FlowClassifierId flowClassifierId(final UUID flowClassifierId) {
+ public static FlowClassifierId of(final UUID flowClassifierId) {
return new FlowClassifierId(flowClassifierId);
}
@@ -52,7 +55,7 @@ public final class FlowClassifierId {
* @param flowClassifierId flow classifier id
* @return new flow classifier id
*/
- public static FlowClassifierId flowClassifierId(final String flowClassifierId) {
+ public static FlowClassifierId of(final String flowClassifierId) {
return new FlowClassifierId(UUID.fromString(flowClassifierId));
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PhysicalNetwork.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PhysicalNetwork.java
index e96e666a..30631d28 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PhysicalNetwork.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PhysicalNetwork.java
@@ -53,7 +53,7 @@ public final class PhysicalNetwork {
@Override
public int hashCode() {
- return Objects.hash(physicalNetwork);
+ return physicalNetwork.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java
index 66edbdcc..a42a700f 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java
@@ -19,8 +19,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.UUID;
-
-import com.google.common.base.Objects;
+import java.util.Objects;
/**
* Representation of a Port Chain ID.
@@ -40,22 +39,22 @@ public final class PortChainId {
}
/**
- * Constructor to create port chain id from UUID.
+ * Returns newly created port chain id object.
*
* @param id UUID of port chain
* @return object of port chain id
*/
- public static PortChainId portChainId(UUID id) {
+ public static PortChainId of(UUID id) {
return new PortChainId(id);
}
/**
- * Constructor to create port chain id from string.
+ * Returns newly created port chain id object.
*
* @param id port chain id in string
* @return object of port chain id
*/
- public static PortChainId portChainId(String id) {
+ public static PortChainId of(String id) {
return new PortChainId(UUID.fromString(id));
}
@@ -73,10 +72,9 @@ public final class PortChainId {
if (this == obj) {
return true;
}
-
- if (obj.getClass() == this.getClass()) {
- PortChainId that = (PortChainId) obj;
- return Objects.equal(this.portChainId, that.portChainId);
+ if (obj instanceof PortChainId) {
+ final PortChainId other = (PortChainId) obj;
+ return Objects.equals(this.portChainId, other.portChainId);
}
return false;
}
@@ -88,8 +86,6 @@ public final class PortChainId {
@Override
public String toString() {
- return toStringHelper(this)
- .add("portChainId", portChainId.toString())
- .toString();
+ return toStringHelper(this).add("portChainId", portChainId).toString();
}
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java
index 0474901c..a52a2bb3 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java
@@ -19,8 +19,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.UUID;
-
-import com.google.common.base.Objects;
+import java.util.Objects;
/**
* Representation of a Port Pair Group ID.
@@ -40,22 +39,22 @@ public final class PortPairGroupId {
}
/**
- * Constructor to create port pair group id from UUID.
+ * Returns newly created port pair group id object.
*
- * @param id UUID of port pair group id
+ * @param id port pair group id in UUID
* @return object of port pair group id
*/
- public static PortPairGroupId portPairGroupId(UUID id) {
+ public static PortPairGroupId of(UUID id) {
return new PortPairGroupId(id);
}
/**
- * Constructor to create port pair group id from string.
+ * Returns newly created port pair group id object.
*
* @param id port pair group id in string
* @return object of port pair group id
*/
- public static PortPairGroupId portPairGroupId(String id) {
+ public static PortPairGroupId of(String id) {
return new PortPairGroupId(UUID.fromString(id));
}
@@ -73,10 +72,9 @@ public final class PortPairGroupId {
if (this == obj) {
return true;
}
-
- if (obj.getClass() == this.getClass()) {
- PortPairGroupId that = (PortPairGroupId) obj;
- return Objects.equal(this.portPairGroupId, that.portPairGroupId);
+ if (obj instanceof PortPairGroupId) {
+ final PortPairGroupId other = (PortPairGroupId) obj;
+ return Objects.equals(this.portPairGroupId, other.portPairGroupId);
}
return false;
}
@@ -88,8 +86,7 @@ public final class PortPairGroupId {
@Override
public String toString() {
- return toStringHelper(this)
- .add("portPairGroupId", portPairGroupId.toString())
+ return toStringHelper(this).add("portPairGroupId", portPairGroupId)
.toString();
}
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java
index 05c31aac..1f45e80e 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java
@@ -19,8 +19,7 @@ import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.UUID;
-
-import com.google.common.base.Objects;
+import java.util.Objects;
/**
* Representation of a Port Pair ID.
@@ -40,22 +39,22 @@ public final class PortPairId {
}
/**
- * Constructor to create port pair id from UUID.
+ * Returns newly created port pair id object.
*
* @param id UUID of port pair id
* @return object of port pair id
*/
- public static PortPairId portPairId(UUID id) {
+ public static PortPairId of(UUID id) {
return new PortPairId(id);
}
/**
- * Constructor to create port pair id from string.
+ * Returns newly created port pair id object.
*
* @param id port pair id in string
* @return object of port pair id
*/
- public static PortPairId portPairId(String id) {
+ public static PortPairId of(String id) {
return new PortPairId(UUID.fromString(id));
}
@@ -73,10 +72,9 @@ public final class PortPairId {
if (this == obj) {
return true;
}
-
- if (obj.getClass() == this.getClass()) {
- PortPairId that = (PortPairId) obj;
- return Objects.equal(this.portPairId, that.portPairId);
+ if (obj instanceof PortPairId) {
+ final PortPairId other = (PortPairId) obj;
+ return Objects.equals(this.portPairId, other.portPairId);
}
return false;
}
@@ -89,7 +87,7 @@ public final class PortPairId {
@Override
public String toString() {
return toStringHelper(this)
- .add("portPairId", portPairId.toString())
+ .add("portPairId", portPairId)
.toString();
}
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SecurityGroup.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SecurityGroup.java
index 9ec1dc63..33ddcbfe 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SecurityGroup.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SecurityGroup.java
@@ -52,7 +52,7 @@ public final class SecurityGroup {
@Override
public int hashCode() {
- return Objects.hash(securityGroup);
+ return securityGroup.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SegmentationId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SegmentationId.java
index a076265f..651ebd89 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SegmentationId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SegmentationId.java
@@ -53,7 +53,7 @@ public final class SegmentationId {
@Override
public int hashCode() {
- return Objects.hash(segmentationId);
+ return segmentationId.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SubnetId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SubnetId.java
index 4bcc3329..eb93d153 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SubnetId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/SubnetId.java
@@ -53,7 +53,7 @@ public final class SubnetId {
@Override
public int hashCode() {
- return Objects.hash(subnetId);
+ return subnetId.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantId.java
index c4d99e49..0e7c9417 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantId.java
@@ -53,7 +53,7 @@ public final class TenantId {
@Override
public int hashCode() {
- return Objects.hash(tenantId);
+ return tenantId.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantNetworkId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantNetworkId.java
index fbb9e480..8680d28f 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantNetworkId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/TenantNetworkId.java
@@ -52,7 +52,7 @@ public final class TenantNetworkId {
@Override
public int hashCode() {
- return Objects.hash(networkId);
+ return networkId.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/VirtualPortId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/VirtualPortId.java
index 3038bdff..a3863483 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/VirtualPortId.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/VirtualPortId.java
@@ -46,7 +46,7 @@ public final class VirtualPortId {
@Override
public int hashCode() {
- return Objects.hash(portId);
+ return portId.hashCode();
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.java
index 7238558a..ca01c434 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.java
@@ -15,21 +15,26 @@
*/
package org.onosproject.vtnrsc.flowClassifier.impl;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
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.util.KryoNamespace;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.MultiValuedTimestamp;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
import org.onosproject.vtnrsc.FlowClassifierId;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.flowClassifier.FlowClassifierService;
-
import org.slf4j.Logger;
-import static org.slf4j.LoggerFactory.getLogger;
+import static org.slf4j.LoggerFactory.getLogger;
import static com.google.common.base.Preconditions.checkNotNull;
+
import com.google.common.collect.ImmutableList;
/**
@@ -44,16 +49,26 @@ public class FlowClassifierManager implements FlowClassifierService {
private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow Classifier cannot be null";
private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow Classifier Id cannot be null";
- private ConcurrentMap<FlowClassifierId, FlowClassifier> flowClassifierStore
- = new ConcurrentHashMap<FlowClassifierId, FlowClassifier>();
+ private EventuallyConsistentMap<FlowClassifierId, FlowClassifier> flowClassifierStore;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
@Activate
private void activate() {
+ KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(MultiValuedTimestamp.class)
+ .register(FlowClassifier.class);
+ flowClassifierStore = storageService
+ .<FlowClassifierId, FlowClassifier>eventuallyConsistentMapBuilder()
+ .withName("flowclassifierstore").withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
log.info("Flow Classifier service activated");
}
@Deactivate
private void deactivate() {
+ flowClassifierStore.destroy();
log.info("Flow Classifier service deactivated");
}
@@ -92,7 +107,8 @@ public class FlowClassifierManager implements FlowClassifierService {
public boolean updateFlowClassifier(FlowClassifier flowClassifier) {
checkNotNull(flowClassifier, FLOW_CLASSIFIER_NOT_NULL);
FlowClassifierId id = flowClassifier.flowClassifierId();
- return flowClassifierStore.replace(id, flowClassifierStore.get(id), flowClassifier);
+ flowClassifierStore.put(id, flowClassifier);
+ return true;
}
@Override
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
new file mode 100644
index 00000000..5201a2ca
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/PortChainManager.java
@@ -0,0 +1,146 @@
+/*
+ * 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.vtnrsc.portchain.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+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.util.KryoNamespace;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.MultiValuedTimestamp;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.portchain.PortChainService;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of the portChainService.
+ */
+@Component(immediate = true)
+@Service
+public class PortChainManager implements PortChainService {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String PORT_CHAIN_ID_NULL = "PortChain ID cannot be null";
+ private static final String PORT_CHAIN_NULL = "PortChain cannot be null";
+
+ private EventuallyConsistentMap<PortChainId, PortChain> portChainStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Activate
+ public void activate() {
+
+ KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(MultiValuedTimestamp.class)
+ .register(PortChain.class);
+
+ portChainStore = storageService
+ .<PortChainId, PortChain>eventuallyConsistentMapBuilder()
+ .withName("portchainstore").withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ portChainStore.destroy();
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean exists(PortChainId portChainId) {
+ checkNotNull(portChainId, PORT_CHAIN_ID_NULL);
+ return portChainStore.containsKey(portChainId);
+ }
+
+ @Override
+ public int getPortChainCount() {
+ return portChainStore.size();
+ }
+
+ @Override
+ public Iterable<PortChain> getPortChains() {
+ return Collections.unmodifiableCollection(portChainStore.values());
+ }
+
+ @Override
+ public PortChain getPortChain(PortChainId portChainId) {
+ checkNotNull(portChainId, PORT_CHAIN_ID_NULL);
+ return portChainStore.get(portChainId);
+ }
+
+ @Override
+ public boolean createPortChain(PortChain portChain) {
+ checkNotNull(portChain, PORT_CHAIN_NULL);
+
+ portChainStore.put(portChain.portChainId(), portChain);
+ if (!portChainStore.containsKey(portChain.portChainId())) {
+ log.debug("The portChain is created failed which identifier was {}", portChain.portChainId()
+ .toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updatePortChain(PortChain portChain) {
+ checkNotNull(portChain, PORT_CHAIN_NULL);
+
+ if (!portChainStore.containsKey(portChain.portChainId())) {
+ log.debug("The portChain is not exist whose identifier was {} ",
+ portChain.portChainId().toString());
+ return false;
+ }
+
+ portChainStore.put(portChain.portChainId(), portChain);
+
+ if (!portChain.equals(portChainStore.get(portChain.portChainId()))) {
+ log.debug("The portChain is updated failed whose identifier was {} ",
+ portChain.portChainId().toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removePortChain(PortChainId portChainId) {
+ checkNotNull(portChainId, PORT_CHAIN_NULL);
+
+ portChainStore.remove(portChainId);
+ if (portChainStore.containsKey(portChainId)) {
+ log.debug("The portChain is removed failed whose identifier was {}",
+ portChainId.toString());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/package-info.java
new file mode 100644
index 00000000..424d54ab
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of service for interacting with the inventory of port chains.
+ */
+package org.onosproject.vtnrsc.portchain.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java
new file mode 100644
index 00000000..f99cc2cf
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/PortPairService.java
@@ -0,0 +1,80 @@
+/*
+ * 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.vtnrsc.portpair;
+
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+
+/**
+ * Service for interacting with the inventory of port pairs.
+ */
+public interface PortPairService {
+
+ /**
+ * Returns if the port pair is existed.
+ *
+ * @param portPairId port pair identifier
+ * @return true or false if one with the given identifier exists.
+ */
+ boolean exists(PortPairId portPairId);
+
+ /**
+ * Returns the number of port pairs known to the system.
+ *
+ * @return number of port pairs.
+ */
+ int getPortPairCount();
+
+ /**
+ * Returns an iterable collection of the currently known port pairs.
+ *
+ * @return collection of port pairs.
+ */
+ Iterable<PortPair> getPortPairs();
+
+ /**
+ * Returns the portPair with the given identifier.
+ *
+ * @param portPairId port pair identifier
+ * @return PortPair or null if port pair with the given identifier is not
+ * known.
+ */
+ PortPair getPortPair(PortPairId portPairId);
+
+ /**
+ * Creates a PortPair in the store.
+ *
+ * @param portPair the port pair to create
+ * @return true if given port pair is created successfully.
+ */
+ boolean createPortPair(PortPair portPair);
+
+ /**
+ * Updates the portPair in the store.
+ *
+ * @param portPair the port pair to update
+ * @return true if given port pair is updated successfully.
+ */
+ boolean updatePortPair(PortPair portPair);
+
+ /**
+ * Deletes portPair by given portPairId.
+ *
+ * @param portPairId id of port pair to remove
+ * @return true if the give port pair is deleted successfully.
+ */
+ boolean removePortPair(PortPairId portPairId);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
new file mode 100644
index 00000000..93c8782a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/PortPairManager.java
@@ -0,0 +1,146 @@
+/*
+ * 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.vtnrsc.portpair.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+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.util.KryoNamespace;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.MultiValuedTimestamp;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.portpair.PortPairService;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of the portPairService.
+ */
+@Component(immediate = true)
+@Service
+public class PortPairManager implements PortPairService {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String PORT_PAIR_ID_NULL = "PortPair ID cannot be null";
+ private static final String PORT_PAIR_NULL = "PortPair cannot be null";
+
+ private EventuallyConsistentMap<PortPairId, PortPair> portPairStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Activate
+ public void activate() {
+
+ KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(MultiValuedTimestamp.class)
+ .register(PortPair.class);
+
+ portPairStore = storageService
+ .<PortPairId, PortPair>eventuallyConsistentMapBuilder()
+ .withName("portpairstore").withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ portPairStore.destroy();
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean exists(PortPairId portPairId) {
+ checkNotNull(portPairId, PORT_PAIR_ID_NULL);
+ return portPairStore.containsKey(portPairId);
+ }
+
+ @Override
+ public int getPortPairCount() {
+ return portPairStore.size();
+ }
+
+ @Override
+ public Iterable<PortPair> getPortPairs() {
+ return Collections.unmodifiableCollection(portPairStore.values());
+ }
+
+ @Override
+ public PortPair getPortPair(PortPairId portPairId) {
+ checkNotNull(portPairId, PORT_PAIR_ID_NULL);
+ return portPairStore.get(portPairId);
+ }
+
+ @Override
+ public boolean createPortPair(PortPair portPair) {
+ checkNotNull(portPair, PORT_PAIR_NULL);
+
+ portPairStore.put(portPair.portPairId(), portPair);
+ if (!portPairStore.containsKey(portPair.portPairId())) {
+ log.debug("The portPair is created failed which identifier was {}", portPair.portPairId()
+ .toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updatePortPair(PortPair portPair) {
+ checkNotNull(portPair, PORT_PAIR_NULL);
+
+ if (!portPairStore.containsKey(portPair.portPairId())) {
+ log.debug("The portPair is not exist whose identifier was {} ",
+ portPair.portPairId().toString());
+ return false;
+ }
+
+ portPairStore.put(portPair.portPairId(), portPair);
+
+ if (!portPair.equals(portPairStore.get(portPair.portPairId()))) {
+ log.debug("The portPair is updated failed whose identifier was {} ",
+ portPair.portPairId().toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removePortPair(PortPairId portPairId) {
+ checkNotNull(portPairId, PORT_PAIR_NULL);
+
+ portPairStore.remove(portPairId);
+ if (portPairStore.containsKey(portPairId)) {
+ log.debug("The portPair is removed failed whose identifier was {}",
+ portPairId.toString());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/package-info.java
new file mode 100644
index 00000000..625fbdd4
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of service for interacting with the inventory of port pairs.
+ */
+package org.onosproject.vtnrsc.portpair.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/package-info.java
index 34636a9f..e2c61531 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/package-info.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpair/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * Codecs for virtual tenant objects.
+ * Service for interacting with the inventory of port pairs.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnrsc.portpair;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
new file mode 100644
index 00000000..55fb4e43
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManager.java
@@ -0,0 +1,146 @@
+/*
+ * 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.vtnrsc.portpairgroup.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collections;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+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.util.KryoNamespace;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.MultiValuedTimestamp;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of the portPairGroupService.
+ */
+@Component(immediate = true)
+@Service
+public class PortPairGroupManager implements PortPairGroupService {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String PORT_PAIR_GROUP_ID_NULL = "PortPairGroup ID cannot be null";
+ private static final String PORT_PAIR_GROUP_NULL = "PortPairGroup cannot be null";
+
+ private EventuallyConsistentMap<PortPairGroupId, PortPairGroup> portPairGroupStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Activate
+ public void activate() {
+
+ KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(MultiValuedTimestamp.class)
+ .register(PortPairGroup.class);
+
+ portPairGroupStore = storageService
+ .<PortPairGroupId, PortPairGroup>eventuallyConsistentMapBuilder()
+ .withName("portpairgroupstore").withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp()).build();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ portPairGroupStore.destroy();
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean exists(PortPairGroupId portPairGroupId) {
+ checkNotNull(portPairGroupId, PORT_PAIR_GROUP_ID_NULL);
+ return portPairGroupStore.containsKey(portPairGroupId);
+ }
+
+ @Override
+ public int getPortPairGroupCount() {
+ return portPairGroupStore.size();
+ }
+
+ @Override
+ public Iterable<PortPairGroup> getPortPairGroups() {
+ return Collections.unmodifiableCollection(portPairGroupStore.values());
+ }
+
+ @Override
+ public PortPairGroup getPortPairGroup(PortPairGroupId portPairGroupId) {
+ checkNotNull(portPairGroupId, PORT_PAIR_GROUP_ID_NULL);
+ return portPairGroupStore.get(portPairGroupId);
+ }
+
+ @Override
+ public boolean createPortPairGroup(PortPairGroup portPairGroup) {
+ checkNotNull(portPairGroup, PORT_PAIR_GROUP_NULL);
+
+ portPairGroupStore.put(portPairGroup.portPairGroupId(), portPairGroup);
+ if (!portPairGroupStore.containsKey(portPairGroup.portPairGroupId())) {
+ log.debug("The portPairGroup is created failed which identifier was {}", portPairGroup.portPairGroupId()
+ .toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updatePortPairGroup(PortPairGroup portPairGroup) {
+ checkNotNull(portPairGroup, PORT_PAIR_GROUP_NULL);
+
+ if (!portPairGroupStore.containsKey(portPairGroup.portPairGroupId())) {
+ log.debug("The portPairGroup is not exist whose identifier was {} ",
+ portPairGroup.portPairGroupId().toString());
+ return false;
+ }
+
+ portPairGroupStore.put(portPairGroup.portPairGroupId(), portPairGroup);
+
+ if (!portPairGroup.equals(portPairGroupStore.get(portPairGroup.portPairGroupId()))) {
+ log.debug("The portPairGroup is updated failed whose identifier was {} ",
+ portPairGroup.portPairGroupId().toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removePortPairGroup(PortPairGroupId portPairGroupId) {
+ checkNotNull(portPairGroupId, PORT_PAIR_GROUP_NULL);
+
+ portPairGroupStore.remove(portPairGroupId);
+ if (portPairGroupStore.containsKey(portPairGroupId)) {
+ log.debug("The portPairGroup is removed failed whose identifier was {}",
+ portPairGroupId.toString());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/package-info.java
new file mode 100644
index 00000000..68c186bc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * Implementation of service for interacting with the inventory of port pair groups.
+ */
+package org.onosproject.vtnrsc.portpairgroup.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java
index b2fed347..4f521836 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java
@@ -32,11 +32,11 @@ import java.util.UUID;
public class FlowClassifierIdTest {
final FlowClassifierId flowClassifierId1 = FlowClassifierId
- .flowClassifierId("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ .of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
final FlowClassifierId sameAsFlowClassifierId1 = FlowClassifierId
- .flowClassifierId("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ .of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
final FlowClassifierId flowClassifierId2 = FlowClassifierId
- .flowClassifierId("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+ .of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
/**
* Checks that the FlowClassifierId class is immutable.
@@ -61,7 +61,7 @@ public class FlowClassifierIdTest {
@Test
public void testConstruction() {
final String flowClassifierIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
- final FlowClassifierId flowClassifierId = FlowClassifierId.flowClassifierId(flowClassifierIdValue);
+ final FlowClassifierId flowClassifierId = FlowClassifierId.of(flowClassifierIdValue);
assertThat(flowClassifierId, is(notNullValue()));
assertThat(flowClassifierId.value(), is(UUID.fromString(flowClassifierIdValue)));
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/PortChainIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/PortChainIdTest.java
new file mode 100644
index 00000000..88fecf8d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/PortChainIdTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.vtnrsc.portpair;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.PortChainId;
+
+import com.google.common.testing.EqualsTester;
+import java.util.UUID;
+
+/**
+ * Unit tests for PortChainId class.
+ */
+public class PortChainIdTest {
+
+ final PortChainId portChainId1 = PortChainId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortChainId sameAsPortChainId1 = PortChainId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortChainId portChainId2 = PortChainId.of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the PortChainId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PortChainId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(portChainId1, sameAsPortChainId1).addEqualityGroup(portChainId2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a PortChainId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String portChainIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final PortChainId portChainId = PortChainId.of(portChainIdValue);
+ assertThat(portChainId, is(notNullValue()));
+ assertThat(portChainId.value(), is(UUID.fromString(portChainIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/PortPairIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/PortPairIdTest.java
new file mode 100644
index 00000000..f176089e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/PortPairIdTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.vtnrsc.portpair;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.PortPairId;
+
+import com.google.common.testing.EqualsTester;
+import java.util.UUID;
+
+/**
+ * Unit tests for PortPairId class.
+ */
+public class PortPairIdTest {
+
+ final PortPairId portPairId1 = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairId sameAsPortPairId1 = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairId portPairId2 = PortPairId.of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the PortPairId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PortPairId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(portPairId1, sameAsPortPairId1).addEqualityGroup(portPairId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a PortPairId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String portPairIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final PortPairId portPairId = PortPairId.of(portPairIdValue);
+ assertThat(portPairId, is(notNullValue()));
+ assertThat(portPairId.value(), is(UUID.fromString(portPairIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupIdTest.java
new file mode 100644
index 00000000..7da4c489
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupIdTest.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.vtnrsc.portpair;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.PortPairGroupId;
+
+import com.google.common.testing.EqualsTester;
+import java.util.UUID;
+
+/**
+ * Unit tests for PortPairGroupId class.
+ */
+public class PortPairGroupIdTest {
+
+ final PortPairGroupId portPairGroupId1 = PortPairGroupId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairGroupId sameAsPortPairGroupId1 = PortPairGroupId
+ .of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairGroupId portPairGroupId2 = PortPairGroupId.of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the PortPairGroupId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PortPairGroupId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(portPairGroupId1, sameAsPortPairGroupId1)
+ .addEqualityGroup(portPairGroupId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a PortPairGroupId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String portPairGroupIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final PortPairGroupId portPairGroupId = PortPairGroupId.of(portPairGroupIdValue);
+ assertThat(portPairGroupId, is(notNullValue()));
+ assertThat(portPairGroupId.value(), is(UUID.fromString(portPairGroupIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
index 1450e4ef..b5b8252b 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
@@ -40,7 +40,7 @@ import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
import org.onosproject.rest.AbstractWebResource;
import org.onosproject.vtnrsc.flowClassifier.FlowClassifierService;
-import org.onosproject.vtnrsc.web.FlowClassifierCodec;
+import org.onosproject.vtnweb.web.FlowClassifierCodec;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
@@ -82,11 +82,11 @@ public class FlowClassifierWebResource extends AbstractWebResource {
@Produces(MediaType.APPLICATION_JSON)
public Response getFlowClassifier(@PathParam("flow_id") String id) {
- if (!service.hasFlowClassifier(FlowClassifierId.flowClassifierId(UUID.fromString(id)))) {
+ if (!service.hasFlowClassifier(FlowClassifierId.of(UUID.fromString(id)))) {
return Response.status(NOT_FOUND).entity(FLOW_CLASSIFIER_NOT_FOUND).build();
}
FlowClassifier flowClassifier = nullIsNotFound(
- service.getFlowClassifier(FlowClassifierId.flowClassifierId(UUID.fromString(id))),
+ service.getFlowClassifier(FlowClassifierId.of(UUID.fromString(id))),
FLOW_CLASSIFIER_NOT_FOUND);
ObjectNode result = new ObjectMapper().createObjectNode();
@@ -182,7 +182,7 @@ public class FlowClassifierWebResource extends AbstractWebResource {
@DELETE
public Response deleteFlowClassifier(@PathParam("flow_id") String id) throws IOException {
try {
- FlowClassifierId flowClassifierId = FlowClassifierId.flowClassifierId(UUID.fromString(id));
+ FlowClassifierId flowClassifierId = FlowClassifierId.of(UUID.fromString(id));
service.removeFlowClassifier(flowClassifierId);
return Response.status(201).entity("SUCCESS").build();
} catch (Exception e) {
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java
new file mode 100644
index 00000000..db12bcc7
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortChainWebResource.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2014-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.vtnweb.resources;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.portchain.PortChainService;
+import org.onosproject.vtnweb.web.PortChainCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port chain.
+ */
+
+@Path("port_chains")
+public class PortChainWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(PortChainWebResource.class);
+ private final PortChainService service = get(PortChainService.class);
+ public static final String PORT_CHAIN_NOT_FOUND = "Port chain not found";
+ public static final String PORT_CHAIN_ID_EXIST = "Port chain exists";
+ public static final String PORT_CHAIN_ID_NOT_EXIST = "Port chain does not exist with identifier";
+
+ /**
+ * Get details of all port chains created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortChains() {
+ Iterable<PortChain> portChains = service.getPortChains();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_chains", new PortChainCodec().encode(portChains, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Get details of a specified port chain id.
+ *
+ * @param id port chain id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{chain_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPain(@PathParam("chain_id") String id) {
+
+ if (!service.exists(PortChainId.of(id))) {
+ return Response.status(NOT_FOUND).entity(PORT_CHAIN_NOT_FOUND).build();
+ }
+ PortChain portChain = nullIsNotFound(service.getPortChain(PortChainId.of(id)),
+ PORT_CHAIN_NOT_FOUND);
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_chain", new PortChainCodec().encode(portChain, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Creates a new port chain.
+ *
+ * @param stream port chain from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPortChain(InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortChain portChain = codec(PortChain.class).decode(jsonTree, this);
+ Boolean issuccess = nullIsNotFound(service.createPortChain(portChain), PORT_CHAIN_NOT_FOUND);
+ return Response.status(OK).entity(issuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Exception while creating port chain {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Update details of a specified port chain id.
+ *
+ * @param id port chain id
+ * @param stream port chain json
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @PUT
+ @Path("{chain_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updatePortPain(@PathParam("chain_id") String id,
+ final InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortChain portChain = codec(PortChain.class).decode(jsonTree, this);
+ Boolean result = nullIsNotFound(service.updatePortChain(portChain), PORT_CHAIN_NOT_FOUND);
+ return Response.status(OK).entity(result.toString()).build();
+ } catch (IOException e) {
+ log.error("Update port chain failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Delete details of a specified port chain id.
+ *
+ * @param id port chain id
+ */
+ @Path("{chain_id}")
+ @DELETE
+ public void deletePortPain(@PathParam("chain_id") String id) {
+ log.debug("Deletes port chain by identifier {}.", id);
+ PortChainId portChainId = PortChainId.of(id);
+
+ Boolean issuccess = nullIsNotFound(service.removePortChain(portChainId), PORT_CHAIN_NOT_FOUND);
+ if (!issuccess) {
+ log.debug("Port Chain identifier {} does not exist", id);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java
new file mode 100644
index 00000000..69daad37
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairGroupWebResource.java
@@ -0,0 +1,163 @@
+/*
+ * 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.vtnweb.resources;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.portpairgroup.PortPairGroupService;
+import org.onosproject.vtnweb.web.PortPairGroupCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port pair group.
+ */
+
+@Path("port_pair_groups")
+public class PortPairGroupWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(PortPairGroupWebResource.class);
+ private final PortPairGroupService service = get(PortPairGroupService.class);
+ public static final String PORT_PAIR_GROUP_NOT_FOUND = "Port pair group not found";
+ public static final String PORT_PAIR_GROUP_ID_EXIST = "Port pair group exists";
+ public static final String PORT_PAIR_GROUP_ID_NOT_EXIST = "Port pair group does not exist with identifier";
+
+ /**
+ * Get details of all port pair groups created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPairGroups() {
+ Iterable<PortPairGroup> portPairGroups = service.getPortPairGroups();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pair_groups", new PortPairGroupCodec().encode(portPairGroups, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Get details of a specified port pair group id.
+ *
+ * @param id port pair group id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{group_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPairGroup(@PathParam("group_id") String id) {
+
+ if (!service.exists(PortPairGroupId.of(id))) {
+ return Response.status(NOT_FOUND)
+ .entity(PORT_PAIR_GROUP_NOT_FOUND).build();
+ }
+ PortPairGroup portPairGroup = nullIsNotFound(service.getPortPairGroup(PortPairGroupId.of(id)),
+ PORT_PAIR_GROUP_NOT_FOUND);
+
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pair_group", new PortPairGroupCodec().encode(portPairGroup, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Creates a new port pair group.
+ *
+ * @param stream port pair group from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPortPairGroup(InputStream stream) {
+
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+
+ PortPairGroup portPairGroup = codec(PortPairGroup.class).decode(jsonTree, this);
+ Boolean issuccess = nullIsNotFound(service.createPortPairGroup(portPairGroup),
+ PORT_PAIR_GROUP_NOT_FOUND);
+ return Response.status(OK).entity(issuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Exception while creating port pair group {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Update details of a specified port pair group id.
+ *
+ * @param id port pair group id
+ * @param stream port pair group from json
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @PUT
+ @Path("{group_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updatePortPairGroup(@PathParam("group_id") String id,
+ final InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortPairGroup portPairGroup = codec(PortPairGroup.class).decode(jsonTree, this);
+ Boolean isSuccess = nullIsNotFound(service.updatePortPairGroup(portPairGroup), PORT_PAIR_GROUP_NOT_FOUND);
+ return Response.status(OK).entity(isSuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Update port pair group failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Delete details of a specified port pair group id.
+ *
+ * @param id port pair group id
+ */
+ @Path("{group_id}")
+ @DELETE
+ public void deletePortPairGroup(@PathParam("group_id") String id) {
+ log.debug("Deletes port pair group by identifier {}.", id);
+ PortPairGroupId portPairGroupId = PortPairGroupId.of(id);
+ Boolean issuccess = nullIsNotFound(service.removePortPairGroup(portPairGroupId),
+ PORT_PAIR_GROUP_NOT_FOUND);
+ if (!issuccess) {
+ log.debug("Port pair group identifier {} does not exist", id);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java
new file mode 100644
index 00000000..8bf459c2
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/PortPairWebResource.java
@@ -0,0 +1,161 @@
+/*
+ * 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.vtnweb.resources;
+
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.OK;
+import static org.onlab.util.Tools.nullIsNotFound;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.portpair.PortPairService;
+import org.onosproject.vtnweb.web.PortPairCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program port pair.
+ */
+@Path("port_pairs")
+public class PortPairWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(PortPairWebResource.class);
+ private final PortPairService service = get(PortPairService.class);
+ public static final String PORT_PAIR_NOT_FOUND = "Port pair not found";
+ public static final String PORT_PAIR_ID_EXIST = "Port pair exists";
+ public static final String PORT_PAIR_ID_NOT_EXIST = "Port pair does not exist with identifier";
+
+ /**
+ * Get details of all port pairs created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPairs() {
+ Iterable<PortPair> portPairs = service.getPortPairs();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pairs", new PortPairCodec().encode(portPairs, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Get details of a specified port pair id.
+ *
+ * @param id port pair id
+ * @return 200 OK, 404 if given identifier does not exist
+ */
+ @GET
+ @Path("{pair_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getPortPair(@PathParam("portPairId") String id) {
+
+ if (!service.exists(PortPairId.of(id))) {
+ return Response.status(NOT_FOUND)
+ .entity(PORT_PAIR_NOT_FOUND).build();
+ }
+ PortPair portPair = nullIsNotFound(service.getPortPair(PortPairId.of(id)),
+ PORT_PAIR_NOT_FOUND);
+
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("port_pair", new PortPairCodec().encode(portPair, this));
+ return ok(result).build();
+ }
+
+ /**
+ * Creates a new port pair.
+ *
+ * @param stream port pair from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPortPair(InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+
+ PortPair portPair = codec(PortPair.class).decode(jsonTree, this);
+ Boolean isSuccess = nullIsNotFound(service.createPortPair(portPair),
+ PORT_PAIR_NOT_FOUND);
+ return Response.status(OK).entity(isSuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Exception while creating port pair {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Update details of a specified port pair id.
+ *
+ * @param id port pair id
+ * @param stream port pair from json
+ * @return 200 OK, 404 if the given identifier does not exist
+ */
+ @PUT
+ @Path("{pair_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updatePortPair(@PathParam("pair_id") String id,
+ final InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ PortPair portPair = codec(PortPair.class).decode(jsonTree, this);
+ Boolean isSuccess = nullIsNotFound(service.updatePortPair(portPair), PORT_PAIR_NOT_FOUND);
+ return Response.status(OK).entity(isSuccess.toString()).build();
+ } catch (IOException e) {
+ log.error("Update port pair failed because of exception {}.", e.toString());
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * Delete details of a specified port pair id.
+ *
+ * @param id port pair id
+ */
+ @Path("{pair_id}")
+ @DELETE
+ public void deletePortPair(@PathParam("pair_id") String id) {
+
+ PortPairId portPairId = PortPairId.of(id);
+ Boolean isSuccess = nullIsNotFound(service.removePortPair(portPairId),
+ PORT_PAIR_NOT_FOUND);
+ if (!isSuccess) {
+ log.debug("Port pair identifier {} does not exist", id);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
index fd5b1ee4..4c17633c 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FlowClassifierCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
@@ -62,7 +62,7 @@ public final class FlowClassifierCodec extends JsonCodec<FlowClassifier> {
String flowClassifierId = nullIsIllegal(json.get(FLOW_CLASSIFIER_ID),
FLOW_CLASSIFIER_ID + MISSING_MEMBER_MESSAGE).asText();
- resultBuilder.setFlowClassifierId(FlowClassifierId.flowClassifierId(UUID.fromString(flowClassifierId)));
+ resultBuilder.setFlowClassifierId(FlowClassifierId.of(UUID.fromString(flowClassifierId)));
String tenantId = nullIsIllegal(json.get(TENANT_ID), TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
resultBuilder.setTenantId(TenantId.tenantId(tenantId));
@@ -131,4 +131,4 @@ public final class FlowClassifierCodec extends JsonCodec<FlowClassifier> {
.put("DST_PORT", flowClassifier.dstPort().toString());
return result;
}
-} \ No newline at end of file
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
index 28da5cd1..1e9cf009 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
@@ -59,7 +59,7 @@ public final class PortChainCodec extends JsonCodec<PortChain> {
String id = nullIsIllegal(json.get(ID),
ID + MISSING_MEMBER_MESSAGE).asText();
- resultBuilder.setId(PortChainId.portChainId(id));
+ resultBuilder.setId(PortChainId.of(id));
String tenantId = nullIsIllegal(json.get(TENANT_ID),
TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
@@ -76,14 +76,14 @@ public final class PortChainCodec extends JsonCodec<PortChain> {
ArrayNode arrayNode = (ArrayNode) json.path(PORT_PAIR_GROUPS);
if (arrayNode != null) {
List<PortPairGroupId> list = Lists.newArrayList();
- arrayNode.forEach(i -> list.add(PortPairGroupId.portPairGroupId(i.asText())));
+ arrayNode.forEach(i -> list.add(PortPairGroupId.of(i.asText())));
resultBuilder.setPortPairGroups(list);
}
arrayNode = (ArrayNode) json.path(FLOW_CLASSIFIERS);
if (arrayNode != null) {
List<FlowClassifierId> list = Lists.newArrayList();
- arrayNode.forEach(i -> list.add(FlowClassifierId.flowClassifierId(UUID.fromString(i.asText()))));
+ arrayNode.forEach(i -> list.add(FlowClassifierId.of(UUID.fromString(i.asText()))));
resultBuilder.setFlowClassifiers(list);
}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java
new file mode 100644
index 00000000..691536f4
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairCodec.java
@@ -0,0 +1,94 @@
+/*
+ * 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.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.vtnrsc.DefaultPortPair;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Port Pair JSON codec.
+ */
+public final class PortPairCodec extends JsonCodec<PortPair> {
+
+ private static final String ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String INGRESS = "ingress";
+ private static final String EGRESS = "egress";
+ private static final String MISSING_MEMBER_MESSAGE =
+ " member is required in PortPair";
+
+ @Override
+ public PortPair decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ PortPair.Builder resultBuilder = new DefaultPortPair.Builder();
+
+ CoreService coreService = context.getService(CoreService.class);
+
+ String id = nullIsIllegal(json.get(ID),
+ ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setId(PortPairId.of(id));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID),
+ TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String name = nullIsIllegal(json.get(NAME),
+ NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(name);
+
+ String description = nullIsIllegal(json.get(DESCRIPTION),
+ DESCRIPTION + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDescription(description);
+
+ String ingressPort = nullIsIllegal(json.get(INGRESS),
+ INGRESS + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setIngress(ingressPort);
+
+ String egressPort = nullIsIllegal(json.get(EGRESS),
+ EGRESS + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setEgress(egressPort);
+
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(PortPair portPair, CodecContext context) {
+ checkNotNull(portPair, "port pair cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(ID, portPair.portPairId().toString())
+ .put(TENANT_ID, portPair.tenantId().toString())
+ .put(NAME, portPair.name())
+ .put(DESCRIPTION, portPair.description())
+ .put(INGRESS, portPair.ingress())
+ .put(EGRESS, portPair.egress());
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java
new file mode 100644
index 00000000..b5ae266b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortPairGroupCodec.java
@@ -0,0 +1,95 @@
+/*
+ * 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.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import java.util.List;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.vtnrsc.DefaultPortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+
+/**
+ * Port Pair Group JSON codec.
+ */
+public final class PortPairGroupCodec extends JsonCodec<PortPairGroup> {
+
+ private static final String ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String PORT_PAIRS = "port_pairs";
+ private static final String MISSING_MEMBER_MESSAGE =
+ " member is required in PortPairGroup";
+
+ @Override
+ public PortPairGroup decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ PortPairGroup.Builder resultBuilder = new DefaultPortPairGroup.Builder();
+
+ CoreService coreService = context.getService(CoreService.class);
+
+ String id = nullIsIllegal(json.get(ID),
+ ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setId(PortPairGroupId.of(id));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID),
+ TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String name = nullIsIllegal(json.get(NAME),
+ NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(name);
+
+ String description = nullIsIllegal(json.get(DESCRIPTION),
+ DESCRIPTION + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDescription(description);
+
+ List<PortPairId> list = Lists.newArrayList();
+ ArrayNode arrayNode = (ArrayNode) json.path(PORT_PAIRS);
+ arrayNode.forEach(i -> list.add(PortPairId.of(i.asText())));
+ resultBuilder.setPortPairs(list);
+
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(PortPairGroup portPairGroup, CodecContext context) {
+ checkNotNull(portPairGroup, "port pair group cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(ID, portPairGroup.portPairGroupId().toString())
+ .put(TENANT_ID, portPairGroup.tenantId().toString())
+ .put(NAME, portPairGroup.name())
+ .put(DESCRIPTION, portPairGroup.description())
+ .put(PORT_PAIRS, portPairGroup.portPairs().toString());
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
index 4cc12455..97337960 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
@@ -33,6 +33,10 @@
org.onosproject.vtnweb.resources.TenantNetworkWebResource,
org.onosproject.vtnweb.resources.SubnetWebResource,
org.onosproject.vtnweb.resources.VirtualPortWebResource
+ org.onosproject.vtnweb.resources.FlowClassifierWebResource
+ org.onosproject.vtnweb.resources.PortChainWebResource
+ org.onosproject.vtnweb.resources.PortPairGroupWebResource
+ org.onosproject.vtnweb.resources.PortPairWebResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java
new file mode 100644
index 00000000..7651e098
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/PortPairCodecTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.vtnweb.web;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Port pair codec unit tests.
+ */
+public class PortPairCodecTest {
+
+ SfcCodecContext context;
+ JsonCodec<PortPair> portPairCodec;
+ /**
+ * Sets up for each test. Creates a context and fetches the port pair
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new SfcCodecContext();
+ portPairCodec = context.codec(PortPair.class);
+ assertThat(portPairCodec, notNullValue());
+ }
+
+ /**
+ * Reads in a port pair from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the port pair
+ * @return decoded port pair
+ * @throws IOException if processing the resource fails
+ */
+ private PortPair getPortPair(String resourceName) throws IOException {
+ InputStream jsonStream = PortPairCodecTest.class
+ .getResourceAsStream(resourceName);
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode json = mapper.readTree(jsonStream);
+ assertThat(json, notNullValue());
+ PortPair portPair = portPairCodec.decode((ObjectNode) json, context);
+ assertThat(portPair, notNullValue());
+ return portPair;
+ }
+
+ /**
+ * Checks that a simple port pair decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecPortPairTest() throws IOException {
+
+ PortPair portPair = getPortPair("portPair.json");
+
+ assertThat(portPair, notNullValue());
+
+ PortPairId portPairId = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ TenantId tenantId = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5");
+
+ assertThat(portPair.portPairId().toString(), is(portPairId.toString()));
+ assertThat(portPair.name(), is("PP1"));
+ assertThat(portPair.tenantId().toString(), is(tenantId.toString()));
+ assertThat(portPair.description(), is("SF-A"));
+ assertThat(portPair.ingress().toString(), is("dace4513-24fc-4fae-af4b-321c5e2eb3d1"));
+ assertThat(portPair.egress().toString(), is("aef3478a-4a56-2a6e-cd3a-9dee4e2ec345"));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java
new file mode 100644
index 00000000..fe9d7995
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/SfcCodecContext.java
@@ -0,0 +1,77 @@
+/*
+ * 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.vtnweb.web;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairGroup;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Mock codec context for use in codec unit tests.
+ */
+public class SfcCodecContext implements CodecContext {
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final Map<Class<?>, JsonCodec> codecs = new ConcurrentHashMap<>();
+
+ /**
+ * Constructs a new mock codec context.
+ */
+ public SfcCodecContext() {
+ codecs.clear();
+ registerCodec(PortPair.class, new PortPairCodec());
+ registerCodec(PortChain.class, new PortChainCodec());
+ registerCodec(PortPairGroup.class, new PortPairGroupCodec());
+ registerCodec(FlowClassifier.class, new FlowClassifierCodec());
+ }
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ // TODO
+ return null;
+ }
+
+ /**
+ * Registers the specified JSON codec for the given entity class.
+ *
+ * @param entityClass entity class
+ * @param codec JSON codec
+ * @param <T> entity type
+ */
+ public <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec) {
+ codecs.putIfAbsent(entityClass, codec);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ return codecs.get(entityClass);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json
new file mode 100644
index 00000000..f858c88c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/portPair.json
@@ -0,0 +1,9 @@
+{
+ "id": "78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae",
+ "name": "PP1",
+ "tenant_id": "d382007aa9904763a801f68ecf065cf5",
+ "description": "SF-A",
+ "ingress": "dace4513-24fc-4fae-af4b-321c5e2eb3d1",
+ "egress": "aef3478a-4a56-2a6e-cd3a-9dee4e2ec345"
+}
+