Expanded CMTS emulator to accept at least one type of gate request. Future work will... 67/19467/2
authorSteven Pisarski <s.pisarski@cablelabs.com>
Fri, 1 May 2015 22:55:12 +0000 (16:55 -0600)
committerThomas Kee <xsited@yahoo.com>
Fri, 8 May 2015 19:52:00 +0000 (12:52 -0700)
Change-Id: I98681f2514b88575a951f1e16a683ac046d32750
Signed-off-by: Steven Pisarski <s.pisarski@cablelabs.com>
packetcable-driver/src/main/java/org/pcmm/rcd/impl/CMTS.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepAgent.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepConnection.java
packetcable-driver/src/main/java/org/umu/cops/prpep/COPSPepReqStateMan.java
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMService.java
packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PacketcableProvider.java
packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java

index 8f17553ed203c749386542da52a5bdd1ea87a794..9a8126b4f149309b987e0981c8722b3dee32e3a5 100644 (file)
@@ -45,7 +45,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
 
                return new AbstractPCMMClientHandler(socket) {
 
-                       private String handle;
+                       private COPSHandle handle;
 
                        public void run() {
                                try {
@@ -88,11 +88,11 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                                {
                                                        Properties prop = new Properties();
                                                        COPSMsg reqMsg = MessageFactory.getInstance().create(OPCode.REQ, prop);
-                                                       handle = ((COPSReqMsg) reqMsg).getClientHandle().getId().str();
+                                                       handle = ((COPSReqMsg) reqMsg).getClientHandle();
                                                        sendRequest(reqMsg);
                                                }
                                                // Create the connection manager
-                                               PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
+                                               final PCMMCmtsConnection conn = new PCMMCmtsConnection(CLIENT_TYPE, socket);
                                                // pcmm specific handler
                                                // conn.addReqStateMgr(handle, new
                                                // PCMMPSReqStateMan(CLIENT_TYPE, handle));
@@ -137,8 +137,8 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                        super(clientType, sock);
                }
 
-               public COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process)
-                               throws COPSException, COPSPepException {
+               public COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
+                               throws COPSException {
                        return super.addRequestState(clientHandle, process);
                }
 
@@ -151,22 +151,17 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
        @SuppressWarnings("rawtypes")
        class PCMMPSReqStateMan extends COPSPepReqStateMan {
 
-               public PCMMPSReqStateMan(final short clientType, final String clientHandle) {
+               public PCMMPSReqStateMan(final short clientType, final COPSHandle clientHandle) {
                        super(clientType, clientHandle);
                        _process = new CmtsDataProcessor();
 
                }
 
                @Override
-               protected void processDecision(COPSDecisionMsg dMsg)
-                               throws COPSPepException {
-
-                       // COPSHandle handle = dMsg.getClientHandle();
-                       Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
-
-            Map<String, String> removeDecs = new HashMap<>();
-            Map<String, String> installDecs = new HashMap<>();
-            Map<String, String> errorDecs = new HashMap<>();
+               protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
+            final Map<String, String> removeDecs = new HashMap<>();
+                       final Map<String, String> installDecs = new HashMap<>();
+                       final Map<String, String> errorDecs = new HashMap<>();
 
                        for (final Set<COPSDecision> copsDecisions : dMsg.getDecisions().values()) {
                                final COPSDecision cmddecision = copsDecisions.iterator().next();
@@ -176,7 +171,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                 switch (cmddecision.getCommand()) {
                     case INSTALL:
                         for (final COPSDecision decision : copsDecisions) {
-                            COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                                                       final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
                             switch (obj.getSNum()) {
                                 // TODO when there is install request only the PR_PRID
                                 // is git but the ClientSI object containing the PR_EPD
@@ -194,7 +189,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                         }
                     case REMOVE:
                         for (final COPSDecision decision : copsDecisions) {
-                            COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                                                       final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
                             switch (obj.getSNum()) {
                                 // TODO when there is install request only the PR_PRID
                                 // is git but the ClientSI object containing the PR_EPD
@@ -254,16 +249,16 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                }
 
                @Override
-               public boolean isFailReport(COPSPepReqStateMan man) {
+               public boolean isFailReport(final COPSPepReqStateMan man) {
                        return (errorDecs != null && errorDecs.size() > 0);
                }
 
                @Override
-               public Map<String, String> getReportData(COPSPepReqStateMan man) {
+               public Map<String, String> getReportData(final COPSPepReqStateMan man) {
                        if (isFailReport(man)) {
                                return errorDecs;
                        } else {
-                               Map<String, String> siDataHashTable = new HashMap<>();
+                               final Map<String, String> siDataHashTable = new HashMap<>();
                                if (installDecs.size() > 0) {
                                        String data = "";
                                        for (String k : installDecs.keySet()) {
@@ -271,7 +266,7 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                                                break;
                                        }
                                        final ITransactionID transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID();
-                                       IPCMMGate responseGate = new PCMMGateReq();
+                                       final IPCMMGate responseGate = new PCMMGateReq();
                                        responseGate.setTransactionID(transactionID);
 
                     // TODO FIXME - Why is the key always null??? What value should be used here???
@@ -283,15 +278,15 @@ public class CMTS extends AbstractPCMMServer implements ICMTS {
                }
 
                @Override
-               public Hashtable getClientData(COPSPepReqStateMan man) {
+               public Map<String, String> getClientData(COPSPepReqStateMan man) {
                        // TODO Auto-generated method stub
-                       return new Hashtable<String, String>();
+                       return new HashMap<>();
                }
 
                @Override
-               public Hashtable getAcctData(COPSPepReqStateMan man) {
+               public Map<String, String> getAcctData(COPSPepReqStateMan man) {
                        // TODO Auto-generated method stub
-                       return new Hashtable<String, String>();
+                       return new HashMap<>();
                }
 
                @Override
index e57823ece6afe3fe02b8bc0ac93711b1cff4d3ad..e7ab809d9260249aec2701409b8f13f2eb7d9117 100644 (file)
@@ -6,6 +6,8 @@
 
 package org.umu.cops.prpep;
 
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.*;
 import org.umu.cops.stack.COPSHeader.OPCode;
 
@@ -20,6 +22,8 @@ import java.net.UnknownHostException;
  */
 public class COPSPepAgent {
 
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepAgent.class);
+
     /**
         PEP's Identifier
      */
@@ -117,9 +121,8 @@ public class COPSPepAgent {
      * @throws   COPSException
      * @throws   COPSPepException
      */
-    public boolean connect(String psHost, int psPort) throws IOException, COPSException, COPSPepException {
-
-        // COPSDebug.out(getClass().getName(), "Thread ( " + _pepID + ") - Connecting to PDP");
+    public boolean connect(String psHost, int psPort) throws IOException, COPSException {
+        logger.info("Thread ( " + _pepID + ") - Connecting to PDP");
         _psHost = psHost;
         _psPort = psPort;
 
@@ -173,8 +176,8 @@ public class COPSPepAgent {
      * @throws COPSPepException
      * @throws COPSException
      */
-    public COPSPepReqStateMan addRequestState(final String handle, final COPSPepDataProcess process)
-            throws COPSPepException, COPSException {
+    public COPSPepReqStateMan addRequestState(final COPSHandle handle, final COPSPepDataProcess process)
+            throws COPSException {
         if (_conn != null) {
             return _conn.addRequestState(handle, process);
         }
@@ -188,8 +191,7 @@ public class COPSPepAgent {
      * @throws COPSPepException
      * @throws COPSException
      */
-    public void deleteRequestState(final COPSPepReqStateMan man)
-    throws COPSPepException, COPSException {
+    public void deleteRequestState(final COPSPepReqStateMan man) throws COPSException {
         if (_conn != null)
             _conn.deleteRequestState(man);
     }
@@ -225,8 +227,8 @@ public class COPSPepAgent {
      * @throws   COPSPepException
      *
      */
-    private COPSPepConnection processConnection(String psHost, int psPort)
-            throws IOException, COPSException, COPSPepException {
+    private COPSPepConnection processConnection(final String psHost, final int psPort)
+            throws IOException, COPSException {
         // Build OPN
         final COPSClientOpenMsg msg = new COPSClientOpenMsg(_clientType, new COPSPepId(new COPSData(_pepID)),
                 null, null, null);
index f51109fdd398cf406acb7d122bf476406a66cc03..f8eaf269e3f335df7c78bf8d4aa60537b7e1f622 100644 (file)
@@ -26,7 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class COPSPepConnection implements Runnable {
 
-    public final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepConnection.class);
 
     /** Socket connected to PDP */
     protected Socket _sock;
@@ -55,7 +55,7 @@ public class COPSPepConnection implements Runnable {
     /**
         Maps a COPS Client Handle to a Request State Manager
      */
-    protected final Map<String, COPSPepReqStateMan> _managerMap;
+    protected final Map<COPSHandle, COPSPepReqStateMan> _managerMap;
 
     /**
         COPS error returned by PDP
@@ -68,7 +68,6 @@ public class COPSPepConnection implements Runnable {
      * @param sock          Socket connected to PDP
      */
     public COPSPepConnection(final short clientType, final Socket sock) {
-
         _clientType = clientType;
         _sock = sock;
 
@@ -236,21 +235,21 @@ public class COPSPepConnection implements Runnable {
      * @throws COPSException
      * @throws IOException
      */
-    protected byte processMessage(final Socket conn) throws COPSPepException, COPSException, IOException {
+    protected byte processMessage(final Socket conn) throws COPSException, IOException {
         final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
 
         switch (msg.getHeader().getOpCode()) {
             case CC:
-                handleClientCloseMsg(conn, msg);
+                handleClientCloseMsg(conn, (COPSClientCloseMsg)msg);
                 return (byte)OPCode.CC.ordinal();
             case DEC:
-                handleDecisionMsg(conn, msg);
+                handleDecisionMsg((COPSDecisionMsg)msg);
                 return (byte)OPCode.DEC.ordinal();
             case SSQ:
-                handleSyncStateReqMsg(conn, msg);
+                handleSyncStateReqMsg((COPSSyncStateMsg)msg);
                 return (byte)OPCode.SSQ.ordinal();
             case KA:
-                handleKeepAliveMsg(conn, msg);
+                handleKeepAliveMsg((COPSKAMsg)msg);
                 return (byte)OPCode.KA.ordinal();
             default:
                 throw new COPSPepException("Message not expected (" + msg.getHeader().getOpCode() + ").");
@@ -259,31 +258,18 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Handle Client Close Message, close the passed connection
-     *
      * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
-     *
-     * <Client-Close> ::= <Common Header>
-     *                      <Error>
-     *                      [<Integrity>]
-     *
-     * Not support [<Integrity>]
-     *
+     * @param    cMsg                a  COPSClientCloseMsg
      */
-    private void handleClientCloseMsg(Socket conn, COPSMsg msg) {
-        COPSClientCloseMsg cMsg = (COPSClientCloseMsg) msg;
+    private void handleClientCloseMsg(final Socket conn, final COPSClientCloseMsg cMsg) {
         _error = cMsg.getError();
-
-        // COPSDebug.out(getClass().getName(),"Got close request, closing connection " +
-        //  conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
-
+        logger.info("Got close request, closing connection "
+                + conn.getInetAddress() + ":" + conn.getPort() + ":[Error " + _error.getDescription() + "]");
         try {
             // Support
             if (cMsg.getIntegrity() != null) {
                 logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
             }
-
             conn.close();
         } catch (Exception unae) {
             logger.error("Unexpected exception closing connection", unae);
@@ -292,9 +278,7 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Method getError
-     *
      * @return   a COPSError
-     *
      */
     protected COPSError getError()  {
         return _error;
@@ -302,25 +286,14 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Handle Keep Alive Message
-     *
-     * <Keep-Alive> ::= <Common Header>
-     *                  [<Integrity>]
-     *
-     * Not support [<Integrity>]
-     *
-     * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    cMsg                a  COPSKAMsg
      */
-    private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
-        COPSKAMsg cMsg = (COPSKAMsg) msg;
-
-        // COPSDebug.out(getClass().getName(),"Get KAlive Msg");
-
+    private void handleKeepAliveMsg(final COPSKAMsg cMsg) {
+        logger.info("Get KAlive Msg");
         try {
             // Support
             if (cMsg.getIntegrity() != null) {
-                logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+                logger.warn("Unsupported objects (Integrity)");
             }
 
             // should we do anything else?? ....
@@ -332,39 +305,20 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Method handleDecisionMsg
-     *
-     * <Decision Message> ::= <Common Header: Flag SOLICITED>
-     *                          <Client Handle>
-     *                          *(<Decision>) | <Error>
-     *                          [<Integrity>]
-     * <Decision> ::= <Context>
-     *                  <Decision: Flags>
-     *                  [<Named Decision Data: Provisioning>]
-     * <Decision: Flags> ::= <Command-Code> NULLFlag
-     * <Command-Code> ::= NULLDecision | Install | Remove
-     * <Named Decision Data> ::= <<Install Decision> | <Remove Decision>>
-     * <Install Decision> ::= *(<PRID> <EPD>)
-     * <Remove Decision> ::= *(<PRID> | <PPRID>)
-     *
-     * Very important, this is actually being treated like this:
-     * <Install Decision> ::= <PRID> | <EPD>
-     * <Remove Decision> ::= <PRID> | <PPRID>
-     *
-     * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    dMsg                 a  COPSDecisionMsg
      */
-    private void handleDecisionMsg(final Socket conn, final COPSMsg msg) throws COPSPepException {
-        final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+    private void handleDecisionMsg(final COPSDecisionMsg dMsg) throws COPSPepException {
         final COPSHandle handle = dMsg.getClientHandle();
         final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
 
         for (final Set<COPSDecision> copsDecisions: decisions.values()) {
             for (final COPSDecision decision : copsDecisions) {
                 // Get the associated manager
-                final COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
-                if (manager == null)
-                    logger.warn("Unable to find state manager with key - " + handle.getId().str());
+                final COPSPepReqStateMan manager = _managerMap.get(handle);
+                if (manager == null) {
+                    logger.warn("Unable to find state manager with key - " + handle);
+                    return;
+                }
 
                 // Check message type
                 // TODO FIXME - Use of manager object could result in a NPE
@@ -374,10 +328,10 @@ public class COPSPepConnection implements Runnable {
                         manager.processDeleteRequestState(dMsg);
                     else
                         // Open new Request State
-                        handleOpenNewRequestStateMsg(conn, handle);
+                        handleOpenNewRequestStateMsg(handle);
                 } else
                     // Decision
-                    manager.processDecision(dMsg);
+                    manager.processDecision(dMsg, _sock);
             }
         }
     }
@@ -385,82 +339,60 @@ public class COPSPepConnection implements Runnable {
 
     /**
      * Method handleOpenNewRequestStateMsg
-     *
-     * @param    conn                a  Socket
      * @param    handle              a  COPSHandle
-     *
      */
-    private void handleOpenNewRequestStateMsg(Socket conn, COPSHandle handle) throws COPSPepException {
-
-        COPSPepReqStateMan manager = _managerMap.get(handle.getId().str());
+    private void handleOpenNewRequestStateMsg(final COPSHandle handle) throws COPSPepException {
+        final COPSPepReqStateMan manager = _managerMap.get(handle);
         if (manager == null)
             logger.warn("Unable to find state manager with key - " + handle.getId().str());
-
-        // TODO FIXME - Use of manager object could result in a NPE
-        manager.processOpenNewRequestState();
+        else
+            manager.processOpenNewRequestState();
     }
 
     /**
      * Method handleSyncStateReqMsg
-     *
-     *              <Synchronize State> ::= <Common Header>
-     *                                      [<Client Handle>]
-     *                                      [<Integrity>]
-     *
-     * @param    conn                a  Socket
-     * @param    msg                 a  COPSMsg
-     *
+     * @param    cMsg                a  COPSSyncStateMsg
      */
-    private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
-        COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
-
-        // Support
+    private void handleSyncStateReqMsg(final COPSSyncStateMsg cMsg) throws COPSPepException {
         if (cMsg.getIntegrity() != null) {
-            logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
+            logger.warn("Unsupported objects (Integrity)");
         }
 
-        COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
-        if (manager == null) {
+        final COPSPepReqStateMan manager = _managerMap.get(cMsg.getClientHandle());
+        if (manager == null)
             logger.warn("Unable to find state manager with key - " + cMsg.getClientHandle().getId().str());
-        } else {
+        else
             manager.processSyncStateRequest(cMsg);
-        }
     }
 
     /**
      * Method createRequestState
-     *
      * @param    clientHandle             a  String
      * @param    process                  a  COPSPepDataProcess
-     *
      * @return   a COPSPepmanager
-     *
      * @throws   COPSException
      * @throws   COPSPepException
-     *
      */
-    protected COPSPepReqStateMan addRequestState(String clientHandle, COPSPepDataProcess process) throws COPSException,
-            COPSPepException {
-        COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
+    protected COPSPepReqStateMan addRequestState(final COPSHandle clientHandle, final COPSPepDataProcess process)
+            throws COPSException {
+        final COPSPepReqStateMan manager = new COPSPepReqStateMan(_clientType, clientHandle);
         if (_managerMap.get(clientHandle) != null)
             throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
 
         manager.setDataProcess(process);
-        _managerMap.put(clientHandle,manager);
+        _managerMap.put(clientHandle, manager);
+        logger.info("Added state manager with key - " + clientHandle);
         manager.initRequestState(_sock);
         return manager;
     }
 
     /**
      * Method deleteRequestState
-     *
      * @param    manager             a  COPSPepReqStateMan
-     *
      * @throws   COPSException
      * @throws   COPSPepException
-     *
      */
-    protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException, COPSPepException {
+    protected void deleteRequestState(COPSPepReqStateMan manager) throws COPSException {
         manager.finalizeRequestState();
     }
 
index dc0e1d834f46743b3a15b822e5b9694674185109..8d7941889526a666d4ba42da404be26d5e798ffa 100644 (file)
@@ -6,12 +6,19 @@
 
 package org.umu.cops.prpep;
 
+import org.pcmm.gates.impl.GateID;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
+import org.umu.cops.stack.COPSReportType.ReportType;
 
+import java.io.IOException;
 import java.net.Socket;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
 
 /**
  * COPSPepReqStateMan manages Request State using Client Handle (RFC 2748 pag. 21)
@@ -37,6 +44,7 @@ import java.util.Set;
  */
 public class COPSPepReqStateMan {
 
+    // TODO - place these values into an enumeration
     /**
      * Request State created
      */
@@ -86,6 +94,8 @@ public class COPSPepReqStateMan {
      */
     public final static short ST_ACCT = 12;
 
+    private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
+
     /**
      * The client-type identifies the policy client
      */
@@ -123,8 +133,8 @@ public class COPSPepReqStateMan {
      * @param    clientHandle                a Client Handle
      *
      */
-    public COPSPepReqStateMan(final short clientType, final String clientHandle) {
-        _handle = new COPSHandle(new COPSData(clientHandle));
+    public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle) {
+        _handle = clientHandle;
         _clientType = clientType;
         _syncState = true;
         _status = ST_CREATE;
@@ -175,7 +185,7 @@ public class COPSPepReqStateMan {
      * @param    process              a  PolicyConfigure
      *
      */
-    public void setDataProcess(COPSPepDataProcess process) {
+    public void setDataProcess(final COPSPepDataProcess process) {
         _process = process;
     }
 
@@ -185,8 +195,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void initRequestState(Socket sock)
-    throws COPSPepException {
+    protected void initRequestState(final Socket sock) throws COPSPepException {
         // Inits an object for sending COPS messages to the PDP
         _sender = new COPSPepMsgSender(_clientType, _handle, sock);
 
@@ -212,8 +221,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void finalizeRequestState()
-    throws COPSPepException {
+    protected void finalizeRequestState() throws COPSPepException {
         _sender.sendDeleteRequest();
         _status = ST_FINAL;
     }
@@ -226,32 +234,79 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processDecision(COPSDecisionMsg dMsg)
-    throws COPSPepException {
-        // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
-
-        // COPSHandle handle = dMsg.getClientHandle();
+    protected void processDecision(final COPSDecisionMsg dMsg, final Socket socket) throws COPSPepException {
+        logger.info("Processing decision message - " + dMsg);
         final Map<COPSContext, Set<COPSDecision>> decisions = dMsg.getDecisions();
 
         final Map<String, String> removeDecs = new HashMap<>();
         final Map<String, String> installDecs = new HashMap<>();
 
-        for (Set<COPSDecision> copsDecisions: decisions.values()) {
+        for (final Set<COPSDecision> copsDecisions: decisions.values()) {
             final COPSDecision cmddecision = copsDecisions.iterator().next();
             String prid = "";
             switch (cmddecision.getCommand()) {
                 case INSTALL:
+                    // TODO - break up this block
                     for (final COPSDecision decision : copsDecisions) {
-                        final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
-                        switch (obj.getSNum()) {
-                            case COPSPrObjBase.PR_PRID:
-                                prid = obj.getData().str();
-                                break;
-                            case COPSPrObjBase.PR_EPD:
-                                installDecs.put(prid, obj.getData().str());
-                                break;
-                            default:
-                                break;
+                        if (decision.getData().getData().length != 0) {
+                            final COPSPrObjBase obj = new COPSPrObjBase(decision.getData().getData());
+                            switch (obj.getSNum()) {
+                                case COPSPrObjBase.PR_PRID:
+                                    prid = obj.getData().str();
+                                    break;
+                                case COPSPrObjBase.PR_EPD:
+                                    installDecs.put(prid, obj.getData().str());
+                                    break;
+                            }
+                        }
+                        if (decision.getFlag().equals(DecisionFlag.REQERROR)) {
+                            // This is assuming a gate set right or wrong
+                            if (dMsg.getDecisions().size() == 1 && dMsg.getDecSI() != null) {
+                                final PCMMGateReq gateReq = new PCMMGateReq(dMsg.getDecSI().getData().getData());
+                                // TODO - Check and/or Set state here
+                                // Gate ADD gateReq.getTrafficProfile() != null
+                                // Gate REMOVE gateReq.getTrafficProfile() == null
+//                                    final String gateName = trafficProfile.getData().str();
+//                                    final Direction gateDir = gateReq.getGateSpec().getDirection();
+                                final boolean success = true;
+
+                                // Set response
+                                final List<Byte> data = new ArrayList<>();
+                                for (final byte val : gateReq.getTransactionID().getAsBinaryArray())
+                                    data.add(val);
+                                for (final byte val : gateReq.getAMID().getAsBinaryArray())
+                                    data.add(val);
+                                for (final byte val : gateReq.getSubscriberID().getAsBinaryArray())
+                                    data.add(val);
+
+                                // Assign a gate ID
+                                final GateID gateID = new GateID();
+                                gateID.setGateID(UUID.randomUUID().hashCode());
+                                for (final byte val : gateID.getAsBinaryArray())
+                                    data.add(val);
+
+
+                                final byte[] csiArr = new byte[data.size()];
+                                for (int i = 0; i < data.size(); i++) {
+                                    csiArr[i] = data.get(i);
+                                }
+                                final COPSClientSI si = new COPSClientSI(CNum.CSI, CType.DEF, new COPSData(csiArr, 0, csiArr.length));
+
+                                final COPSReportMsg reportMsg;
+                                if (success) {
+                                    reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
+                                            new COPSReportType(ReportType.SUCCESS), si, null);
+                                } else {
+                                    reportMsg = new COPSReportMsg(_clientType, getClientHandle(),
+                                            new COPSReportType(ReportType.FAILURE), si, null);
+                                }
+
+                                try {
+                                    reportMsg.writeData(socket);
+                                } catch (IOException e) {
+                                    throw new COPSPepException("Error writing gate set SUCCESS Report", e);
+                                }
+                            }
                         }
                     }
                     break;
@@ -303,8 +358,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processOpenNewRequestState()
-    throws COPSPepException {
+    protected void processOpenNewRequestState() throws COPSPepException {
 
         if (_process != null)
             _process.newRequestState(this);
@@ -320,8 +374,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processDeleteRequestState(COPSDecisionMsg dMsg)
-    throws COPSPepException {
+    protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
         if (_process != null)
             _process.closeRequestState(this);
 
@@ -339,8 +392,7 @@ public class COPSPepReqStateMan {
      * @throws   COPSPepException
      *
      */
-    protected void processSyncStateRequest(COPSSyncStateMsg ssMsg)
-    throws COPSPepException {
+    protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSPepException {
         _syncState = false;
         // If an object for retrieving PEP features exists,
         // use it for retrieving them
@@ -357,25 +409,21 @@ public class COPSPepReqStateMan {
         _status = ST_SYNC;
     }
 
-    protected void processClosedConnection(COPSError error)
-    throws COPSPepException {
+    protected void processClosedConnection(final COPSError error) throws COPSPepException {
         if (_process != null)
             _process.notifyClosedConnection(this, error);
 
         _status = ST_CCONN;
     }
 
-    protected void processNoKAConnection()
-    throws COPSPepException {
+    protected void processNoKAConnection() throws COPSPepException {
         if (_process != null)
             _process.notifyNoKAliveReceived(this);
 
         _status = ST_NOKA;
     }
 
-    protected void processAcctReport()
-    throws COPSPepException {
-
+    protected void processAcctReport() throws COPSPepException {
         final Map<String, String> report;
         if (_process != null) report = _process.getAcctData(this);
         else report = new HashMap<>();
index 3ccabb106fe32a53a16866b8d787f299aa5029cf..97567d4792fa2dd290bbd46419608b630c092d9b 100644 (file)
@@ -35,7 +35,7 @@ public class PCMMService {
        private final IpAddress ipAddr;
        private final PortNumber portNum;
        protected final CcapClient ccapClient;
-       private Map<String, PCMMGateReq> gateRequests = Maps.newConcurrentMap();
+       protected Map<String, PCMMGateReq> gateRequests = Maps.newConcurrentMap();
 
        private final short clientType;
 
@@ -136,7 +136,7 @@ public class PCMMService {
                }
        }
 
-       public Boolean sendGateDelete(final Ccaps ccap, final String gatePathStr) {
+       public Boolean sendGateDelete(final String gatePathStr) {
                logger.info("sendGateDelete() - " + ccap);
                // recover the original gate request
                final PCMMGateReq gateReq = gateRequests.remove(gatePathStr);
@@ -178,20 +178,27 @@ public class PCMMService {
                }
        }
 
+       /**
+        * Used to interface with a CCAP (including CMTSs)
+        */
        protected class CcapClient {
                public final PCMMPdpDataProcess pcmmProcess;
                public final PCMMPdpAgent pcmmPdp;
 
-               // TODO - Needs to be initialized in connect() method or removed altogether as usage seems to be creating a new
-               // TODO - one each time is is used
-               protected transient PCMMPdpMsgSender pcmmSender;
-
                private final String ipv4;
                private final Integer port;
 
+               // Needs to be initialized in connect() method else would be final
+               protected transient PCMMPdpMsgSender pcmmSender;
+
                private transient Boolean isConnected = false;
                private transient String errMessage = null;
 
+               /**
+                * Constructor
+                * @param ccapIp - the IP of the CCAP to manage
+                * @param portNum - the port number of the CCAP to manage
+                */
                public CcapClient(final IpAddress ccapIp, final PortNumber portNum) {
                        ipv4 = ccapIp.getIpv4Address().getValue();
                        if (portNum != null)  port = portNum.getValue();
@@ -203,13 +210,16 @@ public class PCMMService {
                        pcmmPdp = new PCMMPdpAgent(clientType, ipv4, port, pcmmProcess);
                }
 
+               /**
+                * Starts the connection to the CCAP
+                */
                public void connect( ) {
                        logger.info("Attempting to connect to host: " + ipv4 + " port: " + port);
                        try  {
                                pcmmPdp.connect();
 
                                // Cannot instantiate until after pcmmPdp.connect() is called as this is where the client handle is created
-                               //                pcmmSender = new PCMMPdpMsgSender(PCMMDef.C_PCMM, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
+                               pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
 
                                isConnected = true;
                        } catch (Exception e) {
@@ -234,8 +244,8 @@ public class PCMMService {
                public Boolean sendGateSet(final PCMMGateReq gateReq) {
                        logger.info("CcapClient: sendGateSet(): {}:{} => {}", ipv4, port, gateReq);
                        try {
-                               pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
                                pcmmSender.sendGateSet(gateReq);
+
                                // TODO - determine if this is the correct place to perform this operation as this currently is the
                                // TODO - place where the gate ID can be set on the gateReq object
                                //                pcmmSender.handleGateReport(pcmmPdp.getSocket());
@@ -252,7 +262,6 @@ public class PCMMService {
                public Boolean sendGateDelete(final PCMMGateReq gateReq) {
                        logger.info("CcapClient: sendGateDelete(): {}:{} => {}", ipv4, port, gateReq);
                        try {
-                               pcmmSender = new PCMMPdpMsgSender(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
                                pcmmSender.sendGateDelete(gateReq);
                        } catch (COPSPdpException e) {
                                logger.error("CcapClient: sendGateDelete(): {}:{} => {} FAILED: {}", ipv4, port, gateReq, e.getMessage());
index dfe737d8b25a1d9e6f1ef567dca9c461e96623b2..2350e7502ebe4a3802a2d405654355ef0cf6a15f 100644 (file)
@@ -92,6 +92,7 @@ public class PacketcableProvider implements DataChangeListener, AutoCloseable {
             final AsyncReadWriteTransaction<InstanceIdentifier<?>, ?> tx = dataBroker.newReadWriteTransaction();
             tx.delete(LogicalDatastoreType.CONFIGURATION, ccapIID);
             tx.delete(LogicalDatastoreType.CONFIGURATION, qosIID);
+            // TODO - commit() below has been deprecated
             tx.commit().get();
         }
     }
@@ -287,6 +288,7 @@ public class PacketcableProvider implements DataChangeListener, AutoCloseable {
             logger.info("onDataChanged().getCcaps(): " + thisData);
             for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
                 if (entry.getValue() instanceof Ccaps) {
+                    // TODO FIXME - Potential ClassCastException thrown here!!!
                     ccapIidMap.put((InstanceIdentifier<Ccaps>)entry.getKey(), (Ccaps)entry.getValue());
                 }
             }
@@ -297,6 +299,8 @@ public class PacketcableProvider implements DataChangeListener, AutoCloseable {
             for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
                 if (entry.getValue() instanceof Gates) {
                     final Gates gate = (Gates)entry.getValue();
+
+                    // TODO FIXME - Potential ClassCastException thrown here!!!
                     final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
                     getGatePathMap(gateIID);
                     gateIidMap.put(gateIID, gate);
@@ -356,6 +360,7 @@ public class PacketcableProvider implements DataChangeListener, AutoCloseable {
                         logger.info("onDataChanged(): created CCAP: {}/{} : {}", thisData.gatePath, thisCcap, message);
                         logger.info("onDataChanged(): created CCAP: {} : {}", thisData.gatePath, message);
                     } else {
+                        // TODO - when a connection cannot be made, need to remove CCAP from ODL cache.
                         logger.error("onDataChanged(): create CCAP Failed: {} : {}", thisData.gatePath, message);
                     }
                     // set the response string in the config ccap object using a new thread
@@ -442,7 +447,7 @@ public class PacketcableProvider implements DataChangeListener, AutoCloseable {
                 final Ccaps thisCcap = ccapMap.get(ccapId);
                 final PCMMService service = pcmmServiceMap.get(thisCcap);
                 if (service != null) {
-                    service.sendGateDelete(thisCcap, gatePathStr);
+                    service.sendGateDelete(gatePathStr);
                     logger.info("onDataChanged(): removed QoS gate {} for {}/{}/{}: ", gateId, ccapId, gatePathStr, thisGate);
                     logger.info("onDataChanged(): removed QoS gate {} for {}/{}: ", gateId, ccapId, gatePathStr);
                 } else
index caf94f85a658f715e81dea7a2cd49f8a79d8c9fd..73de401e0ce543239e9679fd6d22c4bb0041babf 100644 (file)
@@ -10,6 +10,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceClassName;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ServiceFlowDirection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TosByte;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.TpProtocol;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
@@ -17,49 +19,53 @@ import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifie
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gate.spec.GateSpec;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
 import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.pcmm.gates.IPCMMGate;
 import org.pcmm.rcd.IPCMMClient;
 import org.pcmm.rcd.impl.CMTS;
+import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSContext.RType;
+import org.umu.cops.stack.COPSDecision.Command;
+import org.umu.cops.stack.COPSDecision.DecisionFlag;
+import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.InetAddress;
+import java.net.Socket;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Tests the PCMMService's ability to connect to a CMTS. Gate additions will not properly work as there is currently
  * not any other means to receive acknowledgements. This functionality must be tested by the PCMMService's client
- * PacketcableProvider
+ * PacketcableProvider.
  */
 public class PCMMServiceTest {
 
-    private Ccaps ccap;
+    /**
+     * The mock CMTS running on localhost with a dynamic port assigned.
+     */
     private CMTS icmts;
 
+    /**
+     * Represents the IP address of the CM the gate should be set against.
+     */
+    private byte[] cmAddr = new byte[4];
+
     @Before
     public void setup() {
         icmts = new CMTS();
         icmts.startServer();
 
-        ccap = Mockito.mock(Ccaps.class);
-        final Connection conn = Mockito.mock(Connection.class);
-        Mockito.when(ccap.getConnection()).thenReturn(conn);
-        final PortNumber port = Mockito.mock(PortNumber.class);
-        Mockito.when(conn.getPort()).thenReturn(port);
-        Mockito.when(port.getValue()).thenReturn(icmts.getPort());
-        final IpAddress addr = Mockito.mock(IpAddress.class);
-        Mockito.when(conn.getIpAddress()).thenReturn(addr);
-        final Ipv4Address ipv4 = Mockito.mock(Ipv4Address.class);
-        Mockito.when(addr.getIpv4Address()).thenReturn(ipv4);
-
-        // Switch the value to a real CMTS here to test against it
-        // Ensure the code is checked in with 127.0.0.1
-        Mockito.when(ipv4.getValue()).thenReturn("127.0.0.1");
-
-        // Following line has been commented out for testing against a real Arris CMTS in the Louisville development lab
-//                Mockito.when(ipv4.getValue()).thenReturn("10.32.10.3");
-
-        Mockito.when(ccap.getCcapId()).thenReturn("ccap-1");
-        final AmId amid = Mockito.mock(AmId.class);
-        Mockito.when(ccap.getAmId()).thenReturn(amid);
-        Mockito.when(amid.getAmTag()).thenReturn(0xcada);
-        Mockito.when(amid.getAmType()).thenReturn(1);
+        cmAddr[0] = 10;
+        cmAddr[1] = 32;
+        cmAddr[2] = 110;
+        cmAddr[3] = (byte)180;
     }
 
     @After
@@ -69,55 +75,207 @@ public class PCMMServiceTest {
 
     @Test
     public void testAddCcap() {
+
+        // TODO - comment out for testing
+        //        final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
+//        final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
+
+        // TODO - Use this instead for automated testing
+        final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+        final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
+
         final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
         final String message = service.addCcap();
-        Assert.assertTrue(message.startsWith("200"));
+        Assert.assertNotNull(message);
+        Assert.assertTrue(message, message.startsWith("200"));
         Assert.assertNotNull(service.ccapClient.pcmmPdp.getClientHandle());
-
-        // TODO - remove this sleep
-/*
-        try {
-            Thread.sleep(100000);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
-        }
-*/
+        service.disconect();
     }
 
-//    @Test
-    public void testAddGate() throws Exception {
+    @Test
+    public void testAddAndRemoveUpGate() throws Exception {
+
+        // TODO - Use this block to test against a real CMTS
+//        final Ipv4Address cmtsAddr = new Ipv4Address("10.32.10.3");
+//        final Ccaps ccap = makeCcapsObj(PCMMPdpAgent.WELL_KNOWN_PDP_PORT, cmtsAddr.getValue(), "ccap-1");
+
+        // TODO - Use this block for automated testing
+        final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+        final Ccaps ccap = makeCcapsObj(icmts.getPort(), cmtsAddr.getValue(), "ccap-1");
+
         final PCMMService service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap);
         service.addCcap();
-        final byte[] addr = new byte[4];
-        addr[0] = 10;
-        addr[1] = 32;
-        addr[2] = 110;
-        addr[3] = (byte)180;
 
+        final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
+        final String gatePath = "testGatePath";
+
+        // Add gate
+        final String msg = service.sendGateSet(gatePath, InetAddress.getByAddress(cmAddr), gate,
+                ServiceFlowDirection.Us);
+        Assert.assertTrue(msg, msg.startsWith("200"));
+
+        // TODO - add validation to the PCMMGateReq contained within the map
+        Assert.assertEquals(1, service.gateRequests.size());
+
+        // Remove gate
+        service.sendGateDelete(gatePath);
+
+        // Wait up to 1 sec for response to be processed
+        final long start = System.currentTimeMillis();
+        while (1000 < System.currentTimeMillis() - start) {
+            if (service.gateRequests.size() == 0) break;
+        }
+        Assert.assertEquals(0, service.gateRequests.size());
+        service.disconect();
+    }
+
+    /**
+     * This tests the instantiation of a COPSDecisionMsg object that is responsible for setting a gate request,
+     * streams it over a mock Socket object and parses the bytes into a new COPSDecisionMsg object which should
+     * be equivalent
+     * @throws Exception - test will fail should any exception be thrown during execution
+     */
+    @Test
+    public void testGateRequestDecisionMsg() throws Exception {
+        final Socket socket = new MockSocket();
+        final Ccaps ccap = makeCcapsObj(icmts.getPort(), "127.0.0.1", "ccap-1");
+        final Ipv4Address cmtsAddr = new Ipv4Address("127.0.0.1");
+        final Gates gate = makeGateObj("extrm_up", cmtsAddr, ServiceFlowDirection.Us);
+        final IPCMMGate gateReq = makeGateRequest(ccap, gate, InetAddress.getByName("localhost"),
+                ServiceFlowDirection.Us);
+        final byte[] data = gateReq.getData();
+
+        final Set<COPSDecision> decisionSet = new HashSet<>();
+        decisionSet.add(new COPSDecision(CType.DEF, Command.INSTALL, DecisionFlag.REQERROR));
+        final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
+        decisionMap.put(new COPSContext(RType.CONFIG, (short) 0), decisionSet);
+
+        final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
+        final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData("123")),
+                decisionMap, null, clientSD);
+        decisionMsg.writeData(socket);
+
+        final COPSMsg msg = COPSMsgParser.parseMessage(socket);
+        Assert.assertNotNull(msg);
+        Assert.assertEquals(decisionMsg, msg);
+    }
+
+    /**
+     * Creates a mock Ccaps object that can be used for connecting to a CMTS
+     * @param inPort - the CMTS port number
+     * @param ipAddr - the CMTS IPv4 address string
+     * @param ccapId - the ID of the CCAP
+     * @return - the mock Ccaps object
+     */
+    private Ccaps makeCcapsObj(final int inPort, final String ipAddr, final String ccapId) {
+        final Ccaps ccap = Mockito.mock(Ccaps.class);
+        final Connection conn = Mockito.mock(Connection.class);
+        Mockito.when(ccap.getConnection()).thenReturn(conn);
+        final PortNumber port = Mockito.mock(PortNumber.class);
+        Mockito.when(conn.getPort()).thenReturn(port);
+        Mockito.when(port.getValue()).thenReturn(inPort);
+
+        final IpAddress addr = Mockito.mock(IpAddress.class);
+        Mockito.when(conn.getIpAddress()).thenReturn(addr);
+        final Ipv4Address ipv4 = new Ipv4Address(ipAddr);
+        Mockito.when(addr.getIpv4Address()).thenReturn(ipv4);
+
+        Mockito.when(ccap.getCcapId()).thenReturn(ccapId);
+        final AmId amid = Mockito.mock(AmId.class);
+        Mockito.when(ccap.getAmId()).thenReturn(amid);
+        Mockito.when(amid.getAmTag()).thenReturn(0xcada);
+        Mockito.when(amid.getAmType()).thenReturn(1);
+
+        return ccap;
+    }
+
+    /**
+     * Creates a mock Gates object
+     * @param scnValue - the service class name defined on the CMTS
+     * @param dstAddr - the CM address this gate should be set against
+     * @return - the gate request
+     */
+    private Gates makeGateObj(final String scnValue, final Ipv4Address dstAddr, final ServiceFlowDirection direction) {
         final Gates gate = Mockito.mock(Gates.class);
         final GateSpec gateSpec = Mockito.mock(GateSpec.class);
         Mockito.when(gate.getGateSpec()).thenReturn(gateSpec);
-        Mockito.when(gateSpec.getDirection()).thenReturn(ServiceFlowDirection.Us);
+        Mockito.when(gateSpec.getDirection()).thenReturn(direction);
         // TODO - make sure to write a test when this value is not null
         Mockito.when(gateSpec.getDscpTosOverwrite()).thenReturn(null);
         final TrafficProfile trafficProfile = Mockito.mock(TrafficProfile.class);
         final ServiceClassName scn = Mockito.mock(ServiceClassName.class);
-        Mockito.when(scn.getValue()).thenReturn("extrm_up");
+        Mockito.when(scn.getValue()).thenReturn(scnValue);
         Mockito.when(trafficProfile.getServiceClassName()).thenReturn(scn);
         Mockito.when(gate.getTrafficProfile()).thenReturn(trafficProfile);
 
         // TODO - write tests when this is null and ExtClassifier or Ipv6Classifier objects are not null
         final Classifier classifier = Mockito.mock(Classifier.class);
+
+        // This is the address of the CM
+        Mockito.when(classifier.getDstIp()).thenReturn(dstAddr);
+
+        final PortNumber dstPort = new PortNumber(4321);
+        Mockito.when(classifier.getDstPort()).thenReturn(dstPort);
+        final TpProtocol protocol = new TpProtocol(0);
+        Mockito.when(classifier.getProtocol()).thenReturn(protocol);
+        final Ipv4Address srcAddr = new Ipv4Address("127.0.0.1");
+        Mockito.when(classifier.getSrcIp()).thenReturn(srcAddr);
+        final PortNumber srcPort = new PortNumber(1234);
+        Mockito.when(classifier.getSrcPort()).thenReturn(srcPort);
+        final TosByte tosByte = new TosByte((short)160);
+        Mockito.when(classifier.getTosByte()).thenReturn(tosByte);
+        final TosByte tosMask = new TosByte((short)224);
+        Mockito.when(classifier.getTosMask()).thenReturn(tosMask);
+
+        // TODO - enhance to test support of the other classifier types
         Mockito.when(gate.getClassifier()).thenReturn(classifier);
         Mockito.when(gate.getExtClassifier()).thenReturn(null);
         Mockito.when(gate.getIpv6Classifier()).thenReturn(null);
+        return gate;
+    }
 
-        // TODO - remove this sleep
-        Thread.sleep(1000);
+    private IPCMMGate makeGateRequest(final Ccaps ccap, final Gates gateReq, final InetAddress addrSubId,
+                                     final ServiceFlowDirection direction) {
+        final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
+        gateBuilder.build(ccap.getAmId());
+        gateBuilder.build(addrSubId);
+        // force gateSpec.Direction to align with SCN direction
+        final ServiceClassName scn = gateReq.getTrafficProfile().getServiceClassName();
+        if (scn != null) {
+            gateBuilder.build(gateReq.getGateSpec(), direction);
+        } else {
+            // not an SCN gate
+            gateBuilder.build(gateReq.getGateSpec(), null);
+        }
+        gateBuilder.build(gateReq.getTrafficProfile());
 
-        final String msg = service.sendGateSet("app1/10.32.110.180/gate2", InetAddress.getByAddress(addr), gate,
-                ServiceFlowDirection.Us);
-        Assert.fail(msg);
+        // pick a classifier type (only one for now)
+        if (gateReq.getClassifier() != null) {
+            gateBuilder.build(gateReq.getClassifier());
+        } else if (gateReq.getExtClassifier() != null) {
+            gateBuilder.build(gateReq.getExtClassifier());
+        } else if (gateReq.getIpv6Classifier() != null) {
+            gateBuilder.build(gateReq.getIpv6Classifier());
+        }
+        // assemble the final gate request
+        return gateBuilder.getGateReq();
+    }
+
+    private class MockSocket extends Socket {
+
+        private ByteArrayOutputStream os = new ByteArrayOutputStream();
+        private ByteArrayInputStream is;
+
+        @Override
+        public OutputStream getOutputStream() {
+            return os;
+        }
+
+        @Override
+        public InputStream getInputStream() {
+            if (is == null) is = new ByteArrayInputStream(os.toByteArray());
+            return is;
+        }
     }
 
 }