diff options
Diffstat (limited to 'framework/src/onos/apps')
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" +} + |