--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>packetcable</artifactId>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <!--
+ Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+ maven repos etc. If you run this archetype in a subdirectory of your project, it
+ will pick the pom.xml from the parent directory as the parent pom, which may or may
+ not be correct.
+ -->
+ <artifactId>features-packetcable-policy</artifactId>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <!-- Optional Uncomment version if you are not using a parent pom.xml
+ <version>1.2.0-SNAPSHOT</version>
+ -->
+ <packaging>jar</packaging>
+ <properties>
+ <features.file>features.xml</features.file>
+ <!-- Optional: Move these properties to your parent pom and possibly
+ DependencyManagement section of your parent pom -->
+ <branding.version>1.1.0-SNAPSHOT</branding.version>
+ <karaf.resources.version>1.5.0-SNAPSHOT</karaf.resources.version>
+ <karaf.empty.version>1.5.0-SNAPSHOT</karaf.empty.version>
+ <surefire.version>2.16</surefire.version>
+ </properties>
+ <dependencies>
+ <!--
+ Necessary: Put dependencies on any feature repos
+ you use in your features.xml file.
+
+ Note: they will need to be <type>xml</xml>
+ and <classifier>features</classifier>.
+ One other thing to watch for is to make sure they are
+ <scope>compile</compile>, which they should be by default,
+ but be cautious lest they be at a different scope in a parent pom.
+
+ Examples:
+ -->
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>features-yangtools</artifactId>
+ <version>0.7.0-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>packetcable-policy-config</artifactId>
+ <version>${project.version}</version>
+ <classifier>config</classifier>
+ <type>xml</type>
+ </dependency>
+
+
+
+
+ <!--
+ Necessary TODO: Put dependencies for bundles directly referenced
+ in your features.xml file. For every <bundle> reference in your
+ features.xml file, you need a corresponding dependency here.
+
+ Examples:
+ -->
+ <dependency>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>packetcable-policy-server</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>packetcable-policy-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>packetcable-driver</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- test to validate features.xml -->
+ <dependency>
+ <groupId>org.opendaylight.odlparent</groupId>
+ <artifactId>features-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!-- dependency for opendaylight-karaf-empty for use by testing -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-empty</artifactId>
+ <version>${karaf.empty.version}</version>
+ <type>zip</type>
+ </dependency>
+ <!-- Uncomment this if you get an error : java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.format(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.7.2</version>
+ </dependency>
+ -->
+
+ </dependencies>
+ <build>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>filter</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>resources</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${features.file}</file>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>${surefire.version}</version>
+ <configuration>
+ <systemPropertyVariables>
+ <karaf.distro.groupId>org.opendaylight.controller</karaf.distro.groupId>
+ <karaf.distro.artifactId>opendaylight-karaf-empty</karaf.distro.artifactId>
+ <karaf.distro.version>${karaf.empty.version}</karaf.distro.version>
+ </systemPropertyVariables>
+ <dependenciesToScan>
+ <dependency>org.opendaylight.odlparent:features-test</dependency>
+ </dependenciesToScan>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=packetcable.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<features name="odl-packetcable-${project.version}" xmlns="http://karaf.apache.org/xmlns/features/v1.2.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://karaf.apache.org/xmlns/features/v1.2.0 http://karaf.apache.org/xmlns/features/v1.2.0">
+ <!--
+ Please read the features guidelines:
+ https://wiki.opendaylight.org/view/Runtime:Karaf_Features_Guidelines#Feature_Best_Practices
+ -->
+ <!--
+ Add repo entries for the repositories of features you refer to in this feature file but do not define here.
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/0.1.0-SNAPSHOT/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-adsal/${feature.adsal.version}/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-adsal-compatibility/1.5.0-SNAPSHOT/xml/features</repository>
+ -->
+ <repository>mvn:org.opendaylight.yangtools/features-yangtools/0.7.0-SNAPSHOT/xml/features</repository>
+ <repository>mvn:org.opendaylight.controller/features-mdsal/1.2.0-SNAPSHOT/xml/features</repository>
+ <repository>mvn:org.opendaylight.openflowplugin/features-openflowplugin/${openflowplugin.version}/xml/features</repository>
+
+ <feature name='odl-packetcable-policy-server-all' version='${project.version}' description='OpenDaylight :: packetcable :: policy :: All'>
+ <feature version='${project.version}'>odl-packetcable-policy-server</feature>
+ <feature version='${project.version}'>odl-packetcable-policy-model</feature>
+ <feature version='${project.version}'>odl-packetcable-driver</feature>
+ </feature>
+
+ <!--
+ Define your features. It is useful to list then in order of dependency. So if A depends on B, list A first.
+ It's also nice to list inside a feature, first the features it needs, then the bundles it needs, then the configfiles.
+ <feature version='0.1.0-SNAPSHOT'>odl-openflowplugin-flow-services</feature>
+ <bundle>mvn:com.google.common.collect/collect/14.0</bundle>
+
+ -->
+ <!--- * Basic MD-SAL Consumer -->
+ <!--- * Basic MD-SAL Model feature -->
+ <feature name='odl-packetcable-policy-model' version='${project.version}' description='OpenDaylight :: packetcable :: policy :: Model'>
+ <feature version='0.7.0-SNAPSHOT'>odl-yangtools-binding</feature>
+ <feature version='0.7.0-SNAPSHOT'>odl-yangtools-models</feature>
+ <bundle>mvn:org.opendaylight.packetcable/packetcable-policy-model/${project.version}</bundle>
+ </feature>
+
+ <!--- * Basic MD-SAL Provider -->
+ <feature name='odl-packetcable-policy-server' version='${project.version}' description='OpenDaylight :: packetcable :: policy :: Provider'>
+ <feature version='1.2.0-SNAPSHOT'>odl-mdsal-broker</feature>
+ <bundle>mvn:org.opendaylight.packetcable/packetcable-policy-server/${project.version}</bundle>
+ <bundle>mvn:org.opendaylight.packetcable/packetcable-driver/${project.version}</bundle>
+ <feature version='${project.version}'>odl-packetcable-policy-model</feature>
+ <feature version='${project.version}'>odl-packetcable-driver</feature>
+ <configfile finalname="etc/opendaylight/karaf/80-packetcable.xml">mvn:org.opendaylight.packetcable/packetcable-policy-config/${project.version}/xml/config</configfile>
+ </feature>
+
+ <!--- * * -->
+ <feature name='odl-packetcable-driver' version='${project.version}' description='OpenDaylight :: packetcable :: Driver'>
+ <feature version='1.2.0-SNAPSHOT'>odl-mdsal-broker</feature>
+ </feature>
+
+</features>
package org.pcmm;
+import org.pcmm.gates.IPCMMGate;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * TODO - Remove all uses of this class which is evil as it contains environmental settings
+ */
public class PCMMGlobalConfig {
// System
public static int Debug = 0;
public static int getGateID2() {
return GateID2;
}
+
+ /**
+ * Global TransactionId to Gate Request map allows recovery of CCAP GateIds
+ * TODO - need to find a better means to store shared state.
+ */
+
+ public static Map<Short, IPCMMGate> transactionGateMap = new ConcurrentHashMap<>();
}
/*
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
/**
* Core PDP agent for provisioning
*/
public class PCMMPdpAgent extends COPSPdpAgent {
- public final static Logger logger = LoggerFactory.getLogger(PCMMPdpAgent.class);
+ private static final Logger logger = LoggerFactory.getLogger(PCMMPdpAgent.class);
/** Well-known port for PCMM */
public static final int WELL_KNOWN_PDP_PORT = 3918;
- private COPSPepId _pepId;
- private String _pepIdString;
/**
* PEP host name
*/
- private String psHost;
+ private final String psHost;
/**
* PEP port
*/
- private int psPort;
-
- private Socket socket;
+ private final int psPort;
/**
* Policy data processing object
*/
- private PCMMPdpDataProcess _process;
- private COPSHandle _handle;
-// private short _transactionID;
+ private final PCMMPdpDataProcess _process;
+ // Next two attributes are initialized when connected
/**
- * Temporary until can refactor PdpAgent classes
- */
- @Deprecated
- private final Map<String, PCMMPdpConnection> _connectionMap;
-
- /**
- * Creates a PDP Agent
- *
- * @param clientType
- * COPS Client-type
- * @param process
- * Object to perform policy data processing
+ * The Socket connection to the PEP
*/
- public PCMMPdpAgent(short clientType, PCMMPdpDataProcess process) {
- this(clientType, null, WELL_KNOWN_PDP_PORT, process);
- }
+ private transient Socket socket;
+ private transient COPSHandle _handle;
/**
* Creates a PDP Agent
*
- * @param clientType
- * COPS Client-type
- * @param psHost
- * Host to connect to
- * @param psPort
- * Port to connect to
- * @param process
- * Object to perform policy data processing
+ * @param clientType - COPS Client-type
+ * @param psHost - Host to connect to
+ * @param psPort - Port to connect to
+ * @param process - Object to perform policy data processing
*/
- public PCMMPdpAgent(short clientType, String psHost, int psPort, PCMMPdpDataProcess process) {
+ public PCMMPdpAgent(final short clientType, final String psHost, final int psPort,
+ final PCMMPdpDataProcess process) {
super(psPort, clientType, null);
this._process = process;
this.psHost = psHost;
- this._connectionMap = new ConcurrentHashMap<>();
+ this.psPort = psPort;
}
/**
/**
* Connects to a PDP
*
- * @param psHost
- * CMTS host name
- * @param psPort
- * CMTS port
* @return <tt>true</tt> if PDP accepts the connection; <tt>false</tt>
* otherwise
* @throws java.net.UnknownHostException
* @throws java.io.IOException
* @throws COPSException
- * @throws COPSPdpException
*/
- public boolean connect(String psHost, int psPort) throws IOException, COPSException, COPSPdpException {
-
- this.psHost = psHost;
- this.psPort = psPort;
+ public boolean connect() throws IOException, COPSException {
// Create Socket and send OPN
- InetAddress addr = InetAddress.getByName(psHost);
- try {
- socket = new Socket(addr, psPort);
- } catch (IOException e) {
- logger.error("Error creating socket connection", e);
- return (false);
- }
- logger.info("PDP Socket Opened");
- // Loop through for Incoming messages
+ final InetAddress addr = InetAddress.getByName(psHost);
+ socket = new Socket(addr, psPort);
+ logger.debug("{} {}", getClass().getName(), "PDP Socket Opened");
- // server infinite loop
- // while(true)
- {
-
- // We're waiting for an message
- try {
- logger.info("PDP COPSTransceiver.receiveMsg");
- COPSMsg msg = COPSTransceiver.receiveMsg(socket);
- if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
- logger.info("PDP msg.getHeader().isAClientOpen");
- handleClientOpenMsg(socket, msg);
- } else {
- try {
- socket.close();
- } catch (Exception ex) {
- logger.error("Unexpected exception closing socket", ex);
- }
- }
- } catch (Exception e) { // COPSException, IOException
+ // We're waiting for an message
+ try {
+ logger.debug("Waiting to receiveMsg");
+ final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+ logger.debug("Message received of type - " + msg.getHeader().getOpCode());
+ if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
+ handleClientOpenMsg(socket, msg);
+ } else {
try {
socket.close();
} catch (Exception ex) {
- logger.error("Unexpected exception closing socket", ex);
+ logger.error("Unexpected error closing socket", ex);
}
- return true;
}
+ } catch (Exception e) {
+ logger.error("Unexpected error handing client open message", e);
+ try {
+ socket.close();
+ } catch (Exception ex) {
+ logger.error("Unexpected error closing socket", ex);
+ }
+ return true;
}
+
return false;
}
- /**
- * Handles a COPS client-open message
- *
- * @param conn
- * Socket to the PEP
- * @param msg
- * <tt>COPSMsg</tt> holding the client-open message
- * @throws COPSException
- * @throws IOException
- */
- private void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+ // TODO - remove and let super handle after DataProcess & PdpConnection classes are properly refactored
+ @Override
+ public void disconnect (final String pepID, final COPSError error) throws COPSException, IOException {
+ final PCMMPdpConnection pdpConn = (PCMMPdpConnection) _connectionMap.get(pepID);
+ if (pdpConn != null) {
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(), error, null, null);
+ closeMsg.writeData(pdpConn.getSocket());
+ pdpConn.close();
+ }
+
+ final Thread thread = threadMap.remove(pepID);
+ if (thread != null) thread.interrupt();
+ }
+
+ // TODO - this method should be broken apart into smaller pieces.
+ @Override
+ protected void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+ logger.info("Processing client open message");
final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
- final COPSPepId pepId = cMsg.getPepId();
+ _pepId = cMsg.getPepId();
// Validate Client Type
if (msg.getHeader().getClientType() != getClientType()) {
// Unsupported client type
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Unexpected error writing COPS data", unae);
+ logger.error("Unexpected error writing data", unae);
}
throw new COPSException("Unsupported client type");
}
// PEPId is mandatory
- if (pepId == null) {
+ if (_pepId == null) {
// Mandatory COPS object missing
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Unexpected error writing COPS data", unae);
+ logger.error("Unexpected error closing socket", unae);
}
throw new COPSException("Mandatory COPS object missing (PEPId)");
}
- setPepId(pepId);
+
// Support
if ((cMsg.getClientSI() != null) ) {
final MMVersionInfo _mminfo = new MMVersionInfo(cMsg.getClientSI().getData().getData());
- logger.info("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + " minor:" +
+ logger.debug("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + " minor:" +
_mminfo.getMinorVersionNB());
} else {
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ // Unsupported objects
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Unexpected error writing COPS data", unae);
+ logger.error("Unexpected error writing data", unae);
}
throw new COPSException("Unsupported objects (PdpAddress, Integrity)");
*/
// Connection accepted
- final COPSKATimer katimer = new COPSKATimer(getKaTimer());
- final COPSAcctTimer acctTimer = new COPSAcctTimer(getAcctTimer());
final COPSClientAcceptMsg acceptMsg;
if (getAcctTimer() != 0)
- acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, acctTimer, null);
+ acceptMsg = new COPSClientAcceptMsg(getClientType(), new COPSKATimer(getKaTimer()),
+ new COPSAcctTimer(getAcctTimer()), null);
else
- acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
-
+ acceptMsg = new COPSClientAcceptMsg(getClientType(), new COPSKATimer(getKaTimer()), null, null);
acceptMsg.writeData(conn);
// XXX - handleRequestMsg
try {
- logger.info("PDP COPSTransceiver.receiveMsg");
- COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
+ logger.debug("handleClientOpenMsg() - Waiting to receive message");
+ final COPSMsg rmsg = COPSTransceiver.receiveMsg(socket);
+ logger.debug("Received message of type - " + rmsg.getHeader().getOpCode());
// Client-Close
if (rmsg.getHeader().getOpCode().equals(OPCode.CC)) {
- logger.info("Client close description - " + ((COPSClientCloseMsg) rmsg).getError().getDescription());
+ System.out.println(((COPSClientCloseMsg) rmsg)
+ .getError().getDescription());
// close the socket
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(getClientType(),
new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Unexpected exception writing COPS data", unae);
+ logger.error("Unexpected error writing data", unae);
}
throw new COPSException("CMTS requetsed Client-Close");
} else {
_handle = rMsg.getClientHandle();
} else
throw new COPSException("Can't understand request");
-
}
} catch (Exception e) { // COPSException, IOException
- throw new COPSException("Error COPSTransceiver.receiveMsg");
+ throw new COPSException("Error COPSTransceiver.receiveMsg", e);
}
- logger.info("PDPCOPSConnection");
- PCMMPdpConnection pdpConn = new PCMMPdpConnection(pepId, conn, _process);
- pdpConn.setKaTimer(getKaTimer());
- if (getAcctTimer() != 0)
- pdpConn.setAccTimer(getAcctTimer());
+ logger.debug("PDPCOPSConnection");
+ final PCMMPdpConnection pdpConn = new PCMMPdpConnection(_pepId, conn, _process, getKaTimer(), getAcctTimer());
// XXX - handleRequestMsg
// XXX - check handle is valid
- PCMMPdpReqStateMan man = new PCMMPdpReqStateMan(getClientType(), _handle.getId().str());
- pdpConn.getReqStateMans().put(_handle.getId().str(),man);
- man.setDataProcess(_process);
+ final PCMMPdpReqStateMan man = new PCMMPdpReqStateMan(getClientType(), _handle, _process);
+ pdpConn.addStateMan(_handle.getId().str(), man);
try {
man.initRequestState(conn);
} catch (COPSPdpException unae) {
- logger.error("Error initializing the state manager's request state");
+ logger.error("Unexpected error initializing state", unae);
}
// XXX - End handleRequestMsg
- logger.info("PDP Thread(pdpConn).start");
- new Thread(pdpConn).start();
- _connectionMap.put(pepId.getData().str(), pdpConn);
- }
-
- /**
- * @return the _psHost
- */
- public String getPsHost() {
- return psHost;
- }
-
- /**
- * TODO - make the host immutable
- * @param _psHost
- * the _psHost to set
- */
- @Deprecated
- public void setPsHost(String _psHost) {
- this.psHost = _psHost;
- }
+ logger.info("Starting PDP connection thread to - " + psHost);
- /**
- * @return the _psPort
- */
- public int getPsPort() {
- return psPort;
+ // TODO - store the thread reference so it is possible to manage.
+ final Thread thread = new Thread(pdpConn, "Agent for - " + psHost);
+ thread.start();
+ threadMap.put(_pepId.getData().str(), thread);
+ _connectionMap.put(_pepId.getData().str(), pdpConn);
}
- /**
- * TODO - make the port immutable
- * @param _psPort
- * the _psPort to set
- */
- @Deprecated
- public void setPsPort(int _psPort) {
- this.psPort = _psPort;
- }
-
- /**
- * @return the socket
- */
public Socket getSocket() {
return socket;
}
- /**
- * TODO - Ensure socket is not overly transient
- * @param socket
- * the socket to set
- */
- @Deprecated
- public void setSocket(Socket socket) {
- this.socket = socket;
- }
-
- /**
- * @return the _process
- */
- public PCMMPdpDataProcess getProcess() {
- return _process;
- }
-
- /**
- * @param _process
- * the _process to set
- */
- public void setProcess(PCMMPdpDataProcess _process) {
- this._process = _process;
- }
-
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
public COPSHandle getClientHandle() {
return _handle;
}
- /**
- * Gets the PepId
- * @return <tt>COPSPepId</tt>
- */
- public COPSPepId getPepId() {
- return _pepId;
- }
-
public String getPepIdString() {
- return _pepIdString;
+ return _pepId.getData().str();
}
- /**
- * Sets the PepId
- * TODO - make PEP ID and the associate string immutable or remove altogether
- * @param pepId - COPSPepId
- */
- @Deprecated
- public void setPepId(COPSPepId pepId) {
- _pepId = pepId;
- _pepIdString = pepId.getData().str();
- }
- /*
- * (non-Javadoc)
- *
- * @see org.pcmm.rcd.IPCMMClient#isConnected()
- */
- public boolean isConnected() {
- return socket != null && socket.isConnected();
- }
-
-
}
+
import org.slf4j.LoggerFactory;
import org.umu.cops.prpdp.COPSPdpException;
import org.umu.cops.stack.*;
-import org.umu.cops.stack.COPSHeader.OPCode;
+import javax.annotation.concurrent.ThreadSafe;
import java.io.IOException;
import java.net.Socket;
import java.util.Date;
-import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
- * Class for managing an provisioning connection at the PDP side.
+ * Class for managing an provisioning connection at the PDP side for receiving and brokering out COPS messages.
*/
+@ThreadSafe
public class PCMMPdpConnection implements Runnable {
-
- public final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
+ private final static Logger logger = LoggerFactory.getLogger(PCMMPdpConnection.class);
/**
Socket connected to PEP
*/
- private Socket _sock;
+ private final Socket _sock;
/**
- PEP identifier
- */
- private COPSPepId _pepId;
+ * PEP identifier
+ * TODO - Determine why the original author put this object into this class
+ */
+ private final COPSPepId _pepId;
/**
- * Time of the latest keep-alive received
+ * Time of the latest keep-alive received
*/
protected Date _lastRecKa;
/**
- Maps a Client Handle to a Handler
+ * Maps a Client Handle to a Handler
*/
- protected Map<String, PCMMPdpReqStateMan> _managerMap;
+ protected final Map<String, PCMMPdpReqStateMan> _managerMap;
/**
* PDP policy data processor class
*/
- protected PCMMPdpDataProcess _process;
+ protected final PCMMPdpDataProcess _process;
/**
- Accounting timer value (secs)
+ * Accounting timer value (secs)
*/
- protected short _acctTimer;
+ protected final short _acctTimer;
/**
- Keep-alive timer value (secs)
+ * Keep-alive timer value (secs)
*/
- protected short _kaTimer;
+ protected final short _kaTimer;
/**
- COPS error returned by PEP
+ * COPS error returned by PEP on close
*/
- protected COPSError _error;
+ protected transient COPSError _error;
/**
* Creates a new PDP connection
* @param sock Socket connected to PEP
* @param process Object for processing policy data
*/
- public PCMMPdpConnection(COPSPepId pepId, Socket sock, PCMMPdpDataProcess process) {
- _sock = sock;
+ public PCMMPdpConnection(final COPSPepId pepId, final Socket sock, final PCMMPdpDataProcess process,
+ final short kaTimer, final short acctTimer) {
_pepId = pepId;
- _managerMap = new ConcurrentHashMap<>();
- _kaTimer = 120;
+ _sock = sock;
_process = process;
- }
-
- /**
- * Sets the keep-alive timer value
- * @param kaTimer Keep-alive timer value (secs)
- */
- public void setKaTimer(final short kaTimer) {
_kaTimer = kaTimer;
- }
-
- /**
- * Sets the accounting timer value
- * @param acctTimer Accounting timer value (secs)
- */
- public void setAccTimer(final short acctTimer) {
_acctTimer = acctTimer;
+ _managerMap = new ConcurrentHashMap<>();
}
- /**
- * Gets the accounting timer value
- * @return Accounting timer value (secs)
- */
- public short getAcctTimer() {
- return _acctTimer;
- }
-
- /**
- * Gets the handle map
- * @return A <tt>Hashtable</tt> holding the handle map
- */
- public Map<String, PCMMPdpReqStateMan> getReqStateMans() {
- // Defensive copy
- return new HashMap<>(_managerMap);
+ public void addStateMan(final String key, final PCMMPdpReqStateMan man) {
+ _managerMap.put(key, man);
}
/**
* Closes the socket to the PEP
* @throws IOException
*/
- protected void close()
- throws IOException {
- _sock.close();
+ protected void close() throws IOException {
+ if (!_sock.isClosed()) _sock.close();
}
/**
* Main loop
*/
public void run () {
+ logger.info("Starting socket listener.");
Date _lastSendKa = new Date();
_lastRecKa = new Date();
- try {
- while (!_sock.isClosed()) {
+
+ // Loop while socket is open
+ while (!_sock.isClosed()) {
+ try {
if (_sock.getInputStream().available() != 0) {
+ logger.info("Waiting to process socket messages");
processMessage(_sock);
+ logger.info("Message processed");
_lastRecKa = new Date();
}
cTime = (int) (new Date().getTime());
if ((cTime - _startTime) > ((_kaTimer*3/4)*1000)) {
- // TODO - determine what is the client type to be used here?
final COPSKAMsg msg = new COPSKAMsg(null);
+ logger.info("Sending KA message to CCAP");
COPSTransceiver.sendMsg(msg, _sock);
+ logger.info("Sent KA message gto CCAP");
_lastSendKa = new Date();
}
}
try {
Thread.sleep(500);
- } catch (Exception e) {
- logger.error("Unexpected exception while sleeping", e);
+ } catch (InterruptedException e) {
+ logger.info("Shutting down socket connection to CCAP");
+ break;
}
-
+ } catch (IOException e) {
+ logger.error("Exception reading from socket - exiting", e);
+ break;
+ } catch (COPSException e) {
+ logger.error("Exception processing message - continue processing", e);
}
- } catch (Exception e) {
- logger.error("Error reading messages from socket", e);
}
- // connection closed by server
- // COPSDebug.out(getClass().getName(),"Connection closed by client");
try {
- _sock.close();
+ if (! _sock.isClosed())
+ _sock.close();
} catch (IOException e) {
logger.error("Error closing socket", e);
}
* Gets a COPS message from the socket and processes it
* @param conn Socket connected to the PEP
*/
- private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
+ private void processMessage(final Socket conn) throws COPSException, IOException {
final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
- if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
- handleClientCloseMsg(conn, msg);
- } else if (msg.getHeader().getOpCode().equals(OPCode.KA)) {
- handleKeepAliveMsg(conn, msg);
- } else if (msg.getHeader().getOpCode().equals(OPCode.REQ)) {
- handleRequestMsg(conn, msg);
- } else if (msg.getHeader().getOpCode().equals(OPCode.RPT)) {
- handleReportMsg(conn, msg);
- } else if (msg.getHeader().getOpCode().equals(OPCode.DRQ)) {
- handleDeleteRequestMsg(conn, msg);
- } else if (msg.getHeader().getOpCode().equals(OPCode.SSQ)) {
- handleSyncComplete(conn, msg);
- } else {
- throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
+ logger.info("Processing message received of type - " + msg.getHeader().getOpCode());
+
+ switch (msg.getHeader().getOpCode()) {
+ case CC:
+ handleClientCloseMsg(conn, (COPSClientCloseMsg)msg);
+ break;
+ case KA:
+ handleKeepAliveMsg(conn, (COPSKAMsg)msg);
+ break;
+ case REQ:
+ handleRequestMsg(conn, (COPSReqMsg)msg);
+ break;
+ case RPT:
+ handleReportMsg(conn, (COPSReportMsg)msg);
+ break;
+ case DRQ:
+ handleDeleteRequestMsg(conn, (COPSDeleteMsg)msg);
+ break;
+ case SSQ:
+ handleSyncComplete(conn, (COPSSyncStateMsg)msg);
+ break;
+ default:
+ throw new COPSPdpException("Message not expected (" + msg.getHeader().getOpCode() + ").");
}
}
/**
* 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();
+ logger.info("Closing client with error - " + _error.getDescription());
try {
// Support
if (cMsg.getIntegrity() != null) {
}
}
- /**
- * Gets the occurred COPS Error
- * @return <tt>COPSError</tt> object
- */
- protected COPSError getError() {
- return _error;
- }
-
/**
* Handle Keep Alive Message
- *
- * <Keep-Alive> ::= <Common Header>
- * [<Integrity>]
- *
- * Not support [<Integrity>]
- *
* @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param kaMsg a COPSKAMsg
*/
- private void handleKeepAliveMsg(Socket conn, COPSMsg msg) {
- COPSKAMsg cMsg = (COPSKAMsg) msg;
-
- COPSKAMsg kaMsg = (COPSKAMsg) msg;
+ private void handleKeepAliveMsg(final Socket conn, final COPSKAMsg kaMsg) {
try {
// Support
- if (cMsg.getIntegrity() != null) {
+ if (kaMsg.getIntegrity() != null) {
logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
}
-
kaMsg.writeData(conn);
} catch (Exception unae) {
logger.error("Unexpected exception while writing keep-alive message", unae);
/**
* Handle Delete Request Message
- *
- * <Delete Request> ::= <Common Header>
- * <Client Handle>
- * <Reason>
- * [<Integrity>]
- *
- * Not support [<Integrity>]
- *
* @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param cMsg a COPSDeleteMsg
*/
- private void handleDeleteRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
- COPSDeleteMsg cMsg = (COPSDeleteMsg) msg;
- // COPSDebug.out(getClass().getName(),"Removing ClientHandle for " +
- // conn.getInetAddress() + ":" + conn.getPort() + ":[Reason " + cMsg.getReason().getDescription() + "]");
-
+ private void handleDeleteRequestMsg(final Socket conn, final COPSDeleteMsg cMsg) throws COPSPdpException {
// Support
if (cMsg.getIntegrity() != null) {
logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
}
// Delete clientHandler
- if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
- // TODO - Determine what to do here???
- // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
- // cMsg.getClientHandle().getId().getData());
- }
-
- final PCMMPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
+ final PCMMPdpReqStateMan man = _managerMap.remove(cMsg.getClientHandle().getId().str());
if (man == null) {
- logger.warn("State manager not found");
+ logger.warn("Cannot delete request state, no state manger found");
} else {
man.processDeleteRequestState(cMsg);
}
-
}
/**
* Handle Request Message
- *
- * <Request> ::= <Common Header>
- * <Client Handle>
- * <Context>
- * *(<Named ClientSI>)
- * [<Integrity>]
- * <Named ClientSI> ::= <*(<PRID> <EPD>)>
- *
- * Not support [<Integrity>]
- *
* @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param reqMsg a COPSReqMsg
*/
- private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
-
- final COPSReqMsg reqMsg = (COPSReqMsg) msg;
-// COPSContext cntxt = reqMsg.getContext();
+ private void handleRequestMsg(final Socket conn, final COPSReqMsg reqMsg) throws COPSException {
final COPSHeader header = reqMsg.getHeader();
- //short reqType = cntxt.getRequestType();
final short cType = header.getClientType();
// Support
logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
}
- PCMMPdpReqStateMan man;
- man = _managerMap.get(reqMsg.getClientHandle().getId().str());
- if (man == null) {
+ final PCMMPdpReqStateMan man;
+ if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
- man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
+ man = new PCMMPdpReqStateMan(cType, reqMsg.getClientHandle(), _process);
_managerMap.put(reqMsg.getClientHandle().getId().str(), man);
- man.setDataProcess(_process);
man.initRequestState(_sock);
-
- // COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
- // header.getClientType() + " msgType=" +
- // cntxt.getMessageType() + ", connId=" + conn.toString());
+ logger.info("Created state manager for ID - " + reqMsg.getClientHandle().getId().str());
+ } else {
+ man = _managerMap.get(reqMsg.getClientHandle().getId().str());
}
man.processRequest(reqMsg);
/**
* Handle Report Message
- *
- * <Report State> ::= <Common Header>
- * <Client Handle>
- * <Report Type>
- * *(<Named ClientSI>)
- * [<Integrity>]
- *
- * Not support [<Integrity>]
- *
* @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param repMsg a COPSReportMsg
*/
- private void handleReportMsg(Socket conn, COPSMsg msg)
- throws COPSPdpException {
- COPSReportMsg repMsg = (COPSReportMsg) msg;
- // COPSHandle handle = repMsg.getClientHandle();
- // COPSHeader header = repMsg.getHeader();
-
+ private void handleReportMsg(final Socket conn, final COPSReportMsg repMsg) throws COPSPdpException {
// Support
if (repMsg.getIntegrity() != null) {
logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
/**
* Method handleSyncComplete
- *
* @param conn a Socket
- * @param msg a COPSMsg
- *
+ * @param cMsg a COPSSyncStateMsg
*/
- private void handleSyncComplete(Socket conn, COPSMsg msg)
- throws COPSPdpException {
- COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
- // COPSHandle handle = cMsg.getClientHandle();
- // COPSHeader header = cMsg.getHeader();
-
+ private void handleSyncComplete(final Socket conn, final COPSSyncStateMsg cMsg) throws COPSException {
// Support
if (cMsg.getIntegrity() != null) {
logger.error("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
* @throws COPSException
* @throws COPSPdpException
*/
- protected void syncAllRequestState() throws COPSException, COPSPdpException {
+ protected void syncAllRequestState() throws COPSException {
for (final PCMMPdpReqStateMan man : _managerMap.values()) {
man.syncRequestState();
}
import org.pcmm.gates.impl.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSMsgSender;
import org.umu.cops.prpdp.COPSPdpException;
import org.umu.cops.stack.*;
+import org.umu.cops.stack.COPSClientSI.CSIType;
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.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSObjHeader.CNum;
import org.umu.cops.stack.COPSObjHeader.CType;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
-//temp
-//pcmm
/*
* Example of an UNSOLICITED decision
*
/**
* COPS message transceiver class for provisioning connections at the PDP side.
*/
-public class PCMMPdpMsgSender {
+public class PCMMPdpMsgSender extends COPSMsgSender {
public final static Logger logger = LoggerFactory.getLogger(PCMMPdpMsgSender.class);
- /**
- * Socket connected to PEP
- */
- protected Socket _sock;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular PEP's request
- * for a client-type
- */
- protected COPSHandle _handle;
-
- /**
- *
- */
protected short _transactionID;
- protected short _classifierID;
+ protected final short _classifierID;
+
// XXX - this does not need to be here
- protected int _gateID;
+ protected IGateID _gateID;
/**
* Creates a PCMMPdpMsgSender
* @param sock
* Socket to the PEP
*/
- public PCMMPdpMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
- // COPS Handle
- _handle = clientHandle;
- _clientType = clientType;
-
- _transactionID = 0;
- _classifierID = 0;
- _sock = sock;
+ public PCMMPdpMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock)
+ throws COPSPdpException {
+ this(clientType, (short)0, clientHandle, sock);
}
public PCMMPdpMsgSender(final short clientType, final short tID, final COPSHandle clientHandle,
- final Socket sock) {
- // COPS Handle
- _handle = clientHandle;
- _clientType = clientType;
+ final Socket sock) throws COPSPdpException {
+ super(clientType, clientHandle, sock);
_transactionID = tID;
_classifierID = 0;
- _sock = sock;
- }
-
- /**
- * Gets the client handle
- *
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- *
- * @return Client-type value
- */
- public short getClientType() {
- return _clientType;
}
/**
return _transactionID;
}
+ /**
+ * Gets the gate-id
+ *
+ * @return the gate-id value
+ */
+ public IGateID getGateID() {
+ return _gateID;
+ }
/**
* Sends a PCMM GateSet COPS Decision message
trID.setTransactionIdentifier(_transactionID);
gate.setTransactionID(trID);
-
+ // retain the transactionId to gate request mapping for gateID recovery after response
+ // see PCMMPdpReqStateMan.processReport()
+ final Short trIDnum = trID.getTransactionIdentifier();
+ logger.info("Adding gate to cache - " + gate + " with key - " + trIDnum);
+ PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
// new pcmm specific clientsi
final byte[] data = gate.getData();
// Client Handle with the same clientHandle as the request
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
- new COPSData(data, 0, data.length)));
+ 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 COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
- decisionMap, null);
-// new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
- // new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null));
+ final COPSClientSI clientSD = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData(data, 0, data.length));
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, clientSD);
+
// ** Send the GateSet Decision
- // **
try {
decisionMsg.writeData(_sock);
} catch (IOException e) {
// TODO - Use some variable here or remove...
if (true) {
//eclassifier.setProtocol(IClassifier.Protocol.NONE);
- eclassifier.setProtocol(IClassifier.Protocol.TCP);
+// eclassifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress
.getByName(PCMMGlobalConfig.SubscriberID);
eclassifier.setPriority((byte) 65);
} else {
- classifier.setProtocol(IClassifier.Protocol.TCP);
+// classifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress
.getByName(PCMMGlobalConfig.SubscriberID);
final byte[] data = gate.getData();
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
- new COPSData(data, 0, data.length)));
+ decisionSet.add(new COPSDecision(CType.NA, 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(CSIType.NAMED, new COPSData(data, 0, data.length));
// Common Header with the same ClientType as the request
// Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(),
- new COPSHandle(getClientHandle().getId()), decisionMap, null);
-// new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
- // new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length))); TODO - what does the value of 4 mean here???
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
// ** Send the GateSet Decision
// **
// XXX - if the version major is less than 4 we need to use Classifier
if (true) {
//eclassifier.setProtocol(IClassifier.Protocol.NONE);
- eclassifier.setProtocol(IClassifier.Protocol.TCP);
+// eclassifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress
.getByName(PCMMGlobalConfig.SubscriberID);
eclassifier.setPriority((byte) 65);
} else {
- classifier.setProtocol(IClassifier.Protocol.TCP);
+// classifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress
.getByName(PCMMGlobalConfig.SubscriberID);
byte[] data = gate.getData();
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR, new COPSData(data, 0, data.length)));
+ decisionSet.add(new COPSDecision(CType.CSI, 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(CSIType.NAMED, new COPSData(data, 0, data.length));
// Common Header with the same ClientType as the request
// Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
- decisionMap, null);
-// new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
- // new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null)); TODO - what does the value of 4 mean here???
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, clientSD);
// ** Send the GateSet Decision
// **
logger.info("the CMTS has sent a Gate-Set-Ack response");
// here CMTS responded that he acknowledged the Gate-Set
// TODO do further check of Gate-Set-Ack GateID etc...
- _gateID = responseGate.getGateID().getGateID();
+ _gateID = responseGate.getGateID();
return true;
} else {
return false;
}
return false;
} catch (Exception e) { // COPSException, IOException
- throw new COPSPdpException("Error COPSTransceiver.receiveMsg");
+ throw new COPSPdpException("Error COPSTransceiver.receiveMsg", e);
}
}
.setRequestTransmissionPolicy(
PCMMGlobalConfig.BETransmissionPolicy);
- // byte[] content = "1234".getBytes();
-
- // handle.setId(new COPSData(content, 0, content.length));
-
// set transaction ID to gate set
trID.setGateCommandType(ITransactionID.GateSet);
_transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID);
* .setServiceClassName("S_up");
*/
- classifier.setProtocol(IClassifier.Protocol.TCP);
+// classifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
final byte[] data = gate.getData();
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL,
- DecisionFlag.REQERROR, new COPSData(data, 0, data.length)));
+ decisionSet.add(new COPSDecision(CType.CSI, 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(CSIType.NAMED, new COPSData(data, 0, data.length));
+
// Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(),
- new COPSHandle(getClientHandle().getId()), decisionMap, null);
-// new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
- // new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null));
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
// ** Send the GateSet Decision
// **
} catch (IOException e) {
logger.error("Failed to send the decision", e);
}
-
}
/**
*
* @throws COPSPdpException
*/
- public void sendGateDelete(int gID) throws COPSPdpException {
- /*
- * Example of an UNSOLICITED decision <Gate Control Command> = <COPS
- * Common Header> <Client Handle> <Context> <Decision Flags> <ClientSI
- * Data> <ClientSI Data> = <Gate-Set> | <Gate-Info> | <Gate-Delete> |
- * <PDP-Config> | <Synch-Request> | <Msg-Receipt> <Gate-Delete> =
- * <Decision Header> <TransactionID> <AMID> <SubscriberID> <GateID>
- */
- // Common Header with the same ClientType as the request
- final IPCMMGate gate = new PCMMGateReq();
- final ITransactionID trID = new TransactionID();
-
- final IAMID amid = new AMID();
- final ISubscriberID subscriberID = new SubscriberID();
- final IGateSpec gateSpec = new GateSpec();
- final IGateID gateID = new GateID();
-
+ public void sendGateDelete(final IPCMMGate gate) throws COPSPdpException {
// set transaction ID to gate set
+ final ITransactionID trID = new TransactionID();
trID.setGateCommandType(ITransactionID.GateDelete);
_transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID);
trID.setTransactionIdentifier(_transactionID);
+ gate.setTransactionID(trID);
- amid.setApplicationType((short) 1);
- amid.setApplicationMgrTag((short) 1);
- gateID.setGateID(gID);
+ Short trIDnum = trID.getTransactionIdentifier();
+ PCMMGlobalConfig.transactionGateMap.put(trIDnum, gate);
- try {
- InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
- subscriberID.setSourceIPAddress(subIP);
- } catch (UnknownHostException unae) {
- logger.error("Error getByName", unae);
- }
-
- gate.setTransactionID(trID);
- gate.setAMID(amid);
- gate.setSubscriberID(subscriberID);
- gate.setGateID(gateID);
+ // gateDelete only requires AMID, subscriberID, and gateID
+ // remove the gateSpec, traffic profile, and classifiers from original gate request
+ gate.setGateSpec(null);
+ gate.setTrafficProfile(null);
+ gate.setClassifier(null);
+ // clear the error object
+ gate.setError(null);
// XXX - GateID
final byte[] data = gate.getData();
-
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR,
- new COPSData(data, 0, data.length)));
+ 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);
+ 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(getClientType(),
- new COPSHandle(getClientHandle().getId()), decisionMap, null);
-// new COPSClientSI(CSIType.SIGNALED, new COPSData(data, 0, data.length)), decisionMap);
- // new COPSClientSI(CNum.DEC, (byte) 4, new COPSData(data, 0, data.length), null));
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, clientSD);
// ** Send the GateDelete Decision
// **
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
- decisionMap, null);
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, null);
try {
decisionMsg.writeData(_sock);
} catch (IOException e) {
- throw new COPSPdpException(
- "Failed to send the open new request state, reason: "
- + e.getMessage());
+ throw new COPSPdpException("Failed to send the open new request state", e);
}
}
/*
* <Gate-Info> ::= <Common Header> [<Client Handle>] [<Integrity>]
*/
- final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), new COPSHandle(_handle.getId()), null);
+ final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), _handle, null);
try {
msg.writeData(_sock);
} catch (IOException e) {
- throw new COPSPdpException(
- "Failed to send the GateInfo request, reason: "
- + e.getMessage());
+ throw new COPSPdpException("Failed to send the GateInfo request", e);
}
}
*/
// Client Handle with the same clientHandle as the request
- final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), new COPSHandle(_handle.getId()), null);
+ final COPSSyncStateMsg msg = new COPSSyncStateMsg(getClientType(), _handle, null);
try {
msg.writeData(_sock);
} catch (IOException e) {
- throw new COPSPdpException(
- "Failed to send the sync state request, reason: "
- + e.getMessage());
+ throw new COPSPdpException("Failed to send the sync state request", e);
}
}
// XXX - Temp
package org.pcmm;
+import org.pcmm.gates.IGateID;
+import org.pcmm.gates.IPCMMGate;
import org.pcmm.gates.ITransactionID;
import org.pcmm.gates.impl.PCMMGateReq;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
import org.umu.cops.prpdp.COPSPdpException;
import org.umu.cops.stack.*;
import org.umu.cops.stack.COPSReportType.ReportType;
/**
* State manager class for provisioning requests, at the PDP side.
*/
-public class PCMMPdpReqStateMan {
+public class PCMMPdpReqStateMan extends COPSStateMan {
- public final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
-
- /**
- * Request State created
- */
- public final static short ST_CREATE = 1;
- /**
- * Request received
- */
- public final static short ST_INIT = 2;
- /**
- * Decisions sent
- */
- public final static short ST_DECS = 3;
- /**
- * Report received
- */
- public final static short ST_REPORT = 4;
- /**
- * Request State finalized
- */
- public final static short ST_FINAL = 5;
- /**
- * New Request State solicited
- */
- public final static short ST_NEW = 6;
- /**
- * Delete Request State solicited
- */
- public final static short ST_DEL = 7;
- /**
- * SYNC request sent
- */
- public final static short ST_SYNC = 8;
- /**
- * SYNC completed
- */
- public final static short ST_SYNCALL = 9;
- /**
- * Close connection received
- */
- public final static short ST_CCONN = 10;
- /**
- * Keep-alive timeout
- */
- public final static short ST_NOKA = 11;
- /**
- * Accounting timeout
- */
- public final static short ST_ACCT = 12;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
+ private final static Logger logger = LoggerFactory.getLogger(PCMMPdpReqStateMan.class);
/**
* Object for performing policy data processing
*/
- protected PCMMPdpDataProcess _process;
-
- /**
- * Current state of the request being managed
- */
- protected short _status;
+ protected final PCMMPdpDataProcess _process;
/** COPS message transceiver used to send COPS messages */
- protected PCMMPdpMsgSender _sender;
+ protected transient PCMMPdpMsgSender _sender;
/**
* Creates a request state manager
* @param clientType Client-type
* @param clientHandle Client handle
*/
- public PCMMPdpReqStateMan(final short clientType, final String clientHandle) {
- _handle = new COPSHandle(new COPSData(clientHandle));
- _clientType = clientType;
- _status = ST_CREATE;
+ // TODO - consider sending in the COPSHandle object instead
+ public PCMMPdpReqStateMan(final short clientType, final COPSHandle clientHandle, final PCMMPdpDataProcess process) {
+ super(clientType, clientHandle);
+ this._process = process;
}
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public int getClientType() {
- return _clientType;
- }
-
- /**
- * Gets the status of the request
- * @return Request state value
- */
- public short getStatus() {
- return _status;
- }
-
- /**
- * Gets the policy data processing object
- * @return Policy data processing object
- */
- public PCMMPdpDataProcess getDataProcess() {
- return _process;
- }
-
- /**
- * Sets the policy data processing object
- * @param process Policy data processing object
- */
- public void setDataProcess(PCMMPdpDataProcess process) {
- _process = process;
- }
-
- /**
- * Called when COPS sync is completed
- * @param repMsg COPS sync message
- * @throws COPSPdpException
- */
- protected void processSyncComplete(COPSSyncStateMsg repMsg)
- throws COPSPdpException {
-
- _status = ST_SYNCALL;
-
- // maybe we should notifySyncComplete ...
- }
-
- /**
- * Initializes a new request state over a socket
- * @param sock Socket to the PEP
- * @throws COPSPdpException
- */
- protected void initRequestState(Socket sock)
- throws COPSPdpException {
+ @Override
+ protected void initRequestState(final Socket sock) throws COPSException {
// Inits an object for sending COPS messages to the PEP
_sender = new PCMMPdpMsgSender(_clientType, _handle, sock);
// Initial state
- _status = ST_INIT;
+ _status = Status.ST_INIT;
}
* @param msg COPS request received from the PEP
* @throws COPSPdpException
*/
- protected void processRequest(COPSReqMsg msg)
- throws COPSPdpException {
+ public void processRequest(final COPSReqMsg msg) throws COPSPdpException {
- COPSHeader hdrmsg = msg.getHeader();
- COPSHandle handlemsg = msg.getClientHandle();
- COPSContext contextmsg = msg.getContext();
+ // TODO - Implement me
+// COPSHeader hdrmsg = msg.getHeader();
+// COPSHandle handlemsg = msg.getClientHandle();
+// COPSContext contextmsg = msg.getContext();
//** Analyze the request
//**
* Processes a report
* @param msg Report message from the PEP
* @throws COPSPdpException
+ * TODO - break apart this method
*/
- protected void processReport(COPSReportMsg msg) throws COPSPdpException {
+ protected void processReport(final COPSReportMsg msg) throws COPSPdpException {
// Report Type
final COPSReportType rtypemsg = msg.getReport();
// PCMMUtils.WriteBinaryDump("COPSReportClientSI", data);
logger.info("PCMMGateReq Parse Gate Message");
- PCMMGateReq gateMsg = new PCMMGateReq(data);
+ final PCMMGateReq gateMsg = new PCMMGateReq(data);
+ // TODO FIXME - Why is this Map being filled but never used???
final Map<String, String> repSIs = new HashMap<>();
String strobjprid = "";
final COPSPrObjBase obj = new COPSPrObjBase(clientSI.getData().getData());
case COPSPrObjBase.PR_EPD:
logger.info("COPSPrObjBase.PR_EPD");
repSIs.put(strobjprid, obj.getData().str());
- // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);
- // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());
+ logger.info("PRID: " + strobjprid);
+ logger.info("EPD: " + obj.getData().str());
break;
default:
logger.error("Object s-num: " + obj.getSNum() + "stype " + obj.getSType());
logger.info("rtypemsg process");
//** Here we must act in accordance with
//** the report received
+
+ // retrieve and remove the transactionId to gate request map entry
+ // see PCMMPdpMsgSender.sendGateSet(IPCMMGate gate)
+ final ITransactionID trID = gateMsg.getTransactionID();
+ final Short trIDnum = trID.getTransactionIdentifier();
+
+ logger.info("Removing gate from cache with key - " + trIDnum);
+ final IPCMMGate gate = PCMMGlobalConfig.transactionGateMap.remove(trIDnum);
+ if (gate != null) {
+ // capture the "error" message if any
+ gate.setError(gateMsg.getError());
+ logger.info("Setting error on gate - " + gateMsg.getError());
+ }else {
+ logger.error("processReport(): gateReq not found for transactionID {}", trIDnum);
+ return;
+ }
+
if (rtypemsg.getReportType().equals(ReportType.SUCCESS)) {
logger.info("rtypemsg success");
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
+ final IGateID gateID = gateMsg.getGateID();
+ logger.info("Setting gate ID on gate object - " + gateID);
+ gate.setGateID(gateID);
if (_process != null)
_process.successReport(this, gateMsg);
} else {
- if (gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck) {
- logger.info("GateDeleteAck: GateID = " + gateMsg.getGateID().getGateID());
- if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID1())
- PCMMGlobalConfig.setGateID1(0);
- if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID2())
- PCMMGlobalConfig.setGateID2(0);
-
- }
- if (gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck) {
- logger.info("GateSetAck: GateID = " + gateMsg.getGateID().getGateID());
- if (0 == PCMMGlobalConfig.getGateID1())
- PCMMGlobalConfig.setGateID1(gateMsg.getGateID().getGateID());
- if (0 == PCMMGlobalConfig.getGateID2())
- PCMMGlobalConfig.setGateID2(gateMsg.getGateID().getGateID());
- }
+ final String cmdType;
+ if ( trID.getGateCommandType() == ITransactionID.GateDeleteAck ) {
+ cmdType = "GateDeleteAck";
+ } else if ( trID.getGateCommandType() == ITransactionID.GateSetAck ) {
+ cmdType = "GateSetAck";
+ } else cmdType = null;
+ // capture the gateId from the response message
+ final IGateID gateID = gateMsg.getGateID();
+ logger.info("Setting gate ID on gate object - " + gateID);
+ gate.setGateID(gateID);
+ int gateIdInt = gateID.getGateID();
+ String gateIdHex = String.format("%08x", gateIdInt);
+ logger.info(getClass().getName() + ": " + cmdType + ": GateID = " + gateIdHex);
}
if (rtypemsg.getReportType().equals(ReportType.FAILURE)) {
logger.info("rtypemsg failure");
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
if (_process != null)
_process.failReport(this, gateMsg);
else
logger.info("Gate message error - " + gateMsg.getError().toString());
- } else
- if (rtypemsg.getReportType().equals(ReportType.ACCOUNTING)) {
+ } else if (rtypemsg.getReportType().equals(ReportType.ACCOUNTING)) {
logger.info("rtypemsg account");
- _status = ST_ACCT;
+ _status = Status.ST_ACCT;
if (_process != null)
_process.acctReport(this, gateMsg);
- }
+ }
+
+ // let the waiting gateSet/gateDelete sender proceed
+ // TODO - see PCMMService#processReport() gate.notify(). Should determine a better means to
+ // TODO - handle this synchronization.
+ logger.info("Notify gate request has been updated with ID - " + gate.getGateID());
+ synchronized(gate) {
+ gate.notify();
+ }
+ logger.info("Out processReport");
}
}
* @param error Reason
* @throws COPSPdpException
*/
- protected void processClosedConnection(COPSError error)
- throws COPSPdpException {
+ protected void processClosedConnection(final COPSError error) throws COPSPdpException {
if (_process != null)
_process.notifyClosedConnection(this, error);
- _status = ST_CCONN;
+ _status = Status.ST_CCONN;
}
/**
* Called when no keep-alive is received
* @throws COPSPdpException
*/
- protected void processNoKAConnection()
- throws COPSPdpException {
+ protected void processNoKAConnection() throws COPSPdpException {
if (_process != null)
_process.notifyNoKAliveReceived(this);
- _status = ST_NOKA;
+ _status = Status.ST_NOKA;
}
/**
* Deletes the request state
* @throws COPSPdpException
*/
- protected void finalizeRequestState()
- throws COPSPdpException {
+ protected void finalizeRequestState() throws COPSPdpException {
_sender.sendDeleteRequestState();
- _status = ST_FINAL;
+ _status = Status.ST_FINAL;
}
/**
* Asks for a COPS sync
* @throws COPSPdpException
*/
- protected void syncRequestState()
- throws COPSPdpException {
+ protected void syncRequestState() throws COPSPdpException {
_sender.sendSyncRequestState();
- _status = ST_SYNC;
+ _status = Status.ST_SYNC;
}
/**
* Opens a new request state
* @throws COPSPdpException
*/
- protected void openNewRequestState()
- throws COPSPdpException {
+ protected void openNewRequestState() throws COPSPdpException {
_sender.sendOpenNewRequestState();
- _status = ST_NEW;
+ _status = Status.ST_NEW;
}
/**
* @param dMsg <tt>COPSDeleteMsg</tt> received from the PEP
* @throws COPSPdpException
*/
- protected void processDeleteRequestState(COPSDeleteMsg dMsg)
- throws COPSPdpException {
+ protected void processDeleteRequestState(COPSDeleteMsg dMsg) throws COPSPdpException {
if (_process != null)
_process.closeRequestState(this);
- _status = ST_DEL;
+ _status = Status.ST_DEL;
}
}
package org.pcmm.gates;
-import java.net.InetAddress;
-
import org.pcmm.base.IPCMMBaseObject;
+import java.net.InetAddress;
+
/**
*
*
*/
public interface IClassifier extends IPCMMBaseObject {
- static final short LENGTH = 24;
- static final byte SNUM = 6;
- static final byte STYPE = 1;
+ short LENGTH = 24;
+ byte SNUM = 6;
+ byte STYPE = 1;
- static enum Protocol {
+ enum Protocol {
/*ICMP((short) 1), IGMP((short) 2), */
NONE((short)0), TCP((short) 6), UDP((short) 17);
*
* @return the protocol.
*/
- Protocol getProtocol();
+ short getProtocol();
/**
* @see <a
* href="http://www.iana.org/assignments/protocol-numbers/protocol-numbers.txt">protocols</a>
- * @param p
+ * @param p - the protocol value
*/
- void setProtocol(Protocol p);
+ void setProtocol(short p);
/**
* Priority may be used to distinguish between multiple classifiers that
* information regarding the treatment of other objects specified in the Gate
* message.
* </p>
- *
- *
- *
- *
*/
public interface IGateSpec extends IPCMMBaseObject {
- static final byte SNUM = 5;
- static final byte STYPE = 1;
- static final short LENGTH = 16;
+ byte SNUM = 5;
+ byte STYPE = 1;
+ short LENGTH = 16;
/**
* <p>
*
*
*/
- public enum Direction {
+ enum Direction {
UPSTREAM((byte) 1), DOWNSTREAM((byte) 0);
- private Direction(byte value) {
+ Direction(byte value) {
this.value = value;
}
}
}
- };
+ }
/**
*
*/
- public enum DSCPTOS {
+ enum DSCPTOS {
- ENABLE((byte) 1), OVERRIDE((byte) 0);
+ ENABLE((byte) 2), OVERRIDE((byte) 0);
- private DSCPTOS(byte value) {
+ DSCPTOS(byte value) {
this.value = value;
}
private byte value;
- };
+ }
/**
* <p>
/**
*
- * @param dscpTos
+ * @param dscpTos - the object used to overwrite
*/
void setDSCP_TOSOverwrite(DSCPTOS dscpTos);
+ // set the DSCP_TOS value
+ void setDSCP_TOSOverwrite(byte dscpTos);
+
/**
*
* @return DSCP/TOS
/**
*
- * @return
+ * @return - the mask
*/
byte getDSCP_TOSMask();
package org.pcmm.gates;
+import java.net.InetAddress;
+
public interface IIPv6Classifier extends IExtendedClassifier {
- static final short LENGTH = 64;
- static final byte SNUM = 6;
- static final byte STYPE = 3;
+ short LENGTH = 64;
+ byte SNUM = 6;
+ byte STYPE = 3;
+
+ // flags: Flow Label match enable flag
+ void setFlowLabelEnableFlag(byte flag);
+ byte getFlowLabelEnableFlag();
// Tc-low
+ void setTcLow(byte tcLow);
+ byte getTcLow();
+
// Tc-high
+ void setTcHigh(byte tcHigh);
+ byte getTcHigh();
+
// Tc-mask
+ void setTcMask(byte tcHigh);
+ byte getTcMask();
+
// Flow Label
+ void setFlowLabel(Long flowLabel);
+ int getFlowLabel();
+
// Next Header Type
+ void setNextHdr(short nxtHdr);
+ short getNextHdr();
+
// Source Prefix Length
+ void setSourcePrefixLen(byte srcPrefixLen);
+ byte getSourcePrefixLen();
+
// Destination Prefix Length
+ void setDestinationPrefixLen(byte dstPrefixLen);
+ byte getDestinationPrefixLen();
+
// IPv6 Source Address
+ void setSourceIPAddress(InetAddress a);
+ InetAddress getSourceIPAddress();
+
// IPv6 Destination Address
+ void setDestinationIPAddress(InetAddress a);
+ InetAddress getDestinationIPAddress();
+
// Source Port Start
+ short getSourcePortStart();
+ void setSourcePortStart(short p);
+
// Source Port End
+ short getSourcePortEnd();
+ void setSourcePortEnd(short p);
+
// Destination Port Start
+ short getDestinationPortStart();
+ void setDestinationPortStart(short p);
+
// Destination Port End
+ short getDestinationPortEnd();
+ void setDestinationPortEnd(short p);
+
// ClassifierID
+ short getClassifierID();
+ void setClassifierID(short p);
+
// Priority
+ void setPriority(byte p);
+ byte getPriority();
+
// Activation State
- // Action
+ void setActivationState(byte s);
+ byte getActivationState();
+ // Action
+ void setAction(byte a);
+ byte getAction();
}
*/
package org.pcmm.gates.impl;
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IClassifier;
+
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
-import org.pcmm.base.impl.PCMMBaseObject;
-import org.pcmm.gates.IClassifier;
-
/**
- *
+ * TODO - Cleanup this interface
*/
public class Classifier extends PCMMBaseObject implements IClassifier {
}
/**
- * @param data
+ * @param data - the data to add
*/
public Classifier(byte[] data) {
super(data);
}
/**
- * @param len
- * @param sType
- * @param sNum
+ * @param len - the classifier's length
+ * @param sType - the sType value
+ * @param sNum - the sNum value
*/
public Classifier(short len, byte sType, byte sNum) {
super(len, sType, sNum);
* @see org.pcmm.gates.IClassifier#getProtocol()
*/
@Override
- public Protocol getProtocol() {
- return Protocol.valueOf(getShort((short) 0));
+ public short getProtocol() {
+ return getShort((short) 0);
}
/*
* @see org.pcmm.gates.IClassifier#setProtocol(short)
*/
@Override
- public void setProtocol(Protocol p) {
- setShort(p.getValue(), (short) 0);
+ public void setProtocol(short p) {
+ setShort(p, (short) 0);
}
/*
implements ITrafficProfile {
public static final byte STYPE = 2;
- public static final short LENGTH = 12;
+ public static final short LENGTH = 24;
/**
*
}
/**
- * @param data
+ * @param data - the data bytes to parse
*/
public DOCSISServiceClassNameTrafficProfile(byte[] data) {
super(data);
}
/**
- * @param len
- * @param sType
- * @param sNum
+ * @param len - the classifier's length
+ * @param sType - the sType value
+ * @param sNum - the sNum value
*/
public DOCSISServiceClassNameTrafficProfile(short len, byte sType, byte sNum) {
super(len, sType, sNum);
*/
package org.pcmm.gates.impl;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
import org.pcmm.base.impl.PCMMBaseObject;
import org.pcmm.gates.IExtendedClassifier;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
*
*/
}
/**
- * @param data
+ * @param data - the data bytes to parse
*/
public ExtendedClassifier(byte[] data) {
super(data);
}
/**
- * @param len
- * @param sType
- * @param sNum
+ * @param len - the classifier's length
+ * @param sType - the sType value
+ * @param sNum - the sNum value
*/
public ExtendedClassifier(short len, byte sType, byte sNum) {
super(len, sType, sNum);
* @see org.pcmm.gates.IClassifier#getProtocol()
*/
@Override
- public Protocol getProtocol() {
- return Protocol.valueOf(getShort((short) 0));
+ public short getProtocol() {
+ return getShort((short) 0);
}
/*
* @see org.pcmm.gates.IClassifier#setProtocol(short)
*/
@Override
- public void setProtocol(Protocol p) {
- setShort(p.getValue(), (short) 0);
+ public void setProtocol(short p) {
+ setShort(p, (short) 0);
}
/*
*/
public class GateSpec extends PCMMBaseObject implements IGateSpec {
+ // GateSpec flags are Direction (bit 0) and DSCPTOS overwrite enable (bit 1)
+ private byte flags = 0;
+
public GateSpec() {
super(LENGTH, STYPE, SNUM);
}
@Override
public void setDirection(Direction direction) {
- setByte(direction.getValue(), (short) 0);
+ // OR in the Direction flag with the DSCPTOS enable flag
+ flags |= direction.getValue();
+ setByte(flags, (short) 0);
}
@Override
@Override
public void setDSCP_TOSOverwrite(DSCPTOS dscpTos) {
- setByte(dscpTos.getValue(), (short) 1);
+ // OR in the DSCPTOS enable flag with the Direction flag
+ flags |= dscpTos.getValue();
+ setByte(flags, (short) 0);
}
+ @Override
+ public void setDSCP_TOSOverwrite(byte dscpTos) {
+ setByte(dscpTos, (short) 1);
+ }
+
+
@Override
public DSCPTOS getDSCP_TOSOverwrite() {
return DSCPTOS.valueOf(getByte((short) 1));
--- /dev/null
+/**
+
+ * Copyright (c) 2014 CableLabs. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+
+ */
+package org.pcmm.gates.impl;
+
+import org.pcmm.base.impl.PCMMBaseObject;
+import org.pcmm.gates.IIPv6Classifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ *
+ */
+public class IPv6Classifier extends PCMMBaseObject implements
+ IIPv6Classifier {
+
+ private Logger logger = LoggerFactory.getLogger(IPv6Classifier.class);
+
+ public IPv6Classifier() {
+ this(LENGTH, STYPE, SNUM);
+ }
+
+ /**
+ * @param data - the data bytes to parse
+ */
+ public IPv6Classifier(byte[] data) {
+ super(data);
+ }
+
+ /**
+ * @param len - the classifier's length
+ * @param sType - the sType value
+ * @param sNum - the sNum value
+ */
+ public IPv6Classifier(short len, byte sType, byte sNum) {
+ super(len, sType, sNum);
+ }
+
+ // offset:length Field Name: Description
+ // 00:01 Flags: 0000.0001 Flow Label enable match
+ // 01:01 Tc-low
+ // 02:01 Tc-high
+ // 03:01 Tc-mask
+ // 04:04 Flow Label: low order 20 bits; high order 12 bits ignored
+ // 08:02 Next Header Type
+ // 10:01 Source Prefix Length
+ // 11:01 Destination Prefix Length
+ // 12:16 IPv6 Source Address
+ // 28:16 IPv6 Destination Address
+ // 44:02 Source Port Start
+ // 46:02 Source Port End
+ // 48:02 Destination Port Start
+ // 50:02 Destination Port End
+ // 52:02 ClassifierID
+ // 54:01 Priority
+ // 55:01 Activation State
+ // 56:01 Action
+ // 57:03 Reserved
+
+ // 00:01 Flags: 0000.0001 Flow Label enable match
+ @Override
+ public void setFlowLabelEnableFlag(byte flag) {
+ setByte(flag, (short) 0);
+ }
+ @Override
+ public byte getFlowLabelEnableFlag() {
+ return getByte((short) 0);
+ }
+
+ // 01:01 Tc-low
+ @Override
+ public void setTcLow(byte tcLow) {
+ setByte(tcLow, (short) 1);
+ }
+ @Override
+ public byte getTcLow() {
+ return getByte((short) 1);
+ }
+
+ // 02:01 Tc-high
+ @Override
+ public void setTcHigh(byte tcHigh) {
+ setByte(tcHigh, (short) 2);
+ }
+ @Override
+ public byte getTcHigh() {
+ return getByte((short) 2);
+ }
+
+ // 03:01 Tc-mask
+ @Override
+ public void setTcMask(byte tcMask) {
+ setByte(tcMask, (short) 3);
+ }
+ @Override
+ public byte getTcMask() {
+ return getByte((short) 3);
+ }
+
+ // 04:04 Flow Label: low order 20 bits; high order 12 bits ignored
+ @Override
+ public void setFlowLabel(Long flowLabel) {
+ setInt(flowLabel.intValue(), (short) 4);
+ }
+ @Override
+ public int getFlowLabel() {
+ return getInt((short) 4);
+ }
+
+ // 08:02 Next Header Type
+ @Override
+ public void setNextHdr(short nxtHdr) {
+ setShort(nxtHdr, (short) 8);
+ }
+ @Override
+ public short getNextHdr() {
+ return getShort((short) 8);
+ }
+
+ // 10:01 Source Prefix Length
+ @Override
+ public void setSourcePrefixLen(byte srcPrefixLen) {
+ setByte(srcPrefixLen, (short) 10);
+ }
+ @Override
+ public byte getSourcePrefixLen() {
+ return getByte((short) 10);
+ }
+
+ // 11:01 Destination Prefix Length
+ @Override
+ public void setDestinationPrefixLen(byte dstPrefixLen) {
+ setByte(dstPrefixLen, (short) 11);
+ }
+ @Override
+ public byte getDestinationPrefixLen() {
+ return getByte((short) 11);
+ }
+
+ // 12:16 IPv6 Source Address
+ @Override
+ public void setSourceIPAddress(InetAddress a) {
+ setBytes(a.getAddress(), (short) 12);
+ }
+ @Override
+ public InetAddress getSourceIPAddress() {
+ try {
+ return InetAddress.getByAddress(getBytes((short) 12, (short) 16));
+ } catch (UnknownHostException e) {
+ logger.error("getSourceIPAddress(): Malformed IPv6 address: {}", e.getMessage());
+ }
+ return null;
+ }
+
+ // 28:16 IPv6 Destination Address
+ @Override
+ public void setDestinationIPAddress(InetAddress a) {
+ setBytes(a.getAddress(), (short) 28);
+ }
+ @Override
+ public InetAddress getDestinationIPAddress() {
+ try {
+ return InetAddress.getByAddress(getBytes((short) 28, (short) 16));
+ } catch (UnknownHostException e) {
+ logger.error("getDestinationIPAddress(): Malformed IPv6 address: {}", e.getMessage());
+ }
+ return null;
+ }
+ // 44:02 Source Port Start
+ @Override
+ public short getSourcePortStart() {
+ return getShort((short) 44);
+ }
+ @Override
+ public void setSourcePortStart(short p) {
+ setShort(p, (short) 44);
+ }
+
+ // 46:02 Source Port End
+ @Override
+ public short getSourcePortEnd() {
+ return getShort((short) 46);
+ }
+ @Override
+ public void setSourcePortEnd(short p) {
+ setShort(p, (short) 46);
+ }
+
+ // 48:02 Destination Port Start
+ @Override
+ public short getDestinationPortStart() {
+ return getShort((short) 48);
+ }
+ @Override
+ public void setDestinationPortStart(short p) {
+ setShort(p, (short) 48);
+ }
+
+ // 50:02 Destination Port End
+ @Override
+ public short getDestinationPortEnd() {
+ return getShort((short) 50);
+ }
+ @Override
+ public void setDestinationPortEnd(short p) {
+ setShort(p, (short) 50);
+ }
+
+ // 52:02 ClassifierID
+ @Override
+ public short getClassifierID() {
+ return getShort((short) 52);
+ }
+
+ @Override
+ public void setClassifierID(short p) {
+ setShort(p, (short) 52);
+ }
+
+ // 54:01 Priority
+ @Override
+ public void setPriority(byte p) {
+ setByte(p, (short) 54);
+ }
+ @Override
+ public byte getPriority() {
+ return getByte((short) 54);
+ }
+
+ // 55:01 Activation State
+ @Override
+ public void setActivationState(byte s) {
+ setByte(s, (short) 55);
+ }
+ @Override
+ public byte getActivationState() {
+ return getByte((short) 55);
+ }
+
+ // 56:01 Action
+ @Override
+ public void setAction(byte a) {
+ setByte(a, (short) 56);
+ }
+ @Override
+ public byte getAction() {
+ return getByte((short) 56);
+ }
+
+
+
+ // baggage from IExtendedClassifier
+ // not used in IPv6 classifiers
+ @Override
+ public void setIPSourceMask(InetAddress a) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void setIPDestinationMask(InetAddress m) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public InetAddress getIPSourceMask() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public InetAddress getIPDestinationMask() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public short getDestinationPort() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void setDestinationPort(short p) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public short getSourcePort() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void setSourcePort(short p) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public short getProtocol() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void setProtocol(short p) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public byte getDSCPTOS() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void setDSCPTOS(byte v) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public byte getDSCPTOSMask() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void setDSCPTOSMask(byte v) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
setGateSpec(new GateSpec(dataBuffer));
break;
case ITrafficProfile.SNUM:
- setTrafficProfile(new BestEffortService(dataBuffer));
+ // TODO - Will need to support other traffic profiles
+ setTrafficProfile(new DOCSISServiceClassNameTrafficProfile(dataBuffer));
break;
case IClassifier.SNUM:
setClassifier(new Classifier(dataBuffer));
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
- final COPSDecisionMsg msg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, handle, decisionMap, null);
+ final COPSDecisionMsg msg = new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, handle, decisionMap, null, null);
// TODO - determine why this block has been commented out
// try {
IWorkerPool pool;
+ /**
+ * Constructor to use the port number contained within the PCMMProperties static object
+ */
protected AbstractPCMMServer() {
this(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
}
+ /**
+ * Constructor for starting the server to a pre-defined port number. When 0 is used, the server socket will
+ * assign one for you. To determine which port is being used, call getPort() after startServer() is called.
+ * @param port - the port number on which to start the server
+ */
protected AbstractPCMMServer(int port) {
// XXX - Assert.assertTrue(port >= 0 && port <= 65535);
this.port = port;
return;
try {
serverSocket = new ServerSocket(port);
+ port = serverSocket.getLocalPort();
logger.info("Server started and listening on port :" + port);
} catch (IOException e) {
logger.error(e.getMessage());
return null;
}
- /**
- * @return the serverSocket
- */
- public ServerSocket getServerSocket() {
- return serverSocket;
- }
-
- /**
- * @param serverSocket
- * the serverSocket to set
- */
- public void setServerSocket(ServerSocket serverSocket) {
- this.serverSocket = serverSocket;
- }
-
/**
* @return the port
*/
import org.pcmm.gates.impl.PCMMGateReq;
import org.pcmm.messages.impl.MessageFactory;
import org.pcmm.rcd.ICMTS;
+import org.umu.cops.COPSStateMan;
import org.umu.cops.prpep.COPSPepConnection;
import org.umu.cops.prpep.COPSPepDataProcess;
import org.umu.cops.prpep.COPSPepException;
import java.util.concurrent.Callable;
/**
- *
+ * This class starts a mock CMTS that can be used for testing.
*/
public class CMTS extends AbstractPCMMServer implements ICMTS {
+ /**
+ * Constructor for having the server port automatically assigned
+ * Call getPort() after startServer() is called to determine the port number of the server
+ */
public CMTS() {
- super();
+ this(0);
+ }
+
+ /**
+ * Constructor for starting the server to a pre-defined port number
+ * @param port - the port number on which to start the server.
+ */
+ public CMTS(final int port) {
+ super(port);
}
@Override
return new AbstractPCMMClientHandler(socket) {
- private String handle;
+ private COPSHandle handle;
public void run() {
try {
{
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));
};
}
- /* public */class PCMMCmtsConnection extends COPSPepConnection {
+ class PCMMCmtsConnection extends COPSPepConnection {
public PCMMCmtsConnection(final short clientType, final Socket sock) {
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);
}
-
- // public void addReqStateMgr(String hanlde, COPSPepReqStateMan r) {
- // // map < String(COPSHandle), COPSPepReqStateMan>;
- // getReqStateMans().put(hanlde, r);
- // }
}
- @SuppressWarnings("rawtypes")
class PCMMPSReqStateMan extends COPSPepReqStateMan {
- public PCMMPSReqStateMan(final short clientType, final String clientHandle) {
- super(clientType, clientHandle);
- _process = new CmtsDataProcessor();
-
+ public PCMMPSReqStateMan(final short clientType, final COPSHandle clientHandle) {
+ super(clientType, clientHandle, 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();
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
}
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
if (_process != null) {
// ** Apply decisions to the configuration
_process.setDecisions(this, removeDecs, installDecs, errorDecs);
- _status = ST_DECS;
+ _status = Status.ST_DECS;
if (_process.isFailReport(this)) {
// COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
_sender.sendFailReport(_process.getReportData(this));
// COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
_sender.sendSuccessReport(_process.getReportData(this));
}
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
}
}
}
- @SuppressWarnings("rawtypes")
- class CmtsDataProcessor extends COPSPepDataProcess {
+ class CmtsDataProcessor implements COPSPepDataProcess {
private Map<String, String> removeDecs;
private Map<String, String> installDecs;
setErrorDecs(new HashMap<String, String>());
}
- @SuppressWarnings("unchecked")
@Override
public void setDecisions(final COPSPepReqStateMan man, final Map<String, String> removeDecs,
final Map<String, String> installDecs, final Map<String, String> errorDecs) {
}
@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()) {
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???
}
@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
- public void notifyClosedConnection(COPSPepReqStateMan man, COPSError error) {
-
+ public void notifyClosedConnection(final COPSStateMan man, final COPSError error) {
+ // TODO Auto-generated method stub
}
@Override
- public void notifyNoKAliveReceived(COPSPepReqStateMan man) {
+ public void notifyNoKAliveReceived(final COPSStateMan man) {
// TODO Auto-generated method stub
-
}
@Override
- public void closeRequestState(COPSPepReqStateMan man) {
+ public void closeRequestState(final COPSStateMan man) {
// TODO Auto-generated method stub
-
}
@Override
- public void newRequestState(COPSPepReqStateMan man) {
+ public void newRequestState(final COPSPepReqStateMan man) {
// TODO Auto-generated method stub
-
}
public Map<String, String> getRemoveDecs() {
public void setStateManager(COPSPepReqStateMan stateManager) {
this.stateManager = stateManager;
}
+
}
}
if (getVersionInfo().getMajorVersionNB() >= 4) {
classifier = new ExtendedClassifier();
// eclassifier.setProtocol(IClassifier.Protocol.NONE);
- classifier.setProtocol(IClassifier.Protocol.TCP);
+// classifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
} else {
classifier = new Classifier();
- classifier.setProtocol(IClassifier.Protocol.TCP);
+// classifier.setProtocol(IClassifier.Protocol.TCP);
try {
InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID);
InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP);
--- /dev/null
+package org.umu.cops;
+
+import org.umu.cops.stack.COPSError;
+
+/**
+ * Defines the standard methods for implementors for processing COPS data.
+ */
+public interface COPSDataProcess {
+
+ /**
+ * Notifies a keep-alive timeout
+ * @param man The associated request state manager
+ */
+ void notifyNoKAliveReceived(COPSStateMan man);
+
+ /**
+ * Notifies that the connection has been closed
+ * @param man The associated request state manager
+ * @param error Reason
+ */
+ void notifyClosedConnection(COPSStateMan man, COPSError error);
+
+ /**
+ * Notifies that a request state has been closed
+ * @param man The associated request state manager
+ */
+ void closeRequestState(COPSStateMan man);
+
+}
--- /dev/null
+package org.umu.cops;
+
+import org.umu.cops.stack.COPSHandle;
+
+import java.net.Socket;
+
+/**
+ * Abstract COPS Message sender
+ */
+public abstract class COPSMsgSender {
+
+ /**
+ * COPS client-type that identifies the policy client
+ */
+ protected final short _clientType;
+
+ /**
+ * COPS client handle used to uniquely identify a particular
+ * PEP's request for a client-type
+ */
+ protected final COPSHandle _handle;
+
+ /**
+ * Socket connected to PEP
+ */
+ protected final Socket _sock;
+
+ public COPSMsgSender(final short clientType, final COPSHandle handle, final Socket sock) {
+ if (handle == null) throw new IllegalArgumentException("Client handle must not be null");
+ if (sock == null) throw new IllegalArgumentException("Socket must not be null");
+ this._clientType = clientType;
+ this._handle = handle;
+ this._sock = sock;
+ }
+
+ /**
+ * Gets the client handle
+ * @return Client's <tt>COPSHandle</tt>
+ */
+ public COPSHandle getClientHandle() {
+ return _handle;
+ }
+
+ /**
+ * Gets the client-type
+ * @return Client-type value
+ */
+ public short getClientType() {
+ return _clientType;
+ }
+
+}
--- /dev/null
+package org.umu.cops;
+
+import org.umu.cops.prpdp.COPSPdpException;
+import org.umu.cops.stack.COPSException;
+import org.umu.cops.stack.COPSHandle;
+import org.umu.cops.stack.COPSSyncStateMsg;
+
+import java.net.Socket;
+
+/**
+ * Abstract COPS state manager.
+ */
+public abstract class COPSStateMan {
+
+ // TODO - place these values into an enumeration
+ /**
+ * COPS client-type that identifies the policy client
+ */
+ protected final short _clientType;
+
+ /**
+ * COPS client handle used to uniquely identify a particular
+ * PEP's request for a client-type
+ */
+ protected final COPSHandle _handle;
+
+ /**
+ * Current state of the request being managed
+ */
+ protected transient Status _status;
+
+ /**
+ * Constructor
+ * @param clientType - the client type
+ * @param clientHandle - the unique handle to the client
+ */
+ public COPSStateMan(final short clientType, final COPSHandle clientHandle) {
+ this._clientType = clientType;
+ this._handle = clientHandle;
+ this._status = Status.ST_CREATE;
+ }
+
+ /**
+ * Gets the client handle
+ * @return Client's <tt>COPSHandle</tt>
+ */
+ public COPSHandle getClientHandle() {
+ return _handle;
+ }
+
+ /**
+ * Gets the client-type
+ * @return Client-type value
+ */
+ public short getClientType() {
+ return _clientType;
+ }
+
+ /**
+ * Gets the status of the request
+ * @return Request state value
+ */
+ public Status getStatus() {
+ return _status;
+ }
+
+ /**
+ * Called when COPS sync is completed
+ * @param repMsg COPS sync message
+ * @throws COPSPdpException
+ */
+ public void processSyncComplete(final COPSSyncStateMsg repMsg) throws COPSException {
+ _status = Status.ST_SYNCALL;
+ // TODO - maybe we should notifySyncComplete ...
+ }
+
+ /**
+ * Initializes a new request state over a socket
+ * @param sock Socket to the PEP
+ * @throws COPSPdpException
+ */
+ protected abstract void initRequestState(final Socket sock) throws COPSException;
+
+ /**
+ * The different state manager statuses
+ */
+ public enum Status {
+ NA,
+ ST_CREATE, // Request State created
+ ST_INIT, // Request received
+ ST_DECS, // Decisions sent
+ ST_REPORT, // Report received
+ ST_FINAL, // Request state finalized
+ ST_NEW, // New request state solicited
+ ST_DEL, // Delete request state solicited
+ ST_SYNC, // SYNC request sent
+ ST_SYNCALL, // SYNC completed
+ ST_CCONN, // Close connection received
+ ST_NOKA, // Keep-alive timeout
+ ST_ACCT, // Accounting timeout
+ }
+
+}
\r
package org.umu.cops.ospdp;\r
\r
+import org.umu.cops.stack.COPSException;\r
+\r
/**\r
* COPS PEP Exception\r
*\r
* @version COPSPepException.java, v 2.00 2004\r
*\r
*/\r
-public class COPSPdpException extends Exception {\r
-\r
- private int rc;\r
- final static int GENERAL_ERROR = 0x00000001;\r
+public class COPSPdpException extends COPSException {\r
\r
/**\r
* Creates a <tt>COPSPdpException</tt> with the given message.\r
- * @param msg Exception message\r
+ * @param msg Exception message\r
*/\r
public COPSPdpException(String msg) {\r
super(msg);\r
- rc=0;\r
}\r
\r
/**\r
* Creates a <tt>COPSPdpException</tt> with the given message and return code.\r
- * @param msg Exception message\r
- * @param retCode Return code\r
+ * @param msg Exception message\r
+ * @param retCode Return code\r
*/\r
public COPSPdpException(String msg, int retCode) {\r
- super(msg);\r
- rc = retCode;\r
+ super(msg, retCode);\r
}\r
\r
/**\r
- * Gets the return code of the exception\r
- * @return Exception's return code\r
+ * Creates a <tt>COPSPdpException</tt> with the given message and throwable.\r
+ * @param msg Exception message\r
+ * @param t the Throwable\r
*/\r
- public int returnCode() {\r
- return rc;\r
+ public COPSPdpException(String msg, Throwable t) {\r
+ super(msg, t);\r
}\r
\r
}\r
* Gets a COPS message from the socket and processes it
* @param conn Socket connected to the PEP
*/
- private void processMessage(Socket conn) throws COPSPdpException, COPSException, IOException {
- COPSMsg msg = COPSTransceiver.receiveMsg(conn);
+ private void processMessage(final Socket conn) throws COPSException, IOException {
+ final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
handleClientCloseMsg(conn, msg);
// Delete clientHandler
if (_managerMap.remove(cMsg.getClientHandle().getId().str()) == null) {
- // COPSDebug.out(getClass().getName(),"Missing for ClientHandle " +
- // cMsg.getClientHandle().getId().getData());
+ logger.warn("Missing state manager for for ClientHandle" + cMsg.getClientHandle().getId().str());
}
final COPSPdpOSReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
* @param msg a COPSMsg
*
*/
- private void handleRequestMsg(Socket conn, COPSMsg msg) throws COPSPdpException {
+ private void handleRequestMsg(final Socket conn, final COPSMsg msg) throws COPSException {
final COPSReqMsg reqMsg = (COPSReqMsg) msg;
final COPSHeader header = reqMsg.getHeader();
final short cType = header.getClientType();
final COPSPdpOSReqStateMan man;
if (_managerMap.get(reqMsg.getClientHandle().getId().str()) == null) {
- man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle().getId().str());
- _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
- man.setDataProcess(_process);
+ man = new COPSPdpOSReqStateMan(cType, reqMsg.getClientHandle(), _process);
+ _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
man.initRequestState(_sock);
} else {
man = _managerMap.get(reqMsg.getClientHandle().getId().str());
* @param msg a COPSMsg
*
*/
- private void handleSyncComplete(Socket conn, COPSMsg msg) throws COPSPdpException {
+ private void handleSyncComplete(final Socket conn, final COPSMsg msg) throws COPSException {
final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
// Support
/**
* Requests a COPS sync from the PEP
- * @throws COPSException
* @throws COPSPdpException
*/
- protected void syncAllRequestState() throws COPSException, COPSPdpException {
+ protected void syncAllRequestState() throws COPSException {
for (final COPSPdpOSReqStateMan man : _managerMap.values()) {
man.syncRequestState();
}
package org.umu.cops.ospdp;
+import org.umu.cops.COPSDataProcess;
import org.umu.cops.stack.COPSClientSI;
-import org.umu.cops.stack.COPSError;
import java.util.Vector;
/**
* Abstract class for implementing policy data processing classes for outsourcing PDPs.
*/
-public interface COPSPdpOSDataProcess {
+public interface COPSPdpOSDataProcess extends COPSDataProcess {
+
/**
* Gets the policies to be uninstalled
* @param man The associated request state manager
* @return A <tt>Vector</tt> holding the policies to be uninstalled
*/
- public Vector getRemovePolicy(COPSPdpOSReqStateMan man);
+ Vector getRemovePolicy(COPSPdpOSReqStateMan man);
+
/**
* Gets the policies to be installed
* @param man The associated request state manager
* @return A <tt>Vector</tt> holding the policies to be uninstalled
*/
- public Vector getInstallPolicy(COPSPdpOSReqStateMan man);
+ Vector getInstallPolicy(COPSPdpOSReqStateMan man);
+
/**
* Makes a decision from the supplied request data
* @param man The associated request state manager
* @param reqSIs Client specific data suppplied in the COPS request
*/
- public void setClientData(COPSPdpOSReqStateMan man, COPSClientSI... reqSIs);
+ void setClientData(COPSPdpOSReqStateMan man, COPSClientSI... reqSIs);
+
/**
* Builds a failure report
* @param man The associated request state manager
* @param reportSIs Report data
*/
- public void failReport (COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+ void failReport(COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+
/**
* Builds a success report
* @param man The associated request state manager
* @param reportSIs Report data
*/
- public void successReport (COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+ void successReport(COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
+
/**
* Builds an accounting report
* @param man The associated request state manager
* @param reportSIs Report data
*/
- public void acctReport (COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
- /**
- * Notifies that no accounting report has been received
- * @param man The associated request state manager
- */
- abstract void notifyNoAcctReport (COPSPdpOSReqStateMan man);
+ void acctReport(COPSPdpOSReqStateMan man, COPSClientSI... reportSIs);
/**
- * Notifies a keep-alive timeout
+ * Notifies that no accounting report has been received
* @param man The associated request state manager
*/
- abstract void notifyNoKAliveReceived (COPSPdpOSReqStateMan man);
-
- /**
- * Notifies that the connection has been closed
- * @param man The associated request state manager
- * @param error Reason
- */
- abstract void notifyClosedConnection (COPSPdpOSReqStateMan man, COPSError error);
+ void notifyNoAcctReport(COPSPdpOSReqStateMan man);
/**
* Notifies that a request state has been deleted
* @param man The associated request state manager
*/
- abstract void notifyDeleteRequestState (COPSPdpOSReqStateMan man);
-
- /**
- * Notifies that a request state has been closed
- * @param man The associated request state manager
- */
- abstract void closeRequestState(COPSPdpOSReqStateMan man);
+ void notifyDeleteRequestState(COPSPdpOSReqStateMan man);
}
package org.umu.cops.ospdp;
+import org.umu.cops.prpdp.COPSPdpMsgSender;
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.COPSHeader.Flag;
import java.io.IOException;
*
* TODO - change all references of Vector to List<>
*/
-public class COPSPdpOSMsgSender {
- /**
- * Socket connected to PEP
- */
- protected final Socket _sock;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected final short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected final COPSHandle _handle;
+public class COPSPdpOSMsgSender extends COPSPdpMsgSender {
/**
* Creates a COPSPepMsgSender
* @param clientHandle Client handle
* @param sock Socket to the PEP
*/
- public COPSPdpOSMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
- // COPS Handle
- _handle = clientHandle;
- _clientType = clientType;
-
- _sock = sock;
- }
-
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public short getClientType() {
- return _clientType;
+ public COPSPdpOSMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
+ super(clientType, clientHandle, sock);
}
/**
}
// Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(1, flag, getClientType(),
- new COPSHandle(getClientHandle().getId()), decisions, null);
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(1, flag, getClientType(), _handle, decisions,
+ null, null);
//** Send decision
//**
}
}
- /**
- * Sends a message asking that the request state be deleted
- * @throws COPSPdpException
- */
- public void sendDeleteRequestState() throws COPSPdpException {
- final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE));
- final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
- decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
-
- // Common Header with the same ClientType as the request (default UNSOLICITED)
- // Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
- decisionMap, null);
-
- try {
- decisionMsg.writeData(_sock);
- } catch (IOException e) {
- throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
- }
- }
-
- /**
- * Method sendOpenNewRequestState
- *
- * @throws COPSPdpException
- *
- */
- //FIXME: Unused?
- public void sendOpenNewRequestState() throws COPSPdpException {
- /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
- * <Client Handle>
- * *(<Decision>)
- * [<Integrity>]
- * <Decision> ::= <Context>
- * <Decision: Flags>
- * <Decision: Flags> ::= Install Request-State
- *
- */
-
- final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE));
- final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
- decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
-
- // Common Header with the same ClientType as the request (default UNSOLICITED)
- // Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
- decisionMap, null);
-
- try {
- decisionMsg.writeData(_sock);
- } catch (IOException e) {
- throw new COPSPdpException("Failed to send the open new request state, reason: " + e.getMessage());
- }
- }
-
- /**
- * Sends a message asking for a COPS sync operation
- * @throws COPSPdpException
- */
- public void sendSyncRequestState() throws COPSPdpException {
- /* <Synchronize State Request> ::= <Common Header>
- * [<Client Handle>]
- * [<Integrity>]
- */
-
- // Common Header with the same ClientType as the request
- // Client Handle with the same clientHandle as the request
- final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, new COPSHandle(_handle.getId()), null);
- try {
- msg.writeData(_sock);
- } catch (IOException e) {
- throw new COPSPdpException("Failed to send the sync state request, reason: " + e.getMessage());
- }
- }
-
}
package org.umu.cops.ospdp;
+import org.umu.cops.COPSStateMan;
import org.umu.cops.stack.*;
import java.net.Socket;
/**
* State manager class for outsourcing requests, at the PDP side.
*/
-public class COPSPdpOSReqStateMan {
- /**
- * Request State created
- */
- public final static short ST_CREATE = 1;
- /**
- * Request received
- */
- public final static short ST_INIT = 2;
- /**
- * Decisions sent
- */
- public final static short ST_DECS = 3;
- /**
- * Report received
- */
- public final static short ST_REPORT = 4;
- /**
- * Request state finalized
- */
- public final static short ST_FINAL = 5;
- /**
- * New request state solicited
- */
- public final static short ST_NEW = 6;
- /**
- * Delete request state solicited
- */
- public final static short ST_DEL = 7;
- /**
- * SYNC request sent
- */
- public final static short ST_SYNC = 8;
- /**
- * SYNC completed
- */
- public final static short ST_SYNCALL = 9;
- /**
- * Close connection received
- */
- public final static short ST_CCONN = 10;
- /**
- * Keep-alive timeout
- */
- public final static short ST_NOKA = 11;
- /**
- * Accounting timeout
- */
- public final static short ST_ACCT = 12;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
+public class COPSPdpOSReqStateMan extends COPSStateMan {
/**
* Object for performing policy data processing
*/
- protected COPSPdpOSDataProcess _process;
-
- /**
- * Current state of the request being managed
- */
- protected short _status;
+ private final COPSPdpOSDataProcess _process;
/** COPS message transceiver used to send COPS messages */
- protected COPSPdpOSMsgSender _sender;
+ private transient COPSPdpOSMsgSender _sender;
/**
* Creates a request state manager
* @param clientType Client-type
* @param clientHandle Client handle
*/
- public COPSPdpOSReqStateMan(final short clientType, final String clientHandle) {
- _handle = new COPSHandle(new COPSData(clientHandle));
- _clientType = clientType;
- _status = ST_CREATE;
- }
-
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public int getClientType() {
- return _clientType;
- }
-
- /**
- * Gets the status of the request
- * @return Request state value
- */
- public short getStatus() {
- return _status;
+ // TODO - consider sending in the COPSHandle object instead
+ public COPSPdpOSReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPdpOSDataProcess process) {
+ super(clientType, clientHandle);
+ this._process = process;
}
- /**
- * Gets the policy data processing object
- * @return Policy data processing object
- */
- public COPSPdpOSDataProcess getDataProcess() {
- return _process;
- }
-
- /**
- * Sets the policy data processing object
- * @param process Policy data processing object
- */
- public void setDataProcess(COPSPdpOSDataProcess process) {
- _process = process;
- }
-
- /**
- * Called when COPS sync is completed
- * @param repMsg COPS sync message
- * @throws COPSPdpException
- */
- protected void processSyncComplete(COPSSyncStateMsg repMsg)
- throws COPSPdpException {
-
- _status = ST_SYNCALL;
-
- // maybe we should notifySyncComplete ...
- }
-
- /**
- * Initializes a new request state over a socket
- * @param sock Socket to the PEP
- * @throws COPSPdpException
- */
- protected void initRequestState(Socket sock)
- throws COPSPdpException {
+ @Override
+ protected void initRequestState(final Socket sock) throws COPSException {
// Inits an object for sending COPS messages to the PDP
_sender = new COPSPdpOSMsgSender(_clientType, _handle, sock);
// Initial state
- _status = ST_INIT;
+ _status = Status.ST_INIT;
}
/**
* Processes a COPS request
* @param msg COPS request received from the PEP
- * @throws COPSPdpException
+ * @throws COPSException
*/
- protected void processRequest(COPSReqMsg msg) throws COPSPdpException {
+ protected void processRequest(COPSReqMsg msg) throws COPSException {
//** Here we must retrieve a decision depending on the
//** supplied ClientSIs
/*Vector removeDecs = new Vector();
//** We create a SOLICITED decision
//**
_sender.sendSolicitedDecision(removeDecs, installDecs);
- _status = ST_DECS;
+ _status = Status.ST_DECS;
}
/**
//** the report received
switch (rtypemsg.getReportType()) {
case SUCCESS:
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
_process.successReport(this, msg.getClientSI());
break;
case FAILURE:
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
_process.failReport(this, msg.getClientSI());
break;
case ACCOUNTING:
- _status = ST_ACCT;
+ _status = Status.ST_ACCT;
_process.acctReport(this, msg.getClientSI());
break;
}
* @param error Reason
* @throws COPSPdpException
*/
- protected void processClosedConnection(COPSError error)
- throws COPSPdpException {
+ protected void processClosedConnection(final COPSError error) throws COPSPdpException {
if (_process != null)
_process.notifyClosedConnection(this, error);
- _status = ST_CCONN;
+ _status = Status.ST_CCONN;
}
/**
* Called when no keep-alive is received
* @throws COPSPdpException
*/
- protected void processNoKAConnection()
- throws COPSPdpException {
+ protected void processNoKAConnection() throws COPSPdpException {
if (_process != null)
_process.notifyNoKAliveReceived(this);
- _status = ST_NOKA;
+ _status = Status.ST_NOKA;
}
/**
* Deletes the request state
* @throws COPSPdpException
*/
- protected void finalizeRequestState()
- throws COPSPdpException {
+ protected void finalizeRequestState() throws COPSException {
_sender.sendDeleteRequestState();
- _status = ST_FINAL;
+ _status = Status.ST_FINAL;
}
/**
* Asks for a COPS sync
* @throws COPSPdpException
*/
- protected void syncRequestState()
- throws COPSPdpException {
+ protected void syncRequestState() throws COPSException {
_sender.sendSyncRequestState();
- _status = ST_SYNC;
+ _status = Status.ST_SYNC;
}
/**
* Opens a new request state
* @throws COPSPdpException
*/
- protected void openNewRequestState()//FIXME: unused?
- throws COPSPdpException {
+ protected void openNewRequestState() throws COPSException {
_sender.sendOpenNewRequestState();
- _status = ST_NEW;
+ _status = Status.ST_NEW;
}
/**
* @param dMsg <tt>COPSDeleteMsg</tt> received from the PEP
* @throws COPSPdpException
*/
- protected void processDeleteRequestState(COPSDeleteMsg dMsg)
- throws COPSPdpException {
+ protected void processDeleteRequestState(final COPSDeleteMsg dMsg) throws COPSPdpException {
if (_process != null)
_process.closeRequestState(this);
- _status = ST_DEL;
+ _status = Status.ST_DEL;
}
}
\r
package org.umu.cops.ospep;\r
\r
+import org.umu.cops.stack.COPSException;\r
+\r
/**\r
* COPS PEP Exception\r
*\r
* @version COPSPepException.java, v 2.00 2004\r
*\r
*/\r
-public class COPSPepException extends Exception {\r
-\r
- private int rc;\r
- final static int GENERAL_ERROR = 0x00000001;\r
-\r
- /**\r
- * Creates a <tt>COPSPdpException</tt> with the given message.\r
- * @param msg Exception message\r
- */\r
+public class COPSPepException extends COPSException {\r
\r
- public COPSPepException(String msg) {\r
- super(msg);\r
- rc=0;\r
+ public COPSPepException(String s) {\r
+ super(s);\r
}\r
\r
- /**\r
- * Creates a <tt>COPSPdpException</tt> with the given message and return code.\r
- * @param msg Exception message\r
- * @param retCode Return code\r
- */\r
public COPSPepException(String msg, int retCode) {\r
- super(msg);\r
- rc = retCode;\r
+ super(msg, retCode);\r
}\r
\r
- /**\r
- * Returns the return code of the exception\r
- *\r
- * @return Exception's return code\r
- *\r
- */\r
- public int returnCode() {\r
- return rc;\r
+ public COPSPepException(String msg, Throwable t) {\r
+ super(msg, t);\r
}\r
\r
}\r
* @throws COPSException
* @throws IOException
*/
- protected void processMessage(Socket conn) throws COPSPepException, COPSException, IOException {
+ protected void processMessage(Socket conn) throws COPSException, IOException {
COPSMsg msg = COPSTransceiver.receiveMsg(conn);
if (msg.getHeader().getOpCode().equals(OPCode.CC)) {
* @param msg a COPSMsg
*
*/
- private void handleDecisionMsg(/*OJO Socket conn, */COPSMsg msg) throws COPSPepException {
- COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
- COPSHandle handle = dMsg.getClientHandle();
- COPSPepOSReqStateMan manager = _managerMap.get(handle.getId().str());
+ private void handleDecisionMsg(final COPSMsg msg) throws COPSException {
+ final COPSDecisionMsg dMsg = (COPSDecisionMsg) msg;
+ final COPSHandle handle = dMsg.getClientHandle();
+ final COPSPepOSReqStateMan manager = _managerMap.get(handle.getId().str());
manager.processDecision(dMsg);
}
* @param msg a COPSMsg
*
*/
- private void handleSyncStateReqMsg(Socket conn, COPSMsg msg) throws COPSPepException {
- COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
+ private void handleSyncStateReqMsg(final Socket conn, final COPSMsg msg) throws COPSException {
+ final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
// COPSHandle handle = cMsg.getClientHandle();
// COPSHeader header = cMsg.getHeader();
if (cMsg.getIntegrity() != null)
logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
- COPSPepOSReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
+ final COPSPepOSReqStateMan manager = _managerMap.get(cMsg.getClientHandle().getId().str());
if (manager == null)
logger.warn("Unable to find state manager with ID - " + cMsg.getClientHandle().getId().str());
* @param clientSIs Client data from the outsourcing event
* @return The newly created request state manager
* @throws COPSException
- * @throws COPSPepException
*/
protected COPSPepOSReqStateMan addRequestState(final String clientHandle, final COPSPepOSDataProcess process,
- final List<COPSClientSI> clientSIs)
- throws COPSException, COPSPepException {
- COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType, clientHandle);
+ final List<COPSClientSI> clientSIs) throws COPSException {
+ final COPSPepOSReqStateMan manager = new COPSPepOSReqStateMan(_clientType,
+ new COPSHandle(new COPSData(clientHandle)), process, clientSIs);
if (_managerMap.get(clientHandle) != null)
throw new COPSPepException("Duplicate Handle, rejecting " + clientHandle);
-
- manager.setDataProcess(process);
- manager.setClientSI(clientSIs);
_managerMap.put(clientHandle, manager);
manager.initRequestState(_sock);
return manager;
/**
* Deletes a request state
* @param manager Request state manager
- * @throws COPSException
* @throws COPSPepException
*/
- protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException, COPSPepException {
+ protected void deleteRequestState(COPSPepOSReqStateMan manager) throws COPSException {
manager.finalizeRequestState();
}
-package org.umu.cops.ospep;\r
-\r
-import java.util.Vector;\r
-\r
-import org.umu.cops.stack.COPSDecisionMsg;\r
-import org.umu.cops.stack.COPSError;\r
-\r
-/**\r
- * Abstract class for implementing policy data processing classes for outsourcing PEPs.\r
- */\r
-public abstract class COPSPepOSDataProcess {\r
- /**\r
- * Applies the decisions from the PDP\r
- * @param man The request state manager\r
- * @param dMsg The decisions message\r
- * @return <tt>true</tt> if failed (reports indicate failure), <tt>false</tt> otherwise\r
- */\r
- public abstract boolean setDecisions(COPSPepOSReqStateMan man, COPSDecisionMsg dMsg);\r
-\r
- /**\r
- * Gets the report data\r
- * @param man The request state manager\r
- * @return A <tt>Vector</tt> holding the report data\r
- */\r
- public abstract Vector getReportData(COPSPepOSReqStateMan man);\r
-\r
- /**\r
- * Gets the supplied client data\r
- * @param man The request state manager\r
- * @return A <tt>Vector</tt> holding the client data\r
- */\r
- public abstract Vector getClientData(COPSPepOSReqStateMan man);\r
-\r
- /**\r
- * Gets the account data\r
- * @param man The request state manager\r
- * @return A <tt>Vector</tt> holding the account data\r
- */\r
- public abstract Vector getAcctData(COPSPepOSReqStateMan man);\r
-\r
- /**\r
- * Called when the connection is closed\r
- * @param man The request state manager\r
- * @param error Reason\r
- */\r
- public abstract void notifyClosedConnection (COPSPepOSReqStateMan man, COPSError error);\r
-\r
- /**\r
- * Called when the keep-alive message is not received\r
- * @param man The request state manager\r
- */\r
- public abstract void notifyNoKAliveReceived (COPSPepOSReqStateMan man);\r
-\r
- /**\r
- * Process a PDP request to close a Request State\r
- * @param man The request state manager\r
- */\r
- public abstract void closeRequestState(COPSPepOSReqStateMan man);\r
-}\r
+package org.umu.cops.ospep;
+
+import org.umu.cops.COPSDataProcess;
+import org.umu.cops.stack.COPSDecisionMsg;
+
+import java.util.Vector;
+
+/**
+ * Abstract class for implementing policy data processing classes for outsourcing PEPs.
+ */
+public interface COPSPepOSDataProcess extends COPSDataProcess {
+ /**
+ * Applies the decisions from the PDP
+ * @param man The request state manager
+ * @param dMsg The decisions message
+ * @return <tt>true</tt> if failed (reports indicate failure), <tt>false</tt> otherwise
+ */
+ boolean setDecisions(COPSPepOSReqStateMan man, COPSDecisionMsg dMsg);
+
+ /**
+ * Gets the report data
+ * @param man The request state manager
+ * @return A <tt>Vector</tt> holding the report data
+ */
+ Vector getReportData(COPSPepOSReqStateMan man);
+
+ /**
+ * Gets the supplied client data
+ * @param man The request state manager
+ * @return A <tt>Vector</tt> holding the client data
+ */
+ Vector getClientData(COPSPepOSReqStateMan man);
+
+ /**
+ * Gets the account data
+ * @param man The request state manager
+ * @return A <tt>Vector</tt> holding the account data
+ */
+ Vector getAcctData(COPSPepOSReqStateMan man);
+
+}
package org.umu.cops.ospep;
+import org.umu.cops.prpep.COPSPepMsgSender;
import org.umu.cops.stack.*;
import org.umu.cops.stack.COPSContext.RType;
-import org.umu.cops.stack.COPSReason.ReasonCode;
import org.umu.cops.stack.COPSReportType.ReportType;
import java.io.IOException;
/**
* COPS message transceiver class for outsourcing connections at the PEP side.
*/
-public class COPSPepOSMsgSender {
- /**
- * Socket connection to PDP
- */
- protected Socket _sock;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
+public class COPSPepOSMsgSender extends COPSPepMsgSender {
/**
* Creates a COPSPepMsgSender
* @param clientHandle Client handle
* @param sock Socket connected to the PDP
*/
- public COPSPepOSMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
- // COPS Handle
- _handle = clientHandle;
- _clientType = clientType;
-
- _sock = sock;
- }
-
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public int getClientType() {
- return _clientType;
+ public COPSPepOSMsgSender(final short clientType, final COPSHandle clientHandle, final Socket sock) {
+ super(clientType, clientHandle, sock);
}
/**
}
}
- /**
- * Sends a sync-complete message to the PDP. This indicates the
- * end of a synchronization requested by the PDP.
- * @throws COPSPepException
- */
- public void sendSyncComplete() throws COPSPepException {
- // Common Header with the same ClientType as the request
- // Client Handle with the same clientHandle as the request
- final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
- try {
- msg.writeData(_sock);
- } catch (IOException e) {
- throw new COPSPepException("Failed to send the sync state request, reason: " + e.getMessage());
- }
- }
-
- /**
- * Sends a delete request to the PDP.
- * When sent from the PEP this message indicates to the remote PDP that
- * the state identified by the client handle is no longer
- * available/relevant.
- * @throws COPSPepException
- */
- public void sendDeleteRequest() throws COPSPepException {
- // *** TODO: use real reason codes
- COPSReason reason = new COPSReason(ReasonCode.UNSPECIFIED, ReasonCode.NA);
-
- final COPSDeleteMsg msg = new COPSDeleteMsg(_clientType, _handle, reason, null);
- try {
- msg.writeData(_sock);
- } catch (IOException e) {
- throw new COPSPepException("Failed to send the delete request, reason: " + e.getMessage());
- }
- }
-
}
package org.umu.cops.ospep;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
import org.umu.cops.stack.*;
import java.net.Socket;
-import java.util.List;
-import java.util.Set;
-import java.util.Vector;
+import java.util.*;
/**
* State manager class for outsourcing requests, at the PEP side.
*/
-public class COPSPepOSReqStateMan {
- /**
- * Request State created
- */
- public final static short ST_CREATE = 1;
- /**
- * Request sent
- */
- public final static short ST_INIT = 2;
- /**
- * Decisions received
- */
- public final static short ST_DECS = 3;
- /**
- * Report sent
- */
- public final static short ST_REPORT = 4;
- /**
- * Request State finalized
- */
- public final static short ST_FINAL = 5;
- /**
- * New Request State solicited
- */
- public final static short ST_NEW = 6;
- /**
- * Delete Request State solicited
- */
- public final static short ST_DEL = 7;
- /**
- * SYNC request received
- */
- public final static short ST_SYNC = 8;
- /**
- * Sync completed
- */
- public final static short ST_SYNCALL = 9;
- /**
- * Close connection received
- */
- public final static short ST_CCONN = 10;
- /**
- * Keep-alive timeout
- */
- public final static short ST_NOKA = 11;
- /**
- * Accounting timeout
- */
- public final static short ST_ACCT = 12;
+public class COPSPepOSReqStateMan extends COPSStateMan {
- /**
- * COPS client-type that identifies the policy client
- */
- protected short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
-
- /**
- Object for performing policy data processing
- */
- protected COPSPepOSDataProcess _process;
+ private final static Logger logger = LoggerFactory.getLogger(COPSPepOSReqStateMan.class);
/**
* ClientSI data from signaling.
protected final Set<COPSClientSI> _clientSIs;
/**
- * Current state of the request being managed
+ Object for performing policy data processing
*/
- protected short _status;
+ protected final COPSPepOSDataProcess _process;
/**
COPS message transceiver used to send COPS messages
*/
- protected COPSPepOSMsgSender _sender;
+ protected transient COPSPepOSMsgSender _sender;
/**
* Sync state
*/
- protected boolean _syncState;
+ protected transient boolean _syncState;
/**
* Creates a state request manager
* @param clientType Client-type
* @param clientHandle Client's <tt>COPSHandle</tt>
*/
- public COPSPepOSReqStateMan(final short clientType, final String clientHandle) {
- // COPS Handle
- _handle = new COPSHandle(new COPSData(clientHandle));
- _clientType = clientType;
+ public COPSPepOSReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepOSDataProcess process,
+ final Collection<COPSClientSI> clientSIs) {
+ super(clientType, clientHandle);
+ this._process = process;
+ this._clientSIs = new HashSet<>(clientSIs);
_syncState = true;
- _status = ST_CREATE;
- _clientSIs = null;
}
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Sets the client SI data.
- * @param someClientSIs Client SI data built by the event listener
- */
- public void setClientSI(final List<COPSClientSI> someClientSIs) {
- _clientSIs.addAll(someClientSIs);
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public int getClientType() {
- return _clientType;
- }
-
- /**
- * Gets the request status
- * @return Request status value
- */
- public short getStatus() {
- return _status;
- }
-
- /**
- * Gets the policy data processing object
- *
- * @return Policy data processing object
- *
- */
- public COPSPepOSDataProcess getDataProcess() {
- return _process;
- }
-
- /**
- * Sets the policy data processing object
- *
- * @param process Policy data processing object
- *
- */
- public void setDataProcess(COPSPepOSDataProcess process) {
- _process = process;
- }
-
- /**
- * Initializes a new request state over a socket
- * @param sock Socket to the PDP
- * @throws COPSPepException
- */
- protected void initRequestState(Socket sock) throws COPSPepException {
+ @Override
+ protected void initRequestState(final Socket sock) throws COPSException {
// Inits an object for sending COPS messages to the PDP
_sender = new COPSPepOSMsgSender(_clientType, _handle, sock);
_sender.sendRequest(_clientSIs);
// Initial state
- _status = ST_INIT;
+ _status = Status.ST_INIT;
}
/**
* Deletes the request state
* @throws COPSPepException
*/
- protected void finalizeRequestState() throws COPSPepException {
+ protected void finalizeRequestState() throws COPSException {
_sender.sendDeleteRequest();
- _status = ST_FINAL;
+ _status = Status.ST_FINAL;
}
/**
* @param dMsg Decision message from the PDP
* @throws COPSPepException
*/
- protected void processDecision(COPSDecisionMsg dMsg) throws COPSPepException {
- // COPSDebug.out(getClass().getName(), "ClientId:" + getClientHandle().getId().str());
-
- //Hashtable decisionsPerContext = dMsg.getDecisions();
-
+ protected void processDecision(final COPSDecisionMsg dMsg) throws COPSException {
//** Applies decisions to the configuration
//_process.setDecisions(this, removeDecs, installDecs, errorDecs);
// second param changed to dMsg so that the data processor
// can check the 'solicited' flag
- boolean isFailReport = _process.setDecisions(this, dMsg /*decisionsPerContext*/);
- _status = ST_DECS;
+ final boolean isFailReport = _process.setDecisions(this, dMsg);
+ _status = Status.ST_DECS;
if (isFailReport) {
- // COPSDebug.out(getClass().getName(),"Sending FAIL Report\n");
+ logger.info("Sending FAIL Report");
_sender.sendFailReport(_process.getReportData(this));
} else {
- // COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
+ logger.info("Sending SUCCESS Report");
_sender.sendSuccessReport(_process.getReportData(this));
}
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
if (!_syncState) {
_sender.sendSyncComplete();
_syncState = true;
- _status = ST_SYNCALL;
+ _status = Status.ST_SYNCALL;
}
}
* @param dMsg <tt>COPSDeleteMsg</tt> received from the PDP
* @throws COPSPepException
*/
- protected void processDeleteRequestState(COPSDecisionMsg dMsg) throws COPSPepException {
+ protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
if (_process != null)
_process.closeRequestState(this);
- _status = ST_DEL;
+ _status = Status.ST_DEL;
}
/**
* @throws COPSPepException
*
*/
- protected void processSyncStateRequest(COPSSyncStateMsg ssMsg) throws COPSPepException {
+ protected void processSyncStateRequest(final COPSSyncStateMsg ssMsg) throws COPSException {
_syncState = false;
// If an object exists for retrieving the PEP features,
// use it for retrieving them.
// Send the request
_sender.sendRequest(_clientSIs);
- _status = ST_SYNC;
+ _status = Status.ST_SYNC;
}
/**
* @param error Reason
* @throws COPSPepException
*/
- 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;
+ _status = Status.ST_CCONN;
}
/**
if (_process != null)
_process.notifyNoKAliveReceived(this);
- _status = ST_NOKA;
+ _status = Status.ST_NOKA;
}
/**
* @throws COPSPepException
*/
protected void processAcctReport() throws COPSPepException {
- Vector report = new Vector();
-
- if (_process != null)
- report = _process.getAcctData(this);
+ final List<COPSClientSI> report;
+ if (_process != null) report = new ArrayList<>(_process.getAcctData(this));
+ else report = new ArrayList<>();
_sender.sendAcctReport(report);
- _status = ST_ACCT;
+ _status = Status.ST_ACCT;
}
}
*/
public class COPSPdpAgent extends Thread {
- public final static Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
+ private static final Logger logger = LoggerFactory.getLogger(COPSPdpAgent.class);
/** Well-known port for COPS */
- public static final int WELL_KNOWN_PDP_PORT = 3288;
+ // public static final int WELL_KNOWN_PDP_PORT = 3288;
/** Default keep-alive timer value (secs) */
public static final short KA_TIMER_VALUE = 30;
/** Default accounting timer value (secs) */
public static final short ACCT_TIMER_VALUE = 0;
/**
- PDP host port
+ * PDP host port
*/
private int _serverPort;
/**
- Client-type of connecting PEP
+ * Client-type of connecting PEP
*/
private short _clientType;
/**
- Accounting timer (secs)
+ * Accounting timer (secs)
*/
private short _acctTimer;
/**
- Keep-alive timer (secs)
+ * Keep-alive timer (secs)
*/
private short _kaTimer;
/**
- Maps a PEP-ID to a connection
+ * The PEP ID
*/
- private final Map<String, COPSPdpConnection> _connectionMap;
+ protected transient COPSPepId _pepId;
+
+ /**
+ * Maps a PEP-ID to a connection
+ * TODO - Refactor COPSPdpConnection to extend PCMMPdpConnection. Until then, the value must remain an Object
+ */
+ protected Map<String, Object> _connectionMap;
// map < String(PEPID), COPSPdpConnection > ConnectionMap;
/**
private COPSPdpDataProcess _process;
/**
- * Creates a PDP Agent
- *
- * @param clientType COPS Client-type
- * @param process Object to perform policy data processing
+ * Holds all of the threads to manage by PEP ID
*/
- public COPSPdpAgent(final short clientType, final COPSPdpDataProcess process) {
- _serverPort = WELL_KNOWN_PDP_PORT;
- _kaTimer = KA_TIMER_VALUE;
- _acctTimer = ACCT_TIMER_VALUE;
-
- _clientType = clientType;
- _connectionMap = new ConcurrentHashMap<>();
- _process = process;
- }
+ protected final Map<String, Thread> threadMap;
/**
* Creates a PDP Agent
_clientType = clientType;
_connectionMap = new ConcurrentHashMap<>();
_process = process;
- }
-
- /**
- * Sets the keep-alive timer value
- * @param kaTimer Keep alive timer value (secs)
- */
- public void setKaTimer (short kaTimer) {
- _kaTimer = kaTimer;
- }
-
- /**
- * Sets the accounting timer value
- * @param acctTimer Accounting timer value (secs)
- */
- public void setAcctTimer (short acctTimer) {
- _acctTimer = acctTimer;
+ this.threadMap = new ConcurrentHashMap<>();
}
/**
* @throws IOException
*/
public void disconnect(final String pepID, final COPSError error) throws COPSException, IOException {
- final COPSPdpConnection pdpConn = _connectionMap.get(pepID);
+ final COPSPdpConnection pdpConn = (COPSPdpConnection)_connectionMap.get(pepID);
final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType, error, null, null);
closeMsg.writeData(pdpConn.getSocket());
pdpConn.close();
* @throws COPSException
* @throws COPSPdpException
*/
- public void sync (String pepID)
- throws COPSException, COPSPdpException {
-
- COPSPdpConnection pdpConn = _connectionMap.get(pepID);
+ public void sync(final String pepID) throws COPSException, COPSPdpException {
+ COPSPdpConnection pdpConn = (COPSPdpConnection) _connectionMap.get(pepID);
pdpConn.syncAllRequestState();
}
* Removes a PEP from the connection map
* @param pepID PEP-ID of the PEP to be removed
*/
- public void delete (String pepID) {
+ public void delete(final String pepID) {
_connectionMap.remove(pepID);
}
final ServerSocket serverSocket = new ServerSocket (_serverPort);
//Loop through for Incoming messages
-
// server infinite loop
while (true) {
-
// Wait for an incoming connection from a PEP
- Socket socket = serverSocket.accept();
+ final Socket socket = serverSocket.accept();
// COPSDebug.out(getClass().getName(),"New connection accepted " +
// socket.getInetAddress() +
// We're waiting for an OPN message
try {
final COPSMsg msg = COPSTransceiver.receiveMsg(socket);
+ logger.info("Message received - " + msg);
if (msg.getHeader().getOpCode().equals(OPCode.OPN)) {
handleClientOpenMsg(socket, msg);
} else {
- // COPSDebug.err(getClass().getName(), COPSDebug.ERROR_NOEXPECTEDMSG);
+ logger.error("Not an open message, closing socket");
try {
socket.close();
} catch (Exception ex) {
- logger.error("Error closing socket", ex);
+ logger.error("Unexpected exception closing socket", ex);
}
}
} catch (Exception e) { // COPSException, IOException
try {
socket.close();
} catch (Exception ex) {
- logger.error("Error closing socket", ex);
+ logger.error("Unexpected exception closing socket", ex);
}
}
}
}
/**
- * Handles a COPS client-open message
- * @param conn Socket to the PEP
- * @param msg <tt>COPSMsg</tt> holding the client-open message
- * @throws COPSException
- * @throws IOException
- */
- private void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
+ * Handles a COPS client-open message
+ * @param conn Socket to the PEP
+ * @param msg <tt>COPSMsg</tt> holding the client-open message
+ * @throws COPSException
+ * @throws IOException
+ * TODO - Refactor PCMMPdpAgent#handleClientOpenMsg() as it contains much of this same logic
+ */
+ protected void handleClientOpenMsg(final Socket conn, final COPSMsg msg) throws COPSException, IOException {
final COPSClientOpenMsg cMsg = (COPSClientOpenMsg) msg;
- final COPSPepId pepId = cMsg.getPepId();
+ _pepId = cMsg.getPepId();
// Validate Client Type
- if (msg.getHeader().getClientType() == _clientType) {
+ if (msg.getHeader().getClientType() != _clientType) {
// Unsupported client type
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
new COPSError(ErrorTypes.UNSUPPORTED_CLIENT_TYPE, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Error writing COPS data", unae);
+ logger.error("Unexpected exception writing data", unae);
}
throw new COPSException("Unsupported client type");
}
// PEPId is mandatory
- if (pepId == null) {
+ if (_pepId == null) {
// Mandatory COPS object missing
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
new COPSError(ErrorTypes.MANDATORY_OBJECT_MISSING, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Error writing close message", unae);
+ logger.error("Unexpected exception writing data", unae);
}
throw new COPSException("Mandatory COPS object missing (PEPId)");
}
// Support
- if ( (cMsg.getClientSI() != null) ||
- (cMsg.getPdpAddress() != null) ||
- (cMsg.getIntegrity() != null)) {
-
+ if ( (cMsg.getClientSI() != null) || (cMsg.getPdpAddress() != null) || (cMsg.getIntegrity() != null)) {
// Unsupported objects
- final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(msg.getHeader().getClientType(),
+ final COPSClientCloseMsg closeMsg = new COPSClientCloseMsg(_clientType,
new COPSError(ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA), null, null);
try {
closeMsg.writeData(conn);
} catch (IOException unae) {
- logger.error("Error writing close message", unae);
+ logger.error("Exception writing data", unae);
}
throw new COPSException("Unsupported objects (ClientSI, PdpAddress, Integrity)");
}
// Connection accepted
- final COPSKATimer katimer = new COPSKATimer(_kaTimer);
final COPSClientAcceptMsg acceptMsg;
- if (_acctTimer != 0) acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer, null, null);
- else acceptMsg = new COPSClientAcceptMsg(msg.getHeader().getClientType(), katimer,
+ if (_acctTimer != 0)
+ acceptMsg = new COPSClientAcceptMsg(_clientType, new COPSKATimer(_kaTimer),
new COPSAcctTimer(_acctTimer), null);
+ else
+ acceptMsg = new COPSClientAcceptMsg(_clientType, new COPSKATimer(_kaTimer),null, null);
acceptMsg.writeData(conn);
- final COPSPdpConnection pdpConn = new COPSPdpConnection(pepId,conn,_process);
+ final COPSPdpConnection pdpConn = new COPSPdpConnection(_pepId, conn, _process);
pdpConn.setKaTimer(_kaTimer);
if (_acctTimer != 0) pdpConn.setAccTimer(_acctTimer);
new Thread(pdpConn).start();
- _connectionMap.put(pepId.getData().str(),pdpConn);
+ _connectionMap.put(_pepId.getData().str(), pdpConn);
}
}
* Gets a COPS message from the socket and processes it
* @param conn Socket connected to the PEP
*/
- private void processMessage(final Socket conn) throws COPSPdpException, COPSException, IOException {
+ private void processMessage(final Socket conn) throws COPSException, IOException {
final COPSMsg msg = COPSTransceiver.receiveMsg(conn);
switch (msg.getHeader().getOpCode()) {
case CC:
COPSPdpReqStateMan man = _managerMap.get(reqMsg.getClientHandle().getId().str());
if (man == null) {
- man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle().getId().str());
- _managerMap.put(reqMsg.getClientHandle().getId().str(),man);
- man.setDataProcess(_process);
+ man = new COPSPdpReqStateMan(cType, reqMsg.getClientHandle(), _process);
+ _managerMap.put(reqMsg.getClientHandle().getId().str(), man);
man.initRequestState(_sock);
// COPSDebug.out(getClass().getName(),"createHandler called, clientType=" +
* @param msg a COPSMsg
*
*/
- private void handleSyncComplete(Socket conn, COPSMsg msg)
- throws COPSPdpException {
- COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
- // COPSHandle handle = cMsg.getClientHandle();
- // COPSHeader header = cMsg.getHeader();
+ private void handleSyncComplete(final Socket conn, final COPSMsg msg) throws COPSException {
+ final COPSSyncStateMsg cMsg = (COPSSyncStateMsg) msg;
// Support
if (cMsg.getIntegrity() != null) {
logger.warn("Unsupported objects (Integrity) to connection " + conn.getInetAddress());
}
- COPSPdpReqStateMan man = (COPSPdpReqStateMan) _managerMap.get(cMsg.getClientHandle().getId().str());
+ final COPSPdpReqStateMan man = _managerMap.get(cMsg.getClientHandle().getId().str());
if (man == null) {
logger.warn("No state manager found with ID - " + cMsg.getClientHandle().getId().str());
} else {
* @throws COPSException
* @throws COPSPdpException
*/
- protected void syncAllRequestState() throws COPSException, COPSPdpException {
+ protected void syncAllRequestState() throws COPSException {
for (final COPSPdpReqStateMan man : _managerMap.values()) {
man.syncRequestState();
}
package org.umu.cops.prpdp;
-import org.umu.cops.stack.COPSError;
+import org.umu.cops.COPSDataProcess;
import java.util.Hashtable;
import java.util.Map;
/**
* Abstract class for implementing policy data processing classes for provisioning PDPs.
*/
-public interface COPSPdpDataProcess {
+public interface COPSPdpDataProcess extends COPSDataProcess {
+
/**
* Gets the policies to be uninstalled
* @param man The associated request state manager
* @return A <tt>Vector</tt> holding the policies to be uninstalled
*/
- public Hashtable getRemovePolicy(COPSPdpReqStateMan man);
+ Hashtable getRemovePolicy(COPSPdpReqStateMan man);
+
/**
* Gets the policies to be installed
* @param man The associated request state manager
* @return A <tt>Vector</tt> holding the policies to be uninstalled
*/
- public Hashtable getInstallPolicy(COPSPdpReqStateMan man);
+ Hashtable getInstallPolicy(COPSPdpReqStateMan man);
+
/**
* Makes a decision from the supplied request data
* @param man The associated request state manager
* @param reqSIs Client specific data suppplied in the COPS request
*/
- public void setClientData(COPSPdpReqStateMan man, Map<String, String> reqSIs);
+ void setClientData(COPSPdpReqStateMan man, Map<String, String> reqSIs);
+
/**
* Builds a failure report
* @param man The associated request state manager
* @param reportSIs Report data
*/
- public void failReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+ void failReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+
/**
* Builds a success report
* @param man The associated request state manager
* @param reportSIs Report data
*/
- public void successReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+ void successReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
+
/**
* Builds an accounting report
* @param man The associated request state manager
* @param reportSIs Report data
*/
- public void acctReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
- /**
- * Notifies that no accounting report has been received
- * @param man The associated request state manager
- */
- public void notifyNoAcctReport (COPSPdpReqStateMan man);
+ void acctReport(COPSPdpReqStateMan man, Map<String, String> reportSIs);
/**
- * Notifies a keep-alive timeout
+ * Notifies that no accounting report has been received
* @param man The associated request state manager
*/
- public void notifyNoKAliveReceived (COPSPdpReqStateMan man);
-
- /**
- * Notifies that the connection has been closed
- * @param man The associated request state manager
- * @param error Reason
- */
- public void notifyClosedConnection (COPSPdpReqStateMan man, COPSError error);
+ void notifyNoAcctReport(COPSPdpReqStateMan man);
/**
* Notifies that a request state has been deleted
* @param man The associated request state manager
*/
- public void notifyDeleteRequestState (COPSPdpReqStateMan man);
+ void notifyDeleteRequestState(COPSPdpReqStateMan man);
- /**
- * Notifies that a request state has been closed
- * @param man The associated request state manager
- */
- public void closeRequestState(COPSPdpReqStateMan man);
}
-/*\r
- * Copyright (c) 2004 University of Murcia. All rights reserved.\r
- * --------------------------------------------------------------\r
- * For more information, please see <http://www.umu.euro6ix.org/>.\r
- */\r
-\r
-package org.umu.cops.prpdp;\r
-\r
-/**\r
- * Exception class for PDP errors\r
- *\r
- * @version COPSPdpException.java, v 2.00 2004\r
- *\r
- */\r
-\r
-public class COPSPdpException extends Exception {\r
-\r
- private int rc;\r
- final static int GENERAL_ERROR = 0x00000001;\r
-\r
- /**\r
- * Creates a <tt>COPSPdpException</tt> with the given message.\r
- * @param msg Exception message\r
- */\r
- public COPSPdpException(String msg) {\r
- super(msg);\r
- rc=0;\r
- }\r
-\r
- /**\r
- * Creates a <tt>COPSPdpException</tt> with the given message and return code.\r
- * @param msg Exception message\r
- * @param retCode Return code\r
- */\r
- public COPSPdpException(String msg, int retCode) {\r
- super(msg);\r
- rc = retCode;\r
- }\r
-\r
- /**\r
- * Gets the return code of the exception\r
- * @return Exception's return code\r
- */\r
- public int returnCode() {\r
- return rc;\r
- }\r
-\r
-}\r
+/*
+ * Copyright (c) 2004 University of Murcia. All rights reserved.
+ * --------------------------------------------------------------
+ * For more information, please see <http://www.umu.euro6ix.org/>.
+ */
+
+package org.umu.cops.prpdp;
+
+import org.umu.cops.stack.COPSException;
+
+/**
+ * Exception class for PDP errors
+ *
+ * @version COPSPdpException.java, v 2.00 2004
+ *
+ */
+
+public class COPSPdpException extends COPSException {
+
+ /**
+ * Creates a <tt>COPSPdpException</tt> with the given message.
+ * @param msg Exception message
+ */
+ public COPSPdpException(String msg) {
+ super(msg);
+ }
+
+ /**
+ * Creates a <tt>COPSPdpException</tt> with the given message and return code.
+ * @param msg Exception message
+ * @param retCode Return code
+ */
+ public COPSPdpException(String msg, int retCode) {
+ super(msg, retCode);
+ }
+
+ /**
+ * Creates a <tt>COPSPdpException</tt> with the given message and throwable.
+ * @param msg Exception message
+ * @param t the Throwable
+ */
+ public COPSPdpException(String msg, Throwable t) {
+ super(msg, t);
+ }
+
+}
package org.umu.cops.prpdp;
+import org.umu.cops.COPSMsgSender;
import org.umu.cops.stack.*;
import org.umu.cops.stack.COPSContext.RType;
import org.umu.cops.stack.COPSDecision.Command;
*
* TODO - Need to continue refactoring by removing all instances of Hashtable (change to Map<>)
*/
-public class COPSPdpMsgSender {
-
- /**
- * Socket connected to PEP
- */
- protected final Socket _sock;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected final short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected final COPSHandle _handle;
+public class COPSPdpMsgSender extends COPSMsgSender {
/**
* Creates a COPSPepMsgSender
* @param sock Socket to the PEP
*/
public COPSPdpMsgSender (final short clientType, final COPSHandle clientHandle, final Socket sock) {
- // COPS Handle
- _handle = clientHandle;
- _clientType = clientType;
-
- _sock = sock;
- }
-
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public short getClientType() {
- return _clientType;
+ super(clientType, clientHandle, sock);
}
/**
*/
public void sendDecision(final Map<String, String> removeDecs, Map<String, String> installDecs)
throws COPSPdpException {
- /* <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>
- *
- */
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
// Common Header with the same ClientType as the request
// Client Handle with the same clientHandle as the request
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
- decisionMap, null);
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, null);
//** Send the decision
- //**
try {
decisionMsg.writeData(_sock);
} catch (IOException e) {
*/
public void sendUnsolicitedDecision(final Map<String, String> removeDecs, final Map<String, String> installDecs)
throws COPSPdpException {
- //** Example of an UNSOLICITED decision
- //**
-
- /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
- * <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>
- *
- */
-
// Common Header with the same ClientType as the request
// Client Handle with the same clientHandle as the request
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
decisionMsg.add(intr);
/**/
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(getClientHandle().getId()),
- decisionMap, null);
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, null);
//** Send the decision
- //**
try {
decisionMsg.writeData(_sock);
} catch (IOException e) {
/**
* Sends a message asking that the request state be deleted
- * @throws COPSPdpException
+ * @throws COPSException
*/
- public void sendDeleteRequestState() throws COPSPdpException {
- /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
- * <Client Handle>
- * *(<Decision>)
- * [<Integrity>]
- * <Decision> ::= <Context>
- * <Decision: Flags>
- * <Decision: Flags> ::= Remove Request-State
- *
- */
-
- // Decisions
- // <Context>
- // <Decision: Flags>
- final COPSDecision dec = new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE);
+ public void sendDeleteRequestState() throws COPSException {
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(dec);
+ decisionSet.add(new COPSDecision(Command.REMOVE, DecisionFlag.REQSTATE));
decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), new COPSHandle(_handle.getId()),
- decisionMap, null);
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(getClientType(), _handle, decisionMap, null, null);
try {
decisionMsg.writeData(_sock);
} catch (IOException e) {
/**
* Sends a request asking that a new request state be created
- * @throws COPSPdpException
+ * @throws COPSException
*/
- public void sendOpenNewRequestState()
- throws COPSPdpException {
- /* <Decision Message> ::= <Common Header: Flag UNSOLICITED>
- * <Client Handle>
- * *(<Decision>)
- * [<Integrity>]
- * <Decision> ::= <Context>
- * <Decision: Flags>
- * <Decision: Flags> ::= Install Request-State
- *
- */
-
- // <Decision: Flags>
- final COPSDecision dec = new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE);
+ public void sendOpenNewRequestState() throws COPSException {
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
final Set<COPSDecision> decisionSet = new HashSet<>();
- decisionSet.add(dec);
+ decisionSet.add(new COPSDecision(Command.INSTALL, DecisionFlag.REQSTATE));
decisionMap.put(new COPSContext(RType.CONFIG, (short)0), decisionSet);
- final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, new COPSHandle(_handle.getId()),
- decisionMap, null);
+ final COPSDecisionMsg decisionMsg = new COPSDecisionMsg(_clientType, _handle, decisionMap, null, null);
try {
decisionMsg.writeData(_sock);
/**
* Sends a message asking for a COPS sync operation
- * @throws COPSPdpException
+ * @throws COPSException
*/
- public void sendSyncRequestState()
- throws COPSPdpException {
- /* <Synchronize State Request> ::= <Common Header>
- * [<Client Handle>]
- * [<Integrity>]
- */
-
- final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, new COPSHandle(_handle.getId()), null);
+ public void sendSyncRequestState() throws COPSException {
+ final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
try {
msg.writeData(_sock);
} catch (IOException e) {
package org.umu.cops.prpdp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.COPSStateMan;
import org.umu.cops.stack.*;
import java.net.Socket;
/**
* State manager class for provisioning requests, at the PDP side.
*/
-public class COPSPdpReqStateMan {
+public class COPSPdpReqStateMan extends COPSStateMan {
- /**
- * Request State created
- */
- public final static short ST_CREATE = 1;
- /**
- * Request received
- */
- public final static short ST_INIT = 2;
- /**
- * Decisions sent
- */
- public final static short ST_DECS = 3;
- /**
- * Report received
- */
- public final static short ST_REPORT = 4;
- /**
- * Request State finalized
- */
- public final static short ST_FINAL = 5;
- /**
- * New Request State solicited
- */
- public final static short ST_NEW = 6;
- /**
- * Delete Request State solicited
- */
- public final static short ST_DEL = 7;
- /**
- * SYNC request sent
- */
- public final static short ST_SYNC = 8;
- /**
- * SYNC completed
- */
- public final static short ST_SYNCALL = 9;
- /**
- * Close connection received
- */
- public final static short ST_CCONN = 10;
- /**
- * Keep-alive timeout
- */
- public final static short ST_NOKA = 11;
- /**
- * Accounting timeout
- */
- public final static short ST_ACCT = 12;
-
- /**
- * COPS client-type that identifies the policy client
- */
- protected short _clientType;
-
- /**
- * COPS client handle used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
+ private final static Logger logger = LoggerFactory.getLogger(COPSPdpReqStateMan.class);
/**
* Object for performing policy data processing
*/
- protected COPSPdpDataProcess _process;
-
- /**
- * Current state of the request being managed
- */
- protected short _status;
+ protected final COPSPdpDataProcess _process;
/** COPS message transceiver used to send COPS messages */
- protected COPSPdpMsgSender _sender;
+ protected transient COPSPdpMsgSender _sender;
/**
* Creates a request state manager
* @param clientType Client-type
* @param clientHandle Client handle
*/
- public COPSPdpReqStateMan(short clientType, String clientHandle) {
- _handle = new COPSHandle(new COPSData(clientHandle));
- _clientType = clientType;
- _status = ST_CREATE;
+ public COPSPdpReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPdpDataProcess process) {
+ super(clientType, clientHandle);
+ this._process = process;
}
- /**
- * Gets the client handle
- * @return Client's <tt>COPSHandle</tt>
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Gets the client-type
- * @return Client-type value
- */
- public int getClientType() {
- return _clientType;
- }
-
- /**
- * Gets the status of the request
- * @return Request state value
- */
- public short getStatus() {
- return _status;
- }
-
- /**
- * Gets the policy data processing object
- * @return Policy data processing object
- */
- public COPSPdpDataProcess getDataProcess() {
- return _process;
- }
-
- /**
- * Sets the policy data processing object
- * @param process Policy data processing object
- */
- public void setDataProcess(COPSPdpDataProcess process) {
- _process = process;
- }
-
- /**
- * Called when COPS sync is completed
- * @param repMsg COPS sync message
- * @throws COPSPdpException
- */
- protected void processSyncComplete(COPSSyncStateMsg repMsg)
- throws COPSPdpException {
-
- _status = ST_SYNCALL;
-
- // maybe we should notifySyncComplete ...
- }
-
- /**
- * Initializes a new request state over a socket
- * @param sock Socket to the PEP
- * @throws COPSPdpException
- */
- protected void initRequestState(Socket sock)
- throws COPSPdpException {
+ @Override
+ protected void initRequestState(final Socket sock) throws COPSPdpException {
// Inits an object for sending COPS messages to the PEP
_sender = new COPSPdpMsgSender(_clientType, _handle, sock);
// Initial state
- _status = ST_INIT;
+ _status = Status.ST_INIT;
}
/**
* @param msg COPS request received from the PEP
* @throws COPSPdpException
*/
- protected void processRequest(COPSReqMsg msg)
- throws COPSPdpException {
+ protected void processRequest(final COPSReqMsg msg) throws COPSPdpException {
- COPSHeader hdrmsg = msg.getHeader();
- COPSHandle handlemsg = msg.getClientHandle();
- COPSContext contextmsg = msg.getContext();
+ // TODO - Implement me
+// COPSHeader hdrmsg = msg.getHeader();
+// COPSHandle handlemsg = msg.getClientHandle();
+// COPSContext contextmsg = msg.getContext();
//** Analyze the request
//**
if (msg.getClientSI() != null) {
// Report Type
final COPSReportType rtypemsg = msg.getReport();
-
- // Named ClientSI
- // final Set<COPSClientSI> clientSIs = msg.getClientSI();
final Map<String, String> repSIs = new HashMap<>();
String strobjprid = "";
- // for (final COPSClientSI clientSI : clientSIs) {
final COPSPrObjBase obj = new COPSPrObjBase(msg.getClientSI().getData().getData());
switch (obj.getSNum()) {
case COPSPrObjBase.PR_PRID:
break;
case COPSPrObjBase.PR_EPD:
repSIs.put(strobjprid, obj.getData().str());
- // COPSDebug.out(getClass().getName(),"PRID: " + strobjprid);
- // COPSDebug.out(getClass().getName(),"EPD: " + obj.getData().str());
+ logger.info("PRID: " + strobjprid);
+ logger.info("EPD: " + obj.getData().str());
break;
default:
break;
}
- // }
//** Here we must act in accordance with
//** the report received
switch (rtypemsg.getReportType()) {
case SUCCESS:
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
_process.successReport(this, repSIs);
break;
case FAILURE:
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
_process.failReport(this, repSIs);
break;
case ACCOUNTING:
- _status = ST_ACCT;
+ _status = Status.ST_ACCT;
_process.acctReport(this, repSIs);
break;
}
* @param error Reason
* @throws COPSPdpException
*/
- protected void processClosedConnection(COPSError error)
- throws COPSPdpException {
+ protected void processClosedConnection(final COPSError error) throws COPSPdpException {
if (_process != null)
_process.notifyClosedConnection(this, error);
- _status = ST_CCONN;
+ _status = Status.ST_CCONN;
}
/**
* Called when no keep-alive is received
* @throws COPSPdpException
*/
- protected void processNoKAConnection()
- throws COPSPdpException {
+ protected void processNoKAConnection() throws COPSPdpException {
if (_process != null)
_process.notifyNoKAliveReceived(this);
- _status = ST_NOKA;
+ _status = Status.ST_NOKA;
}
/**
* Deletes the request state
* @throws COPSPdpException
*/
- protected void finalizeRequestState()
- throws COPSPdpException {
+ protected void finalizeRequestState() throws COPSException {
_sender.sendDeleteRequestState();
- _status = ST_FINAL;
+ _status = Status.ST_FINAL;
}
/**
* Asks for a COPS sync
* @throws COPSPdpException
*/
- protected void syncRequestState()
- throws COPSPdpException {
+ protected void syncRequestState() throws COPSException {
_sender.sendSyncRequestState();
- _status = ST_SYNC;
+ _status = Status.ST_SYNC;
}
/**
* Opens a new request state
* @throws COPSPdpException
*/
- protected void openNewRequestState()
- throws COPSPdpException {
+ protected void openNewRequestState() throws COPSException {
_sender.sendOpenNewRequestState();
- _status = ST_NEW;
+ _status = Status.ST_NEW;
}
/**
* @param dMsg <tt>COPSDeleteMsg</tt> received from the PEP
* @throws COPSPdpException
*/
- protected void processDeleteRequestState(COPSDeleteMsg dMsg)
- throws COPSPdpException {
+ protected void processDeleteRequestState(final COPSDeleteMsg dMsg) throws COPSPdpException {
if (_process != null)
_process.closeRequestState(this);
- _status = ST_DEL;
+ _status = Status.ST_DEL;
}
}
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;
*/
public class COPSPepAgent {
+ private final static Logger logger = LoggerFactory.getLogger(COPSPepAgent.class);
+
/**
PEP's Identifier
*/
* @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;
* @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);
}
* @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);
}
* @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);
*/
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;
/**
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
* @param sock Socket connected to PDP
*/
public COPSPepConnection(final short clientType, final Socket sock) {
-
_clientType = clientType;
_sock = sock;
* @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() + ").");
/**
* 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);
/**
* Method getError
- *
* @return a COPSError
- *
*/
protected COPSError getError() {
return _error;
/**
* 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?? ....
/**
* 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 COPSException {
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
manager.processDeleteRequestState(dMsg);
else
// Open new Request State
- handleOpenNewRequestStateMsg(conn, handle);
+ handleOpenNewRequestStateMsg(handle);
} else
// Decision
- manager.processDecision(dMsg);
+ manager.processDecision(dMsg, _sock);
}
}
}
/**
* 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, process);
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();
}
package org.umu.cops.prpep;
-import org.umu.cops.stack.COPSError;
+import org.umu.cops.COPSDataProcess;
import java.util.Map;
* @version COPSPepDataProcess.java, v 2.00 2004
*
*/
-public abstract class COPSPepDataProcess {
+public interface COPSPepDataProcess extends COPSDataProcess {
/**
* Establish PDP decisions
* @param errorDecs - the error decisions
*/
- public abstract void setDecisions(COPSPepReqStateMan man, Map<String, String> removeDecs,
+ void setDecisions(COPSPepReqStateMan man, Map<String, String> removeDecs,
Map<String, String> installDecs, Map<String, String> errorDecs);
/**
* If the report is fail, return true
- *
* @return - t/f
*/
- public abstract boolean isFailReport(COPSPepReqStateMan man);
+ boolean isFailReport(COPSPepReqStateMan man);
/**
* Return Report Data
- *
* @return - the report data
*/
- public abstract Map<String, String> getReportData(COPSPepReqStateMan man);
+ Map<String, String> getReportData(COPSPepReqStateMan man);
/**
* Return Client Data
- *
* @return - the client data
*/
- public abstract Map<String, String> getClientData(COPSPepReqStateMan man);
+ Map<String, String> getClientData(COPSPepReqStateMan man);
/**
* Return Accounting Data
- *
* @return - the accounting data
*/
- public abstract Map<String, String> getAcctData(COPSPepReqStateMan man);
-
- /**
- * Notify the connection closed
- */
- public abstract void notifyClosedConnection(COPSPepReqStateMan man, COPSError error);
-
- /**
- * Notify the KAlive timeout
- */
- public abstract void notifyNoKAliveReceived(COPSPepReqStateMan man);
-
- /**
- * Process a PDP request to close a Request State
- *
- * @param man Request State Manager
- */
- public abstract void closeRequestState(COPSPepReqStateMan man);
+ Map<String, String> getAcctData(COPSPepReqStateMan man);
/**
* Process a PDP request to open a new Request State
*
* @param man Request State Manager
*/
- public abstract void newRequestState(COPSPepReqStateMan man);
+ void newRequestState(COPSPepReqStateMan man);
}
\r
package org.umu.cops.prpep;\r
\r
+import org.umu.cops.stack.COPSException;\r
+\r
/**\r
* COPS PEP Exception\r
*\r
* @version COPSPepException.java, v 2.00 2004\r
*\r
*/\r
-public class COPSPepException extends Exception {\r
-\r
- private int rc;\r
- final static int GENERAL_ERROR = 0x00000001;\r
+public class COPSPepException extends COPSException {\r
\r
public COPSPepException(String s) {\r
super(s);\r
- rc=0;\r
}\r
\r
public COPSPepException(String msg, int retCode) {\r
- super(msg);\r
- rc = retCode;\r
+ super(msg, retCode);\r
}\r
\r
- /**\r
- * Return error code\r
- *\r
- * @return error code\r
- *\r
- */\r
- public int returnCode() {\r
- return rc;\r
+ public COPSPepException(String msg, Throwable t) {\r
+ super(msg, t);\r
}\r
\r
}\r
package org.umu.cops.prpep;
+import org.umu.cops.COPSMsgSender;
import org.umu.cops.stack.*;
import org.umu.cops.stack.COPSClientSI.CSIType;
import org.umu.cops.stack.COPSContext.RType;
* @version COPSPepMsgSender.java, v 2.00 2004
*
*/
-public class COPSPepMsgSender {
-
- /**
- * Socket connection to PDP
- */
- protected Socket _sock;
-
- /**
- * The client-type identifies the policy client
- */
- protected short _clientType;
-
- /**
- * The client handle is used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
+public class COPSPepMsgSender extends COPSMsgSender {
/**
* Create a COPSPepMsgSender
* @param clientHandle client handle
* @param sock socket of PDP connection
*/
- public COPSPepMsgSender (short clientType, COPSHandle clientHandle, Socket sock) {
- // COPS Handle
- _handle = clientHandle;
- _clientType = clientType;
-
- _sock = sock;
- }
-
- /**
- * Return client handle
- *
- * @return a COPSHandle
- *
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Return client-type
- *
- * @return a short
- *
- */
- public int getClientType() {
- return _clientType;
+ public COPSPepMsgSender(short clientType, COPSHandle clientHandle, Socket sock) {
+ super(clientType, clientHandle, sock);
}
/**
* The Synchronize State Complete is sent by the PEP to the PDP after
* the PDP sends a synchronize state request to the PEP and the PEP has
* finished synchronization.
- *
* @throws COPSPepException
- *
*/
- public void sendSyncComplete() throws COPSPepException {
+ public void sendSyncComplete() throws COPSException {
final COPSSyncStateMsg msg = new COPSSyncStateMsg(_clientType, _handle, null);
try {
msg.writeData(_sock);
* When sent from the PEP this message indicates to the remote PDP that
* the state identified by the client handle is no longer
* available/relevant.
- *
* @throws COPSPepException
- *
*/
- public void sendDeleteRequest() throws COPSPepException {
+ public void sendDeleteRequest() throws COPSException {
// *** TODO: send a real reason
final COPSReason reason = new COPSReason(ReasonCode.UNSPECIFIED, ReasonCode.NA);
final COPSDeleteMsg msg = new COPSDeleteMsg(_clientType, _handle, reason, null);
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.COPSStateMan;
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)
* @version COPSPepReqStateMan.java, v 2.00 2004
*
*/
-public class COPSPepReqStateMan {
+public class COPSPepReqStateMan extends COPSStateMan {
- /**
- * Request State created
- */
- public final static short ST_CREATE = 1;
- /**
- * Request sent
- */
- public final static short ST_INIT = 2;
- /**
- * Decisions received
- */
- public final static short ST_DECS = 3;
- /**
- * Report sent
- */
- public final static short ST_REPORT = 4;
- /**
- * Request State finalized
- */
- public final static short ST_FINAL = 5;
- /**
- * New Request State solicited
- */
- public final static short ST_NEW = 6;
- /**
- * Delete Request State solicited
- */
- public final static short ST_DEL = 7;
- /**
- * SYNC Request received
- */
- public final static short ST_SYNC = 8;
- /**
- * SYNC Completed
- */
- public final static short ST_SYNCALL = 9;
- /**
- * Close Connection received
- */
- public final static short ST_CCONN = 10;
- /**
- * KAlive Time out
- */
- public final static short ST_NOKA = 11;
- /**
- * ACCT Time out
- */
- public final static short ST_ACCT = 12;
-
- /**
- * The client-type identifies the policy client
- */
- protected short _clientType;
-
- /**
- * The client handle is used to uniquely identify a particular
- * PEP's request for a client-type
- */
- protected COPSHandle _handle;
+ private final static Logger logger = LoggerFactory.getLogger(COPSPepReqStateMan.class);
/**
The PolicyDataProcess is used to process policy data in the PEP
*/
- protected COPSPepDataProcess _process;
-
- /**
- * State Request State
- */
- protected short _status;
+ protected final COPSPepDataProcess _process;
/**
The Msg Sender is used to send COPS messages
*/
- protected COPSPepMsgSender _sender;
+ protected transient COPSPepMsgSender _sender;
/**
* Sync State
*/
- protected boolean _syncState;
+ protected transient boolean _syncState;
/**
* Create a State Request Manager
* @param clientHandle a Client Handle
*
*/
- public COPSPepReqStateMan(final short clientType, final String clientHandle) {
- _handle = new COPSHandle(new COPSData(clientHandle));
- _clientType = clientType;
+ public COPSPepReqStateMan(final short clientType, final COPSHandle clientHandle, final COPSPepDataProcess process) {
+ super(clientType, clientHandle);
+ this._process = process;
_syncState = true;
- _status = ST_CREATE;
- }
-
- /**
- * Return client handle
- *
- * @return a COPSHandle
- *
- */
- public COPSHandle getClientHandle() {
- return _handle;
- }
-
- /**
- * Return client-type
- *
- * @return a short
- *
- */
- public int getClientType() {
- return _clientType;
- }
-
- /**
- * Return Request State status
- *
- * @return s short
- */
- public short getStatus() {
- return _status;
- }
-
- /**
- * Return the Policy Data Process
- *
- * @return a PolicyConfigure
- *
- */
- public COPSPepDataProcess getDataProcess() {
- return _process;
- }
-
- /**
- * Establish the Policy Data Process
- *
- * @param process a PolicyConfigure
- *
- */
- public void setDataProcess(COPSPepDataProcess process) {
- _process = process;
}
/**
* @throws COPSPepException
*
*/
- protected void initRequestState(Socket sock)
- throws COPSPepException {
+ protected void initRequestState(final Socket sock) throws COPSException {
// Inits an object for sending COPS messages to the PDP
_sender = new COPSPepMsgSender(_clientType, _handle, sock);
_sender.sendRequest(clientSIs);
// Initial state
- _status = ST_INIT;
+ _status = Status.ST_INIT;
}
/**
* @throws COPSPepException
*
*/
- protected void finalizeRequestState()
- throws COPSPepException {
+ protected void finalizeRequestState() throws COPSException {
_sender.sendDeleteRequest();
- _status = ST_FINAL;
+ _status = Status.ST_FINAL;
}
/**
* @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 COPSException {
+ 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;
+ // TODO FIXME - success is always true
+ 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;
// TODO - why is this collection never getting populated???
final Map<String, String> errorDecs = new HashMap<>();
_process.setDecisions(this, removeDecs, installDecs, errorDecs);
- _status = ST_DECS;
+ _status = Status.ST_DECS;
if (_process.isFailReport(this)) {
// COPSDebug.out(getClass().getName(),"Sending SUCCESS Report\n");
_sender.sendSuccessReport(_process.getReportData(this));
}
- _status = ST_REPORT;
+ _status = Status.ST_REPORT;
if (!_syncState) {
_sender.sendSyncComplete();
_syncState = true;
- _status = ST_SYNCALL;
+ _status = Status.ST_SYNCALL;
}
}
* @throws COPSPepException
*
*/
- protected void processOpenNewRequestState()
- throws COPSPepException {
+ protected void processOpenNewRequestState() throws COPSPepException {
if (_process != null)
_process.newRequestState(this);
- _status = ST_NEW;
+ _status = Status.ST_NEW;
}
/**
* @throws COPSPepException
*
*/
- protected void processDeleteRequestState(COPSDecisionMsg dMsg)
- throws COPSPepException {
+ protected void processDeleteRequestState(final COPSDecisionMsg dMsg) throws COPSPepException {
if (_process != null)
_process.closeRequestState(this);
- _status = ST_DEL;
+ _status = Status.ST_DEL;
}
/**
* @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
// TODO - do we really want to send the request when the map is empty???
_sender.sendRequest(clientSIs);
- _status = ST_SYNC;
+ _status = 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;
+ _status = Status.ST_CCONN;
}
- protected void processNoKAConnection()
- throws COPSPepException {
+ protected void processNoKAConnection() throws COPSPepException {
if (_process != null)
_process.notifyNoKAliveReceived(this);
- _status = ST_NOKA;
+ _status = 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<>();
// TODO - do we really want to send when the map is empty???
_sender.sendAcctReport(report);
- _status = ST_ACCT;
+ _status = Status.ST_ACCT;
}
}
package org.umu.cops.stack;
import org.umu.cops.stack.COPSObjHeader.CNum;
+import org.umu.cops.stack.COPSObjHeader.CType;
import java.io.IOException;
import java.io.OutputStream;
*/
private final COPSData _padding;
+ /**
+ * Constructor generally used for sending messages
+ * @param ctype - the CSIType
+ * @param data - the data
+ * @throws java.lang.IllegalArgumentException
+ */
+ public COPSClientSI(final CNum cnum, final CType ctype, final COPSData data) {
+ /* The CSIType does not map directly to the CType, therefore the hook to map to a CType below is
+ required to ensure the header value outputs the correct value when streamed
+ */
+ this(new COPSObjHeader(cnum, ctype), data);
+ }
+
/**
* Constructor generally used for sending messages
* @param csitype - the CSIType
*/
protected COPSClientSI(final COPSObjHeader hdr, final COPSData data) {
super(hdr);
- _csiType = VAL_TO_CSI.get(hdr.getCType().ordinal());
+ if (VAL_TO_CSI.get(hdr.getCType().ordinal()) == null) {
+ // TODO - determine if this is a good default value???
+ _csiType = CSIType.NAMED;
+ } else {
+ _csiType = VAL_TO_CSI.get(hdr.getCType().ordinal());
+ }
- if (!hdr.getCNum().equals(CNum.CSI))
- throw new IllegalArgumentException("CNum must be equal to " + CNum.CSI);
+ if (!hdr.getCNum().equals(CNum.CSI) && !hdr.getCNum().equals(CNum.DEC))
+ throw new IllegalArgumentException("CNum must be equal to " + CNum.CSI + " or " + CNum.DEC);
if (_csiType == null || _csiType.equals(CSIType.NA))
throw new IllegalArgumentException("Invalid CSIType");
- if (_csiType.ordinal() != hdr.getCType().ordinal())
- throw new IllegalArgumentException("Error mapping CSIType " + _csiType + " to CType" + hdr.getCType());
if (data == null) throw new IllegalArgumentException("Data must not be null");
_data = data;
@Override
public void writeBody(final Socket socket) throws IOException {
COPSUtil.writeData(socket, _data.getData(), _data.length());
- COPSUtil.writeData(socket, _padding.getData(), _padding.length());
+ if (_padding.length() > 0) COPSUtil.writeData(socket, _padding.getData(), _padding.length());
}
@Override
* @throws java.lang.IllegalArgumentException
*/
public COPSDecision(final Command cmdCode) {
- this(CType.DEF, cmdCode, DecisionFlag.NA, new COPSData());
+ this(CType.DEF, cmdCode, DecisionFlag.NA, null);
}
/**
* @throws java.lang.IllegalArgumentException
*/
public COPSDecision(final Command cmdCode, final DecisionFlag flags) {
- this(CType.DEF, cmdCode, flags, new COPSData());
+ this(CType.DEF, cmdCode, flags, null);
}
/**
* @throws java.lang.IllegalArgumentException
*/
public COPSDecision(final CType cType, final Command cmdCode, final DecisionFlag flags) {
- this(cType, cmdCode, flags, new COPSData());
+ this(cType, cmdCode, flags, null);
}
/**
if (hdr.getCType().equals(CType.NA)) throw new IllegalArgumentException("CType must not be " + CType.NA);
if (cmdCode == null) throw new IllegalArgumentException("Command code must not be null");
if (flags == null) throw new IllegalArgumentException("Flags must not be null");
- if (data == null) throw new IllegalArgumentException("Data object must not be null");
_cmdCode = cmdCode;
_flags = flags;
- _data = data;
+
+ if (data == null) _data = new COPSData();
+ else _data = data;
if ((_data.length() % 4) != 0) {
final int padLen = 4 - (_data.length() % 4);
import org.umu.cops.stack.COPSHeader.Flag;
import org.umu.cops.stack.COPSHeader.OPCode;
+import org.umu.cops.stack.COPSObjHeader.CType;
import java.io.IOException;
import java.io.OutputStream;
private final COPSError _error;
private final Map<COPSContext, Set<COPSDecision>> _decisions;
private final COPSIntegrity _integrity;
+ private final COPSClientSI _decSI;
/**
* Constructor for Decision messages containing a COPS Error.
* @param clientHandle - the handle (required)
* @param error - the error (required)
* @param integrity - the integrity (optional)
+ * @param decSI - the client SI for the description(optional)
*/
@Deprecated
- public COPSDecisionMsg(final short clientType, final COPSHandle clientHandle,
- final COPSError error, final COPSIntegrity integrity) {
- this(new COPSHeader(OPCode.DEC, clientType), clientHandle, error, null, integrity);
+ public COPSDecisionMsg(final short clientType, final COPSHandle clientHandle, final COPSError error,
+ final COPSIntegrity integrity, final COPSClientSI decSI) {
+ this(new COPSHeader(OPCode.DEC, clientType), clientHandle, error, null, integrity, decSI);
}
/**
* @param clientHandle - the handle (required)
* @param error - the error (required)
* @param integrity - the integrity (optional)
+ * @param decSI - the client SI for the description(optional)
*/
public COPSDecisionMsg(final int version, final Flag flag, final short clientType, final COPSHandle clientHandle,
- final COPSError error, final COPSIntegrity integrity) {
- this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, error, null, integrity);
+ final COPSError error, final COPSIntegrity integrity, final COPSClientSI decSI) {
+ this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, error, null, integrity, decSI);
}
/**
* @param clientHandle - the handle (required)
* @param decisions - the decisions (required)
* @param integrity - the integrity (optional)
+ * @param decSI - the client SI for the description(optional)
*/
@Deprecated
public COPSDecisionMsg(final short clientType, final COPSHandle clientHandle,
- final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity) {
- this(new COPSHeader(OPCode.DEC, clientType), clientHandle, null, decisions, integrity);
+ final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity,
+ final COPSClientSI decSI) {
+ this(new COPSHeader(OPCode.DEC, clientType), clientHandle, null, decisions, integrity, decSI);
}
/**
* @param clientHandle - the handle (required)
* @param decisions - the decisions (required)
* @param integrity - the integrity (optional)
+ * @param decSI - the client SI for the description(optional)
*/
public COPSDecisionMsg(final int version, final Flag flag, final short clientType, final COPSHandle clientHandle,
- final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity) {
- this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, null, decisions, integrity);
+ final Map<COPSContext, Set<COPSDecision>> decisions, final COPSIntegrity integrity,
+ final COPSClientSI decSI) {
+ this(new COPSHeader(version, flag, OPCode.DEC, clientType), clientHandle, null, decisions, integrity, decSI);
}
/**
* @param error - the error (if null, decisions must not be null or empty)
* @param decisions - the decisions (must be empty or null if error is not)
* @param integrity - the integrity (optional)
+ * @param decSI - the client SI for the description(optional)
*/
protected COPSDecisionMsg(final COPSHeader hdr, final COPSHandle clientHandle,
final COPSError error, final Map<COPSContext, Set<COPSDecision>> decisions,
- final COPSIntegrity integrity) {
+ final COPSIntegrity integrity, final COPSClientSI decSI) {
super(hdr);
if (!hdr.getOpCode().equals(OPCode.DEC))
throw new IllegalArgumentException("OPCode must be of type - " + OPCode.DEC);
_clientHandle = clientHandle;
_error = error;
_integrity = integrity;
-
+ _decSI = decSI;
}
// Getters
public COPSIntegrity getIntegrity() {
return _integrity;
}
+ public COPSClientSI getDecSI() {
+ return _decSI;
+ }
@Override
protected int getDataLength() {
}
if (_integrity != null) out += _integrity.getDataLength() + _integrity.getHeader().getHdrLength();
+ if (_decSI != null) out += _decSI.getDataLength() + _decSI.getHeader().getHdrLength();
return out;
}
}
if (_integrity != null) _integrity.writeData(socket);
+ if (_decSI != null) _decSI.writeData(socket);
}
@Override
if (_integrity != null) {
_integrity.dump(os);
}
+ if (_decSI != null) {
+ _decSI.dump(os);
+ }
}
@Override
return _clientHandle.equals(that._clientHandle) &&
!(_error != null ? !_error.equals(that._error) : that._error != null) &&
- !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null);
+ !(_integrity != null ? !_integrity.equals(that._integrity) : that._integrity != null) &&
+ !(_decSI != null ? !_decSI.equals(that._decSI) : that._decSI != null);
}
result = 31 * result + (_error != null ? _error.hashCode() : 0);
result = 31 * result + _decisions.hashCode();
result = 31 * result + (_integrity != null ? _integrity.hashCode() : 0);
+ result = 31 * result + (_decSI != null ? _decSI.hashCode() : 0);
return result;
}
COPSContext context = null;
COPSError error = null;
COPSIntegrity integrity = null;
+ COPSClientSI descSi = null;
final Map<COPSContext, Set<COPSDecision>> decisionMap = new HashMap<>();
int dataStart = 0;
error = COPSError.parse(objHdrData, buf);
break;
case DEC:
- if (decisionMap.get(context) != null)
- decisionMap.get(context).add(COPSDecision.parse(objHdrData, buf));
- else {
- final Set<COPSDecision> decisions = new HashSet<>();
- decisions.add(COPSDecision.parse(objHdrData, buf));
- decisionMap.put(context, decisions);
+ COPSDecision dec;
+ if (objHdrData.header.getCType().equals(CType.CSI)) {
+ // TODO - Revisit, this is pretty darn clunky
+ try {
+ dec = COPSDecision.parse(objHdrData, buf);
+ } catch (IllegalArgumentException e) {
+ descSi = COPSClientSI.parse(objHdrData, buf);
+ dec = null;
+ }
+ } else {
+ dec = COPSDecision.parse(objHdrData, buf);
+ }
+ if (dec != null) {
+ if (decisionMap.get(context) != null)
+ decisionMap.get(context).add(dec);
+ else {
+ final Set<COPSDecision> decisions = new HashSet<>();
+ decisions.add(dec);
+ decisionMap.put(context, decisions);
+ }
}
break;
+ case CSI:
+ descSi = COPSClientSI.parse(objHdrData, buf);
+ break;
case MSG_INTEGRITY:
integrity = COPSIntegrity.parse(objHdrData, buf);
break;
default:
- throw new COPSException("Bad Message format, unknown object type");
+ throw new COPSException("Bad Message format, unknown object type with CNum - "
+ + objHdrData.header.getCNum());
}
dataStart += objHdrData.msgByteCount;
}
- return new COPSDecisionMsg(hdrData.header, clientHandle, error, decisionMap, integrity);
+ return new COPSDecisionMsg(hdrData.header, clientHandle, error, decisionMap, integrity, descSi);
}
}
\ No newline at end of file
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
/**
* COPS Handle Object (RFC 2748 pag. 9)
@Override
public int hashCode() {
int result = super.hashCode();
- result = 31 * result + _data.hashCode();
- result = 31 * result + _padding.hashCode();
+
+ /*
+ Retrieve hash for the bytes contained in both COPSData members as equivalent objects may contain 0 value bytes
+ either trailing in the _data member or contained in the _padding. This generally will occur between an object
+ constructed via a public constructor vs. parsed from a byte[].
+
+ This is important as this object is known to be used as a key to Maps.
+ */
+ final List<Byte> allBytes = new ArrayList<>();
+ for (final byte val : _data.getData()) {
+ allBytes.add(val);
+ }
+ for (final byte val : _padding.getData()) {
+ allBytes.add(val);
+ }
+ result = 31 * allBytes.hashCode();
return result;
}
*/
package org.pcmm.test;
+import org.pcmm.PCMMConstants;
+import org.pcmm.PCMMProperties;
import org.pcmm.rcd.ICMTS;
-import org.pcmm.rcd.IPCMMPolicyServer;
-import org.pcmm.rcd.IPCMMPolicyServer.IPSCMTSClient;
import org.pcmm.rcd.impl.CMTS;
-import org.pcmm.rcd.impl.PCMMPolicyServer;
/**
*
* @param args
*/
public static void main(String[] args) {
- ICMTS icmts = new CMTS();
+ ICMTS icmts = new CMTS(PCMMProperties.get(PCMMConstants.PCMM_PORT, Integer.class));
icmts.startServer();
- IPCMMPolicyServer ps = new PCMMPolicyServer();
- IPSCMTSClient client = ps.requestCMTSConnection("localhost");
- client.gateSet();
+// IPCMMPolicyServer ps = new PCMMPolicyServer();
+// IPSCMTSClient client = ps.requestCMTSConnection("localhost");
+// client.gateSet();
// IWorkerPool pool = new WorkerPool(2);
// IWorker worker = new Worker(new Callable<String>() {
// @Override
*/
public class COPSClientSITest {
+ @Test(expected = IllegalArgumentException.class)
+ public void nullCNumConstructor1() {
+ new COPSClientSI(null, CType.CSI, new COPSData());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void invalidCNumConstructor1() {
+ new COPSClientSI(CNum.ACCT_TIMER, CType.CSI, new COPSData());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void nullCTypeConstructor1() {
+ new COPSClientSI(CNum.DEC, null, new COPSData());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void invalidCTypeConstructor1() {
+ new COPSClientSI(CNum.DEC, CType.NA, new COPSData());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void nullDataConstructor1() {
+ new COPSClientSI(CNum.DEC, CType.CSI, null);
+ }
+
@Test(expected = IllegalArgumentException.class)
public void invalidCSItype() {
new COPSClientSI(CSIType.NA, new COPSData());
new COPSClientSI(new COPSObjHeader(CNum.ACCT_TIMER, CType.CSI), new COPSData());
}
+ @Test
+ public void validConstructor1() {
+ final COPSClientSI clientSI = new COPSClientSI(CNum.DEC, CType.CSI, new COPSData());
+ Assert.assertEquals(CSIType.NAMED, clientSI.getCsiType());
+ Assert.assertEquals(CNum.DEC, clientSI.getHeader().getCNum());
+ Assert.assertEquals(CType.CSI, clientSI.getHeader().getCType());
+ Assert.assertEquals(new COPSData(), clientSI.getData());
+ }
+
@Test
public void csiSignaledEmptyData() {
final COPSClientSI clientSI = new COPSClientSI(CSIType.SIGNALED, new COPSData());
import org.junit.Before;
import org.junit.Test;
import org.pcmm.rcd.IPCMMClient;
+import org.umu.cops.stack.COPSClientSI.CSIType;
import org.umu.cops.stack.COPSContext.RType;
import org.umu.cops.stack.COPSDecision.Command;
import org.umu.cops.stack.COPSDecision.DecisionFlag;
@Test(expected = IllegalArgumentException.class)
public void version0WithError() {
new COPSDecisionMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
- new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+ new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
}
@Test(expected = IllegalArgumentException.class)
public void version0WithDecisions() {
new COPSDecisionMsg(0, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
- staticDecisions, null);
+ staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullFlagWithError() {
new COPSDecisionMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
- new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+ new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullFlagWithDecisions() {
new COPSDecisionMsg(1, null, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()),
- staticDecisions, null);
+ staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullHandleDeprecatedWithError() {
new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null,
- new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+ new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullHandleDeprecatedWithDecisions() {
- new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null, staticDecisions, null);
+ new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, null, staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullHandleWithError() {
new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null,
- new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null);
+ new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullHandleWithDecisions() {
- new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null, staticDecisions, null);
+ new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, null, staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullErrorDeprecated() {
final COPSError error = null;
- new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null);
+ new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullError() {
final COPSError error = null;
- new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error, null);
+ new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), error,
+ null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullDecisionsDeprecated() {
final Map<COPSContext, Set<COPSDecision>> decisions = null;
- new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullDecisions() {
final Map<COPSContext, Set<COPSDecision>> decisions = null;
- new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+ null, null);
}
@Test(expected = IllegalArgumentException.class)
public void emptyDecisionsMapDeprecated() {
final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
- new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void emptyDecisionsMap() {
final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
- new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+ null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullDecisionsSetDeprecated() {
final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
decisions.put(new COPSContext(RType.CONFIG, (short)1), null);
- new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullDecisionsSet() {
final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
decisions.put(new COPSContext(RType.CONFIG, (short)1), null);
- new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+ null, null);
}
@Test(expected = IllegalArgumentException.class)
public void emptyDecisionsSetDeprecated() {
final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
decisions.put(new COPSContext(RType.CONFIG, (short)1), new HashSet<COPSDecision>());
- new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void emptyDecisionsSet() {
final Map<COPSContext, Set<COPSDecision>> decisions = new HashMap<>();
decisions.put(new COPSContext(RType.CONFIG, (short)1), new HashSet<COPSDecision>());
- new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions, null);
+ new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE, new COPSHandle(new COPSData()), decisions,
+ null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullHeaderErrorOnly() {
final COPSHeader hdr = null;
new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
- null, null);
+ null, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullHeaderDecisionsOnly() {
final COPSHeader hdr = null;
- new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null);
+ new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void invalidHdrErrorOnly() {
final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CC, IPCMMClient.CLIENT_TYPE);
new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
- null, null);
+ null, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void invalidHdrDecisionsOnly() {
final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.CC, IPCMMClient.CLIENT_TYPE);
- new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null);
+ new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void withErrorAndDecisions() {
final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
- staticDecisions, null);
+ staticDecisions, null, null);
}
@Test(expected = IllegalArgumentException.class)
public void nullErrorAndDecisions() {
final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
- new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, null, null);
+ new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()), null, null, null, null);
}
@Test
public void validProtectedError() {
final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
final COPSDecisionMsg msg = new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()),
- new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null);
+ new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA), null, null, null);
Assert.assertEquals(OPCode.DEC, msg.getHeader().getOpCode());
Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
Assert.assertEquals(hdr, msg.getHeader());
public void validProtectedDecisions() {
final COPSHeader hdr = new COPSHeader(1, Flag.UNSOLICITED, OPCode.DEC, IPCMMClient.CLIENT_TYPE);
final COPSDecisionMsg msg = new COPSDecisionMsg(hdr, new COPSHandle(new COPSData()),
- null, staticDecisions, null);
+ null, staticDecisions, null, null);
Assert.assertEquals(OPCode.DEC, msg.getHeader().getOpCode());
Assert.assertEquals(IPCMMClient.CLIENT_TYPE, msg.getHeader().getClientType());
Assert.assertEquals(hdr, msg.getHeader());
public void testDumpErrorAll() throws Exception {
final COPSDecisionMsg msg = new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
new COPSHandle(new COPSData()), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.NA),
- new COPSIntegrity());
+ new COPSIntegrity(), new COPSClientSI(CSIType.NAMED, new COPSData()));
final ByteArrayOutputStream os = new ByteArrayOutputStream();
msg.dump(os);
final String out = new String(os.toByteArray());
System.out.println(out);
final String[] lines = out.split("\n");
- Assert.assertEquals(20, lines.length);
+ Assert.assertEquals(25, lines.length);
// Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
Assert.assertEquals("**MSG HEADER**", lines[0]);
@Test
public void testDumpDecisionsAll() throws Exception {
final COPSDecisionMsg msg = new COPSDecisionMsg(1, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
- new COPSHandle(new COPSData()), staticDecisions, new COPSIntegrity());
+ new COPSHandle(new COPSData()), staticDecisions, new COPSIntegrity(),
+ new COPSClientSI(CSIType.NAMED, new COPSData()));
final ByteArrayOutputStream os = new ByteArrayOutputStream();
msg.dump(os);
final String out = new String(os.toByteArray());
System.out.println(out);
final String[] lines = out.split("\n");
- Assert.assertEquals(24, lines.length);
+ Assert.assertEquals(29, lines.length);
// Only checking COPSMsg elements as the COPSObjectMsg elements have already been validated in their own tests
Assert.assertEquals("**MSG HEADER**", lines[0]);
public void testWriteErrorMin() throws Exception {
final COPSDecisionMsg msg = new COPSDecisionMsg(2, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
new COPSHandle(new COPSData("12345")), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.COMM_FAILURE),
- null);
+ null, null);
msg.writeData(outSocket);
public void testWriteErrorWithIntegrity() throws Exception {
final COPSDecisionMsg msg = new COPSDecisionMsg(2, Flag.SOLICITED, IPCMMClient.CLIENT_TYPE,
new COPSHandle(new COPSData("12345")), new COPSError(ErrorTypes.AUTH_FAILURE, ErrorTypes.COMM_FAILURE),
- new COPSIntegrity(2, 3, new COPSData("123456")));
+ new COPSIntegrity(2, 3, new COPSData("123456")), new COPSClientSI(CSIType.NAMED, new COPSData("123")));
msg.writeData(outSocket);
decisions.put(context2, decisions2);
final COPSDecisionMsg msg = new COPSDecisionMsg(2, Flag.UNSOLICITED, IPCMMClient.CLIENT_TYPE,
- new COPSHandle(new COPSData("12345")), decisions, new COPSIntegrity(4, 5, new COPSData("123456")));
+ new COPSHandle(new COPSData("12345")), decisions, new COPSIntegrity(4, 5, new COPSData("123456")),
+ new COPSClientSI(CSIType.NAMED, new COPSData("123")));
msg.writeData(outSocket);
new COPSDecision(CType.NA, new COPSData());
}
- @Test(expected = IllegalArgumentException.class)
- public void constructor2NullData() {
- new COPSDecision(CType.DEF, null);
- }
-
@Test(expected = IllegalArgumentException.class)
public void constructor3NullCommand() {
new COPSDecision(null, DecisionFlag.NA);
new COPSDecision(CType.CSI, Command.INSTALL, null, new COPSData());
}
- @Test(expected = IllegalArgumentException.class)
- public void constructor5NullData() {
- new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.NA, null);
- }
-
@Test(expected = IllegalArgumentException.class)
public void constructor6NullHeader() {
final COPSObjHeader hdr = null;
@Test(expected = IllegalArgumentException.class)
public void constructor6NullData() {
- new COPSDecision(new COPSObjHeader(CNum.DEC, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+ new COPSDecision(new COPSObjHeader(CNum.CSI, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+ }
+
+ @Test
+ public void cNumDECAndNullData() {
+ final COPSDecision decision = new COPSDecision(CType.DEF, null);
+ Assert.assertNotNull(decision.getData());
+ Assert.assertEquals(0, decision.getData().getData().length);
}
@Test
new COPSLPDPDecision(CType.CSI, Command.INSTALL, null, new COPSData());
}
- @Test(expected = IllegalArgumentException.class)
- public void constructor1NullData() {
- new COPSLPDPDecision(CType.CSI, Command.INSTALL, DecisionFlag.NA, null);
- }
-
@Test(expected = IllegalArgumentException.class)
public void constructor2NullHeader() {
final COPSObjHeader hdr = null;
new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI), Command.INSTALL, null, new COPSData());
}
- @Test(expected = IllegalArgumentException.class)
public void constructor2NullData() {
- new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI), Command.INSTALL, DecisionFlag.NA, null);
+ final COPSLPDPDecision decision = new COPSLPDPDecision(new COPSObjHeader(CNum.LPDP_DEC, CType.CSI),
+ Command.INSTALL, DecisionFlag.NA, null);
+ Assert.assertEquals(0, decision.getData().getData().length);
}
@Test
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+--><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>packetcable</artifactId>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <!--
+ Necessary TODO: Hookup your parent pom here, else you will not get necessary versions,
+ maven repos etc. If you run this archetype in a subdirectory of your project, it
+ will pick the pom.xml from the parent directory as the parent pom, which may or may
+ not be correct.
+ -->
+ <!--
+ Necessary TODO: Replace the contents of src/main/resources/80-packetcable.xml with
+ the proper config subsystem contents for your module
+ -->
+ <artifactId>packetcable-policy-config</artifactId>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <description>Configuration files for md-sal</description>
+ <!-- Optional TODO: Uncomment version if you are not using a parent pom.xml
+ <version>1.1.0-SNAPSHOT</version>
+ -->
+ <packaging>jar</packaging>
+ <properties>
+ <!-- Optional TODO: Rename your configfile to taste -->
+ <configfile>80-packetcable.xml</configfile>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/classes/${configfile}</file>
+ <type>xml</type>
+ <classifier>config</classifier>
+ </artifact>
+ <!--
+ Optional TODO: Add additional config files
+ You may need to add more than one config file
+ if so, you just need to add additional <artifact> entries
+ here WITH DIFFERENT CLASSIFIERS
+ Example:
+ <artifact>
+ <file>${project.build.directory}/classes/<another-configfile></file>
+ <type>xml</type>
+ <classifier>config-<meaningful suffix to describe your other configfile></classifier>
+ </artifact>
+ -->
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=packetcable.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<snapshot>
+ <required-capabilities>
+ <capability>urn:opendaylight:params:xml:ns:yang:packetcable:packetcable-policy-server:impl?module=packetcable-policy-server-impl&revision=2014-01-31</capability>
+ </required-capabilities>
+ <configuration>
+
+ <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:packetcable:packetcable-policy-server:impl">
+ prefix:packetcable-policy-server-impl
+ </type>
+ <name>packetcable-policy-server-default-impl</name>
+ <data-broker>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-async-data-broker</type>
+ <name>binding-data-broker</name>
+ </data-broker>
+ <rpc-registry>
+ <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+ <name>binding-rpc-broker</name>
+ </rpc-registry>
+ </module>
+ </modules>
+ </data>
+ </configuration>
+</snapshot>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>packetcable</artifactId>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>packetcable-policy-karaf</artifactId>
+ <packaging>pom</packaging>
+ <prerequisites>
+ <maven>3.0</maven>
+ </prerequisites>
+ <properties>
+ <!-- Optional TODO: Move these properties to your parent pom and possibly
+ DependencyManagement section of your parent pom -->
+ <branding.version>1.1.0-SNAPSHOT</branding.version>
+ <karaf.resources.version>1.5.0-SNAPSHOT</karaf.resources.version>
+ </properties>
+
+ <dependencies>
+ <!-- Basic Karaf dependencies -->
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>framework</artifactId>
+ <version>${karaf.version}</version>
+ <type>kar</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.features</groupId>
+ <artifactId>standard</artifactId>
+ <version>${karaf.version}</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+
+ <!-- ODL Branding -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf.branding</artifactId>
+ <version>${branding.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <!-- ODL Resources needed for karaf -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>opendaylight-karaf-resources</artifactId>
+ <version>${karaf.resources.version}</version>
+ </dependency>
+
+ <!-- Project local feautures -->
+ <!--
+ Necessary TODO put your features here.
+
+ Note: they will need to be <type>xml</xml>
+ and <classifier>features</classifier>.
+
+ Note: they must be <scope>runtime</scope>
+
+ Note: usually you would only need to depend
+ on your own feature file here for your local distro,
+ and possible the features-mdsal for odl-restconf
+ (although, strange situations do exist :) )
+
+ Example:
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.openflowplugin</groupId>
+ <artifactId>features-openflowplugin</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <classifier>features</classifier>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ -->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-mdsal</artifactId>
+ <classifier>features</classifier>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+<!--
+ <dependency>
+ <groupId>org.opendaylight.l2switch</groupId>
+ <artifactId>features-l2switch</artifactId>
+ <classifier>features</classifier>
+ <version>0.2.0-SNAPSHOT</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+-->
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>features-restconf</artifactId>
+ <classifier>features</classifier>
+ <version>1.2.0-SNAPSHOT</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.dlux</groupId>
+ <artifactId>features-dlux</artifactId>
+ <classifier>features</classifier>
+ <version>0.2.0-SNAPSHOT</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>features-packetcable-policy</artifactId>
+ <classifier>features</classifier>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>cleanVersions</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>copy</goal>
+ <goal>unpack</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>commands-generate-help</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.fusesource.scalate</groupId>
+ <artifactId>maven-scalate-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>sitegen</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.apache.servicemix.tooling</groupId>
+ <artifactId>depends-maven-plugin</artifactId>
+ <versionRange>[0,)</versionRange>
+ <goals>
+ <goal>generate-depends-file</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <version>${karaf.version}</version>
+ <extensions>true</extensions>
+ <configuration>
+ <bootFeatures>
+ <feature>standard</feature>
+ <!-- Uncomment the following lines to ensure restconf & dlux are automatically installed -->
+ <!--<feature>odl-restconf</feature>-->
+ <!--<feature>odl-dlux-core</feature>-->
+ <feature>odl-mdsal-apidocs</feature>
+ <feature>odl-packetcable-policy-server-all</feature>
+ <!--
+ Optional TODO: Add entries here for the features you want in your local distro
+ Note: odl-restconf is a separate feature from odl-mdsal-broker. If you want
+ restconf, you need to list it here explicitely.
+ Examples:
+ <feature>odl-openflowplugin-flow-services</feature>
+ <feature>odl-restconf</feature>
+ -->
+ <!-- Final TODO: Remove TODO Comments ;) -->
+ </bootFeatures>
+ </configuration>
+ <executions>
+ <execution>
+ <id>process-resources</id>
+ <goals>
+ <goal>install-kars</goal>
+ </goals>
+ <phase>process-resources</phase>
+ </execution>
+ <execution>
+ <id>package</id>
+ <goals>
+ <goal>instance-create-archive</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>karaf.branding</artifactId>
+ <version>${karaf.branding.version}</version>
+ <outputDirectory>target/assembly/lib</outputDirectory>
+ <destFileName>karaf.branding-${branding.version}.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ <execution>
+ <id>unpack-karaf-resources</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <outputDirectory>${project.build.directory}/assembly</outputDirectory>
+ <groupId>org.opendaylight.controller</groupId>
+ <includeArtifactIds>opendaylight-karaf-resources</includeArtifactIds>
+ <excludes>META-INF\/**</excludes>
+ <excludeTransitive>true</excludeTransitive>
+ <ignorePermissions>false</ignorePermissions>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <tasks>
+ <chmod perm="755">
+ <fileset dir="${project.build.directory}/assembly/bin">
+ <include name="karaf" />
+ <include name="instance" />
+ <include name="start" />
+ <include name="stop" />
+ <include name="status" />
+ <include name="client" />
+ <include name="shell" />
+ </fileset>
+ </chmod>
+ </tasks>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://git.opendaylight.org/gerrit/gitweb?p=packetcable.git;a=summary</url>
+ </scm>
+</project>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>packetcable</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>packetcable-policy-model</artifactId>
+ <packaging>bundle</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-common</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>maven-sal-api-gen-plugin</artifactId>
+ <version>${yangtools.version}</version>
+ <type>jar</type>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+</project>
--- /dev/null
+module packetcable
+{
+ namespace "urn:packetcable";
+ prefix "pcmm";
+
+ import ietf-yang-types { prefix yang; }
+ import ietf-inet-types { prefix inet; }
+
+ description "This module contains the PCMM Converged Cable Access Platform (CCAP) definitions";
+ organization "OpenDaylight Project";
+
+ revision 2015-03-27 {
+ description "Initial revision of PCMM CCAP definitions";
+ }
+
+
+ // Global typedefs
+ typedef service-class-name {
+ type string { length "2..16"; }
+ description "The Service Class Name is MUST be 2-16 bytes.";
+ }
+ typedef service-flow-direction {
+ type enumeration {
+ enum us {
+ value "1";
+ description "Upstream service flow.";
+ }
+ enum ds {
+ value "2";
+ description "Downstream service flow.";
+ }
+ }
+ description "This value represents the service flow direction.";
+ }
+ typedef tp-protocol {
+ type uint16 {range "0..257";}
+ description "This value represents the IP transport protocol (or Next Header) where 256 is any protocol and 257 is TCP or UDP";
+ }
+ typedef tos-byte {
+ type uint8;
+ description "TOS/TC byte or mask";
+ }
+
+
+ // CCAP devices
+ container ccap {
+ list ccaps {
+ description "
+ CCAP devices are known by their network name which is any string.
+ Each CCAP device has a network address:port, a list of subscriber IP subnets,
+ and a list of available Service Class Names.
+ ";
+ key "ccapId";
+ leaf ccapId {
+ type string;
+ description "CCAP Identity";
+ }
+ uses ccap-attributes;
+ }
+ }
+
+ grouping ccap-attributes {
+ description "
+ Each CCAP device has a COPS connection address:port,
+ a list of subscriber IP subnets, and
+ a list of available Service Class Names.
+ ";
+ container connection {
+ leaf ipAddress {
+ type inet:ip-address;
+ description "IP Address of CCAP";
+ }
+ leaf port {
+ type inet:port-number;
+ description "COPS session TCP port number";
+ default 3918;
+ }
+ }
+ container amId {
+ leaf am-tag {
+ type uint16;
+ description "Application Manager Tag -- unique for this operator";
+ }
+ leaf am-type {
+ type uint16;
+ description "Application Manager Type -- unique for this AM tag";
+ }
+ }
+ leaf-list subscriber-subnets {
+ type inet:ip-prefix;
+ }
+ leaf-list upstream-scns {
+ type service-class-name;
+ }
+ leaf-list downstream-scns {
+ type service-class-name;
+ }
+ leaf response {
+ type string;
+ description "HTTP response from the PUT operation provided by the API";
+ }
+ }
+
+ // PCMM QoS Gates
+ container qos {
+ description "
+ PCMM QoS Gates are organized as a tree by Application/Subscriber/Gate:
+ Each Application is known by its appId which is any string.
+ Each Subscriber is known by its subId which is a CPE IP address in either IPv4 or IPv6 format.
+ Each Gate is known by its gateId which is any string.
+
+ The subscriber's CPE IP address is used to locate the CCAP device that is currently hosting the
+ the Cable Modem that is connected to the subscriber's device. Therefore, it is not necessary
+ for the PCMM applications to know the topology of the CCAP devices and CMs in the network path
+ to their subscriber devices.
+
+ Note that each CCAP entry contains a list of connected subscriber IP subnets as well as a list
+ of all Service Class Names (SCNs) available on the CCAP device.
+ ";
+ uses pcmm-qos-gates;
+ }
+
+ grouping pcmm-qos-gates {
+ list apps {
+ key "appId";
+ leaf appId {
+ type string;
+ description "Application Identity";
+ }
+ list subs {
+ key "subId";
+ leaf subId {
+ type string;
+ description "Subscriber Identity -- must be a CM or CPE IP address";
+ }
+ list gates {
+ key "gateId";
+ leaf gateId {
+ type string;
+ description "Qos Gate Identity";
+ }
+ uses pcmm-qos-gate-attributes;
+ }
+ }
+ }
+ }
+
+ grouping pcmm-qos-gate-attributes {
+ uses pcmm-qos-gate-spec;
+ uses pcmm-qos-traffic-profile;
+ uses pcmm-qos-classifier;
+ uses pcmm-qos-ext-classifier;
+ uses pcmm-qos-ipv6-classifier;
+ leaf response {
+ type string;
+ description "HTTP response from the PUT operation provided by the API";
+ }
+ }
+
+ grouping pcmm-qos-gate-spec {
+ container gate-spec {
+ leaf direction {
+ type service-flow-direction;
+ description "Gate Direction (ignored for traffic profile SCN)";
+ }
+ leaf dscp-tos-overwrite {
+ type tos-byte;
+ description "Optional DSCP/TOS overwrite value";
+ }
+ leaf dscp-tos-mask {
+ type tos-byte;
+ description "Optional DSCP/TOS overwrite AND mask";
+ }
+ }
+ }
+
+ grouping pcmm-qos-traffic-profile {
+ container traffic-profile {
+ leaf service-class-name {
+ type service-class-name;
+ description "The Service Class Name (SCN). This SCN must be pre-provisioned on the target CCAP";
+ }
+ }
+ }
+
+ grouping tp-port-match-ranges {
+ leaf srcPort-start {
+ type inet:port-number;
+ description "TCP/UDP source port range start.";
+ }
+ leaf srcPort-end {
+ type inet:port-number;
+ description "TCP/UDP source port range end.";
+ }
+ leaf dstPort-start {
+ type inet:port-number;
+ description "TCP/UDP destination port range start.";
+ }
+ leaf dstPort-end {
+ type inet:port-number;
+ description "TCP/UDP destination port range end.";
+ }
+ }
+
+ grouping pcmm-qos-classifier {
+ container classifier {
+ leaf srcIp {
+ type inet:ipv4-address;
+ description "Source IPv4 address (exact match)";
+ }
+ leaf dstIp {
+ type inet:ipv4-address;
+ description "Destination IPv4 address (exact match)";
+ }
+ leaf tos-byte {
+ type tos-byte;
+ description "TOS/DSCP match";
+ }
+ leaf tos-mask {
+ type tos-byte;
+ description "TOS/DSCP mask";
+ }
+ leaf protocol {
+ type tp-protocol;
+ description "IPv4 transport protocol";
+ }
+ leaf srcPort {
+ type inet:port-number;
+ description "TCP/UDP source port (exact match).";
+ }
+ leaf dstPort {
+ type inet:port-number;
+ description "TCP/UDP destination port (exact match).";
+ }
+ }
+ }
+
+ grouping pcmm-qos-ext-classifier {
+ container ext-classifier {
+ leaf srcIp {
+ type inet:ipv4-address;
+ description "Source IPv4 address match";
+ }
+ leaf srcIpMask {
+ type inet:ipv4-address;
+ description "Source IPv4 mask";
+ }
+ leaf dstIp {
+ type inet:ipv4-address;
+ description "Destination IPv4 address match";
+ }
+ leaf dstIpMask {
+ type inet:ipv4-address;
+ description "Destination IPv4 mask";
+ }
+ leaf tos-byte {
+ type tos-byte;
+ description "TOS/DSCP match";
+ }
+ leaf tos-mask {
+ type tos-byte;
+ description "TOS/DSCP mask";
+ }
+ leaf protocol {
+ type tp-protocol;
+ description "IPv4 transport protocol";
+ }
+ uses tp-port-match-ranges;
+ }
+ }
+
+ grouping pcmm-qos-ipv6-classifier {
+ container ipv6-classifier {
+ leaf srcIp6 {
+ type inet:ipv6-prefix;
+ description "Source IPv6 prefix match in <address/len> notation";
+ }
+ leaf dstIp6 {
+ type inet:ipv6-prefix;
+ description "Destination IPv6 prefix match in <address/len> notation";
+ }
+ leaf tc-low {
+ type tos-byte;
+ description "TC low range match";
+ }
+ leaf tc-high {
+ type tos-byte;
+ description "TC high range match";
+ }
+ leaf tc-mask {
+ type tos-byte;
+ description "TC mask";
+ }
+ leaf next-hdr {
+ type tp-protocol;
+ description "IPv6 Next Header";
+ }
+ leaf flow-label {
+ type uint32 {
+ range "0 .. 1048575";
+ }
+ description "IPv6 Flow Label (20 bits)";
+ }
+ uses tp-port-match-ranges;
+ }
+ }
+
+}
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.packetcable</groupId>
+ <artifactId>packetcable</artifactId>
+ <version>1.2.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>packetcable-policy-server</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <sal-binding-api.version>1.2.0-SNAPSHOT</sal-binding-api.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>packetcable-driver</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>packetcable-policy-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-inet-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools.model</groupId>
+ <artifactId>ietf-yang-types</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-config</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <version>2.0.2-beta</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>org.opendaylight.controller.config.yang.toaster_provider,</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>config</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator</codeGeneratorClass>
+ <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
+ <additionalConfiguration>
+ <namespaceToPackage1>urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang</namespaceToPackage1>
+ </additionalConfiguration>
+ </generator>
+ <generator>
+ <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+ <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>true</inspectDependencies>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <tag>HEAD</tag>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+</project>
--- /dev/null
+/**
+ * Build PCMM gate requests from API QoS Gate objects
+ */
+package org.opendaylight.controller.packetcable.provider;
+
+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.ccap.attributes.AmId;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifier;
+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.ipv6.classifier.Ipv6Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.pcmm.gates.*;
+import org.pcmm.gates.IGateSpec.DSCPTOS;
+import org.pcmm.gates.IGateSpec.Direction;
+import org.pcmm.gates.impl.DOCSISServiceClassNameTrafficProfile;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.pcmm.gates.impl.SubscriberID;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ *
+ * PacketCable data processor
+ *
+ */
+public class PCMMGateReqBuilder {
+
+ private Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class);
+
+ private PCMMGateReq gateReq = null;
+
+ public PCMMGateReqBuilder() {
+ gateReq = new org.pcmm.gates.impl.PCMMGateReq();
+ }
+
+ public PCMMGateReq getGateReq() {
+ return gateReq;
+ }
+
+ public void build(AmId qosAmId){
+ IAMID amId = new org.pcmm.gates.impl.AMID();
+ amId.setApplicationMgrTag(qosAmId.getAmTag().shortValue());
+ amId.setApplicationType(qosAmId.getAmType().shortValue());
+ gateReq.setAMID(amId);
+ }
+
+ public void build(InetAddress qosSubId){
+ ISubscriberID subId = new SubscriberID();
+ subId.setSourceIPAddress(qosSubId);
+ gateReq.setSubscriberID(subId);
+ }
+
+ public void build(GateSpec qosGateSpec, ServiceFlowDirection scnDirection) {
+ IGateSpec gateSpec = new org.pcmm.gates.impl.GateSpec();
+ // service flow direction
+ ServiceFlowDirection qosDir = null;
+ Direction gateDir = null;
+ if (scnDirection != null) {
+ qosDir = scnDirection;
+ } else if (qosGateSpec.getDirection() != null) {
+ qosDir = qosGateSpec.getDirection();
+ }
+ if (qosDir == ServiceFlowDirection.Ds) {
+ gateDir = Direction.DOWNSTREAM;
+ } else if (qosDir == ServiceFlowDirection.Us) {
+ gateDir = Direction.UPSTREAM;
+ }
+ gateSpec.setDirection(gateDir);
+ // DSCP/TOS Overwrite
+ TosByte tosOverwrite = qosGateSpec.getDscpTosOverwrite();
+ if (tosOverwrite != null) {
+ byte gateTos = tosOverwrite.getValue().byteValue();
+ gateSpec.setDSCP_TOSOverwrite(DSCPTOS.ENABLE);
+ gateSpec.setDSCP_TOSOverwrite(gateTos);
+ TosByte tosMask = qosGateSpec.getDscpTosMask();
+ if (tosMask != null) {
+ byte gateTosMask = tosMask.getValue().byteValue();
+ gateSpec.setDSCP_TOSMask(gateTosMask);
+ } else {
+ gateSpec.setDSCP_TOSMask((byte)0xff);
+ }
+ }
+ gateReq.setGateSpec(gateSpec);
+ }
+
+ public void build(TrafficProfile qosTrafficProfile) {
+ if (qosTrafficProfile.getServiceClassName() != null) {
+ String scn = qosTrafficProfile.getServiceClassName().getValue();
+ DOCSISServiceClassNameTrafficProfile trafficProfile = new DOCSISServiceClassNameTrafficProfile();
+ if (scn.length() <= 16) { // NB.16 char SCN is max length per PCMM spec
+ trafficProfile.setServiceClassName(scn);
+ gateReq.setTrafficProfile(trafficProfile);
+ }
+ }
+ }
+
+ private InetAddress getByName(String ipAddressStr){
+ InetAddress ipAddress = null;
+ try {
+ ipAddress = InetAddress.getByName(ipAddressStr);
+ } catch (UnknownHostException e) {
+ logger.error(e.getMessage());
+ }
+ return ipAddress;
+ }
+
+ public void build(Classifier qosClassifier) {
+ // Legacy classifier
+ IClassifier classifier = new org.pcmm.gates.impl.Classifier();
+ classifier.setPriority((byte) 64);
+ if (qosClassifier.getProtocol() != null){
+ classifier.setProtocol(qosClassifier.getProtocol().getValue().shortValue());
+ }
+ if (qosClassifier.getSrcIp() != null) {
+ InetAddress sip = getByName(qosClassifier.getSrcIp().getValue());
+ if (sip != null) {
+ classifier.setSourceIPAddress(sip);
+ }
+ }
+ if (qosClassifier.getDstIp() != null) {
+ InetAddress dip = getByName(qosClassifier.getDstIp().getValue());
+ if (dip != null) {
+ classifier.setDestinationIPAddress(dip);
+ }
+ }
+ if (qosClassifier.getSrcPort() != null) {
+ classifier.setSourcePort(qosClassifier.getSrcPort().getValue().shortValue());
+ }
+ if (qosClassifier.getDstPort() != null) {
+ classifier.setDestinationPort(qosClassifier.getDstPort().getValue().shortValue());
+ }
+ if (qosClassifier.getTosByte() != null) {
+ classifier.setDSCPTOS(qosClassifier.getTosByte().getValue().byteValue());
+ if (qosClassifier.getTosMask() != null) {
+ classifier.setDSCPTOSMask(qosClassifier.getTosMask().getValue().byteValue());
+ } else {
+ // set default TOS mask
+ classifier.setDSCPTOSMask((byte)0xff);
+ }
+ }
+ // push the classifier to the gate request
+ gateReq.setClassifier(classifier);
+ }
+
+ public void build(ExtClassifier qosExtClassifier) {
+ // Extended classifier
+ IExtendedClassifier extClassifier = new org.pcmm.gates.impl.ExtendedClassifier();
+ extClassifier.setPriority((byte) 64);
+ extClassifier.setActivationState((byte) 0x01);
+ // Protocol -- zero is match any
+ if (qosExtClassifier.getProtocol() != null){
+ extClassifier.setProtocol(qosExtClassifier.getProtocol().getValue().shortValue());
+ } else {
+ extClassifier.setProtocol((short)0);
+ }
+ // Source IP address & mask
+ if (qosExtClassifier.getSrcIp() != null) {
+ InetAddress sip = getByName(qosExtClassifier.getSrcIp().getValue());
+ if (sip != null) {
+ extClassifier.setSourceIPAddress(sip);
+ if (qosExtClassifier.getSrcIpMask() != null) {
+ InetAddress sipMask = getByName(qosExtClassifier.getSrcIpMask().getValue());
+ extClassifier.setIPSourceMask(sipMask);
+ } else {
+ // default mask is /32
+ extClassifier.setIPSourceMask(getByName("255.255.255.255"));
+ }
+ }
+ }
+ // Destination IP address & mask
+ if (qosExtClassifier.getDstIp() != null) {
+ InetAddress dip = getByName(qosExtClassifier.getDstIp().getValue());
+ if (dip != null) {
+ extClassifier.setDestinationIPAddress(dip);
+ if (qosExtClassifier.getDstIpMask() != null) {
+ InetAddress dipMask = getByName(qosExtClassifier.getDstIpMask().getValue());
+ extClassifier.setIPDestinationMask(dipMask);
+ } else {
+ // default mask is /32
+ extClassifier.setIPDestinationMask(getByName("255.255.255.255"));
+ }
+ }
+ }
+ // default source port range must be set to match any even if qosExtClassifier has no range
+ // match any port range is 0-65535, NOT 0-0
+ short startPort = (short)0;
+ short endPort = (short)65535;
+ if (qosExtClassifier.getSrcPortStart() != null) {
+ startPort = qosExtClassifier.getSrcPortStart().getValue().shortValue();
+ endPort = startPort;
+ if (qosExtClassifier.getSrcPortEnd() != null) {
+ endPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue();
+ }
+ if (startPort > endPort) {
+ logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same", startPort, endPort);
+ endPort = startPort;
+ }
+ }
+ extClassifier.setSourcePortStart(startPort);
+ extClassifier.setSourcePortEnd(endPort);
+ // default destination port range must be set to match any even if qosExtClassifier has no range
+ // match any port range is 0-65535, NOT 0-0
+ startPort = (short)0;
+ endPort = (short)65535;
+ if (qosExtClassifier.getDstPortStart() != null) {
+ startPort = qosExtClassifier.getDstPortStart().getValue().shortValue();
+ endPort = startPort;
+ if (qosExtClassifier.getDstPortEnd() != null) {
+ endPort = qosExtClassifier.getDstPortEnd().getValue().shortValue();
+ }
+ if (startPort > endPort) {
+ logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same", startPort, endPort);
+ endPort = startPort;
+ }
+ }
+ extClassifier.setDestinationPortStart(startPort);
+ extClassifier.setDestinationPortEnd(endPort);
+ // DSCP/TOP byte
+ if (qosExtClassifier.getTosByte() != null) {
+ // OR in the DSCP/TOS enable bit 0x01
+ extClassifier.setDSCPTOS((byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01));
+ if (qosExtClassifier.getTosMask() != null) {
+ extClassifier.setDSCPTOSMask(qosExtClassifier.getTosMask().getValue().byteValue());
+ } else {
+ // set default TOS mask
+ extClassifier.setDSCPTOSMask((byte)0xff);
+ }
+ }
+ // push the extended classifier to the gate request
+ gateReq.setClassifier(extClassifier);
+ }
+
+ public void build(Ipv6Classifier qosIpv6Classifier) {
+ // IPv6 classifier
+ IIPv6Classifier ipv6Classifier = new org.pcmm.gates.impl.IPv6Classifier();
+ ipv6Classifier.setPriority((byte) 64);
+ ipv6Classifier.setActivationState((byte) 0x01);
+ // Flow Label
+ if (qosIpv6Classifier.getFlowLabel() != null){
+ ipv6Classifier.setFlowLabel(qosIpv6Classifier.getFlowLabel());
+ ipv6Classifier.setFlowLabelEnableFlag((byte)0x01);
+ }
+ // Next Header
+ if (qosIpv6Classifier.getNextHdr() != null){
+ ipv6Classifier.setNextHdr(qosIpv6Classifier.getNextHdr().getValue().shortValue());
+ } else {
+ // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option
+ ipv6Classifier.setNextHdr((short)256);
+ }
+ // Source IPv6 address & prefix len
+ byte prefLen;
+ if (qosIpv6Classifier.getSrcIp6() != null) {
+ String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/");
+ String Ipv6AddressStr = parts[0];
+ InetAddress sip6 = getByName(Ipv6AddressStr);
+ if (sip6 != null) {
+ ipv6Classifier.setSourceIPAddress(sip6);
+ }
+ prefLen = (byte)128;
+ if (parts.length > 1) {
+ prefLen = (byte)Integer.parseInt(parts[1]);
+ }
+ ipv6Classifier.setSourcePrefixLen(prefLen);
+ }
+ // Destination IPv6 address & prefix len
+ if (qosIpv6Classifier.getDstIp6() != null) {
+ String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/");
+ String Ipv6AddressStr = parts[0];
+ InetAddress dip6 = getByName(Ipv6AddressStr);
+ if (dip6 != null) {
+ ipv6Classifier.setDestinationIPAddress(dip6);
+ }
+ prefLen = (byte)128;
+ if (parts.length > 1) {
+ prefLen = (byte)Integer.parseInt(parts[1]);
+ }
+ ipv6Classifier.setDestinationPrefixLen(prefLen);
+ }
+ // default source port range must be set to match any -- even if qosExtClassifier has no range value
+ // match any port range is 0-65535, NOT 0-0
+ short startPort = (short)0;
+ short endPort = (short)65535;
+ if (qosIpv6Classifier.getSrcPortStart() != null) {
+ startPort = qosIpv6Classifier.getSrcPortStart().getValue().shortValue();
+ endPort = startPort;
+ if (qosIpv6Classifier.getSrcPortEnd() != null) {
+ endPort = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue();
+ }
+ if (startPort > endPort) {
+ logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same", startPort, endPort);
+ endPort = startPort;
+ }
+ }
+ ipv6Classifier.setSourcePortStart(startPort);
+ ipv6Classifier.setSourcePortEnd(endPort);
+ // default destination port range must be set to match any -- even if qosExtClassifier has no range value
+ // match any port range is 0-65535, NOT 0-0
+ startPort = (short)0;
+ endPort = (short)65535;
+ if (qosIpv6Classifier.getDstPortStart() != null) {
+ startPort = qosIpv6Classifier.getDstPortStart().getValue().shortValue();
+ endPort = startPort;
+ if (qosIpv6Classifier.getDstPortEnd() != null) {
+ endPort = qosIpv6Classifier.getDstPortEnd().getValue().shortValue();
+ }
+ if (startPort > endPort) {
+ logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same", startPort, endPort);
+ endPort = startPort;
+ }
+ }
+ ipv6Classifier.setDestinationPortStart(startPort);
+ ipv6Classifier.setDestinationPortEnd(endPort);
+ // TC low, high, mask
+ if (qosIpv6Classifier.getTcLow() != null) {
+ ipv6Classifier.setTcLow(qosIpv6Classifier.getTcLow().getValue().byteValue());
+ if (qosIpv6Classifier.getTcHigh() != null) {
+ ipv6Classifier.setTcHigh(qosIpv6Classifier.getTcHigh().getValue().byteValue());
+ }
+ if (qosIpv6Classifier.getTcMask() != null) {
+ ipv6Classifier.setTcMask(qosIpv6Classifier.getTcMask().getValue().byteValue());
+ } else {
+ // set default TOS mask
+ ipv6Classifier.setTcMask((byte)0xff);
+ }
+ } else {
+ // mask 0x00 is match any
+ ipv6Classifier.setTcMask((byte)0x00);
+ }
+ // push the IPv6 classifier to the gate request
+ gateReq.setClassifier(ipv6Classifier);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.packetcable.provider;
+
+import com.google.common.collect.Maps;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+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.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.subs.Gates;
+import org.pcmm.PCMMPdpAgent;
+import org.pcmm.PCMMPdpDataProcess;
+import org.pcmm.PCMMPdpMsgSender;
+import org.pcmm.gates.impl.PCMMGateReq;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.umu.cops.prpdp.COPSPdpException;
+import org.umu.cops.stack.COPSError;
+import org.umu.cops.stack.COPSError.ErrorTypes;
+import org.umu.cops.stack.COPSException;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.Map;
+
+/**
+ * Class responsible for managing the gates for a single CCAP.
+ */
+@ThreadSafe
+public class PCMMService {
+ private Logger logger = LoggerFactory.getLogger(PCMMService.class);
+
+ private final Ccaps ccap;
+ private final IpAddress ipAddr;
+ private final PortNumber portNum;
+ protected final CcapClient ccapClient;
+ protected Map<String, PCMMGateReq> gateRequests = Maps.newConcurrentMap();
+
+ private final short clientType;
+
+ public PCMMService(final short clientType, final Ccaps ccap) {
+ this.clientType = clientType;
+ this.ccap = ccap;
+ ipAddr = ccap.getConnection().getIpAddress();
+ portNum = ccap.getConnection().getPort();
+ ccapClient = new CcapClient(ipAddr, portNum);
+ logger.info("Attempting to add CCAP with ID {} @ {}:{}", ccap.getCcapId(), ipAddr.getIpv4Address().getValue(), portNum.getValue());
+ }
+
+ public void disconect() {
+ ccapClient.disconnect();
+ }
+
+ // TODO - try and change the return to something other than a String to be parsed to determine success
+ public String addCcap() {
+ ccapClient.connect();
+ if (ccapClient.isConnected) {
+ logger.info("Connected to CCAP with ID - " + ccap.getCcapId());
+ return String.format("200 OK - CCAP %s connected @ %s:%d", ccap.getCcapId(),
+ ipAddr.getIpv4Address().getValue(), portNum.getValue());
+ } else {
+ return String.format("404 Not Found - CCAP %s failed to connect @ %s:%d - %s",
+ ccap.getCcapId(),
+ ipAddr.getIpv4Address().getValue(), portNum.getValue(), ccapClient.errMessage);
+ }
+ }
+
+ // TODO - Consider creating an object to return that contains a success flag, message, and gate ID or gate object
+ // TODO FIXME - the gate appears to be getting set as per restconf but I am not seeing the proper logging occurring
+ public String sendGateSet(final String gatePathStr, final InetAddress subId, final Gates qosGate,
+ final ServiceFlowDirection scnDir) {
+ logger.info("Sending gate to CCAP with ID - " + ccap.getCcapId());
+ // assemble the gate request for this subId
+ final PCMMGateReqBuilder gateBuilder = new PCMMGateReqBuilder();
+ gateBuilder.build(ccap.getAmId());
+ gateBuilder.build(subId);
+ // force gateSpec.Direction to align with SCN direction
+ final ServiceClassName scn = qosGate.getTrafficProfile().getServiceClassName();
+ if (scn != null) {
+ gateBuilder.build(qosGate.getGateSpec(), scnDir);
+ } else {
+ // not an SCN gate
+ gateBuilder.build(qosGate.getGateSpec(), null);
+ }
+ gateBuilder.build(qosGate.getTrafficProfile());
+
+ // pick a classifier type (only one for now)
+ if (qosGate.getClassifier() != null) {
+ gateBuilder.build(qosGate.getClassifier());
+ } else if (qosGate.getExtClassifier() != null) {
+ gateBuilder.build(qosGate.getExtClassifier());
+ } else if (qosGate.getIpv6Classifier() != null) {
+ gateBuilder.build(qosGate.getIpv6Classifier());
+ }
+ // assemble the final gate request
+ final PCMMGateReq gateReq = gateBuilder.getGateReq();
+
+ // and remember it
+ gateRequests.put(gatePathStr, gateReq);
+ // and send it to the CCAP
+ ccapClient.sendGateSet(gateReq);
+ // and wait for the COPS response to complete processing gate request
+ try {
+ // TODO - see PCMMPdpReqStateMan#processReport() gate.notify(). Should determine a better means to
+ // TODO - handle this synchronization.
+ // TODO - if not changing this, may want to make this timeout configurable
+ synchronized(gateReq) {
+ logger.info("Waiting 1000ms for gate request to be updated");
+ gateReq.wait(1000);
+ logger.debug("Gate request error - " + gateReq.getError());
+ logger.debug("Gate request ID - " + gateReq.getGateID());
+ }
+ } catch (Exception e) {
+ logger.error("PCMMService: sendGateSet(): gate response timeout exceeded for "
+ + gatePathStr + '/' + gateReq, e);
+ return String.format("408 Request Timeout - gate response timeout exceeded for %s/%s",
+ ccap.getCcapId(), gatePathStr);
+ }
+ if (gateReq.getError() != null) {
+ logger.error("PCMMService: sendGateSet(): returned error: {}",
+ gateReq.getError().toString());
+ return String.format("404 Not Found - sendGateSet for %s/%s returned error - %s",
+ ccap.getCcapId(), gatePathStr, gateReq.getError().toString());
+ } else {
+ if (gateReq.getGateID() != null) {
+ logger.info(String.format("PCMMService: sendGateSet(): returned GateId %08x: ",
+ gateReq.getGateID().getGateID()));
+ return String.format("200 OK - sendGateSet for %s/%s returned GateId %08x",
+ ccap.getCcapId(), gatePathStr, gateReq.getGateID().getGateID());
+ } else {
+ logger.info("PCMMService: sendGateSet(): no gateId returned:");
+ return String.format("404 Not Found - sendGateSet for %s/%s no gateId returned",
+ ccap.getCcapId(), gatePathStr);
+ }
+ }
+ }
+
+ public Boolean sendGateDelete(final String gatePathStr) {
+ logger.info("sendGateDelete() - " + ccap);
+ // recover the original gate request
+ final PCMMGateReq gateReq = gateRequests.remove(gatePathStr);
+ if (gateReq != null) {
+ ccapClient.sendGateDelete(gateReq);
+ // and wait for the response to complete
+ try {
+ // TODO - see PCMMPdpReqStateMan#processReport() gate.notify(). Should determine a better means to
+ // TODO - handle this synchronization.
+ synchronized(gateReq) {
+ gateReq.wait(1000);
+ }
+ } catch (InterruptedException e) {
+ logger.error("PCMMService: sendGateDelete(): gate response timeout exceeded for {}/{}",
+ gatePathStr, gateReq);
+ }
+ if (gateReq.getError() != null) {
+ logger.warn("PCMMService: sendGateDelete(): returned error: {}", gateReq.getError().toString());
+ return false;
+ } else {
+ if (gateReq.getGateID() != null) {
+ logger.info(String.format("PCMMService: sendGateDelete(): deleted GateId %08x: ", gateReq.getGateID().getGateID()));
+ } else {
+ logger.error("PCMMService: sendGateDelete(): deleted but no gateId returned");
+ }
+ return true;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ private String getIpAddressStr(final IpAddress ipAddress) {
+ final Ipv4Address ipv4 = ipAddress.getIpv4Address();
+ if (ipv4 != null) {
+ return ipv4.getValue();
+ } else {
+ return ipAddress.getIpv6Address().getValue();
+ }
+ }
+
+ /**
+ * Used to interface with a CCAP (including CMTSs)
+ */
+ protected class CcapClient {
+ public final PCMMPdpDataProcess pcmmProcess;
+ public final PCMMPdpAgent pcmmPdp;
+
+ 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();
+ else port = PCMMPdpAgent.WELL_KNOWN_PDP_PORT;
+ // TODO FIXME - if this object is not null, gate processing will not work correctly
+ // TODO see - PCMMPdpReqStateMan#processReport() where the report type is success and the process is null
+ // pcmmProcess = new PCMMPdpDataProcess();
+ pcmmProcess = null;
+ 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(clientType, pcmmPdp.getClientHandle(), pcmmPdp.getSocket());
+
+ isConnected = true;
+ } catch (Exception e) {
+ isConnected = false;
+ logger.error("Failed to connect to host: " + ipv4 + " port: " + port, e);
+ errMessage = e.getMessage();
+ }
+ }
+
+ public void disconnect() {
+ logger.info("CcapClient: disconnect(): {}:{}", ipv4, port);
+ try {
+ pcmmPdp.disconnect(pcmmPdp.getPepIdString(), new COPSError(ErrorTypes.SHUTTING_DOWN, ErrorTypes.NA));
+ isConnected = false;
+ } catch (COPSException | IOException e) {
+ logger.error("CcapClient: disconnect(): {}:{} FAILED: {}", ipv4, port, e.getMessage());
+ }
+ }
+
+ // TODO - consider returning a new PCMMGateReq object or a future here instead of setting the ID on the old
+ // TODO - request by reference which makes the code more convoluted thus making issues more difficult to track down.
+ public Boolean sendGateSet(final PCMMGateReq gateReq) {
+ logger.info("CcapClient: sendGateSet(): {}:{} => {}", ipv4, port, gateReq);
+ try {
+ 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());
+ } catch (COPSPdpException e) {
+ logger.error("CcapClient: sendGateSet(): {}:{} => {} FAILED:", ipv4, port, gateReq, e);
+ }
+ // and save it back to the gateRequest object for gate delete later
+ gateReq.setGateID(pcmmSender.getGateID());
+
+ // TODO - determine why this method is always returning true???
+ return true;
+ }
+
+ public Boolean sendGateDelete(final PCMMGateReq gateReq) {
+ logger.info("CcapClient: sendGateDelete(): {}:{} => {}", ipv4, port, gateReq);
+ try {
+ pcmmSender.sendGateDelete(gateReq);
+ } catch (COPSPdpException e) {
+ logger.error("CcapClient: sendGateDelete(): {}:{} => {} FAILED: {}", ipv4, port, gateReq, e.getMessage());
+ }
+ return true;
+ }
+ }
+}
+
--- /dev/null
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.Ccap;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.Qos;
+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.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.Apps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.AppsKey;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.Subs;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.gates.apps.SubsKey;
+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.gates.apps.subs.GatesKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.pcmm.rcd.IPCMMClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.concurrent.ThreadSafe;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Called by ODL framework to start this bundle.
+ *
+ * This class is responsible for processing messages received from ODL's restconf interface.
+ * TODO - Remove some of these state maps and move some of this into the PCMMService
+ */
+@ThreadSafe
+public class PacketcableProvider implements DataChangeListener, AutoCloseable {
+
+ private static final Logger logger = LoggerFactory.getLogger(PacketcableProvider.class);
+
+ // keys to the /restconf/config/packetcable:ccap and /restconf/config/packetcable:qos config datastore
+ public static final InstanceIdentifier<Ccap> ccapIID = InstanceIdentifier.builder(Ccap.class).build();
+ public static final InstanceIdentifier<Qos> qosIID = InstanceIdentifier.builder(Qos.class).build();
+
+ /**
+ * The ODL object used to broker messages throughout the framework
+ */
+ private final DataBroker dataBroker;
+
+ /**
+ * The thread pool executor
+ */
+ private final ExecutorService executor;
+
+ // TODO - Revisit these maps and remove the ones no longer necessary
+ private final Map<String, Ccaps> ccapMap = new ConcurrentHashMap<>();
+ private final Map<String, Gates> gateMap = new ConcurrentHashMap<>();
+ private final Map<String, String> gateCcapMap = new ConcurrentHashMap<>();
+ private final Map<Subnet, Ccaps> subscriberSubnetsMap = new ConcurrentHashMap<>();
+ private final Map<ServiceClassName, List<Ccaps>> downstreamScnMap = new ConcurrentHashMap<>();
+ private final Map<ServiceClassName, List<Ccaps>> upstreamScnMap = new ConcurrentHashMap<>();
+
+ /**
+ * Holds a PCMMService object for each CCAP being managed.
+ */
+ private final Map<Ccaps, PCMMService> pcmmServiceMap = new ConcurrentHashMap<>();
+
+ /**
+ * Constructor
+ */
+ public PacketcableProvider(final DataBroker dataBroker) {
+ logger.info("Starting provider");
+ this.dataBroker = dataBroker;
+ executor = Executors.newCachedThreadPool();
+ }
+
+ /**
+ * Implemented from the AutoCloseable interface.
+ */
+ @Override
+ public void close() throws ExecutionException, InterruptedException {
+ executor.shutdown();
+ if (dataBroker != null) {
+ // remove our config datastore instances
+ 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();
+ }
+ }
+
+ public InetAddress getInetAddress(final String subId){
+ try {
+ return InetAddress.getByName(subId);
+ } catch (UnknownHostException e) {
+ logger.error("getInetAddress: {} FAILED: {}", subId, e.getMessage());
+ return null;
+ }
+ }
+
+ private String getIpPrefixStr(final IpPrefix ipPrefix) {
+ final Ipv4Prefix ipv4 = ipPrefix.getIpv4Prefix();
+ if (ipv4 != null) {
+ return ipv4.getValue();
+ } else {
+ return ipPrefix.getIpv6Prefix().getValue();
+ }
+ }
+
+ private void updateCcapMaps(final Ccaps ccap) {
+ // add ccap to the subscriberSubnets map
+ for (final IpPrefix ipPrefix : ccap.getSubscriberSubnets()) {
+ try {
+ subscriberSubnetsMap.put(Subnet.createInstance(getIpPrefixStr(ipPrefix)), ccap);
+ } catch (UnknownHostException e) {
+ logger.error("updateSubscriberSubnets: {}:{} FAILED: {}", ipPrefix, ccap, e.getMessage());
+ }
+ }
+ // ccap to upstream SCN map
+ for (final ServiceClassName scn : ccap.getUpstreamScns()) {
+ if (upstreamScnMap.containsKey(scn)) {
+ upstreamScnMap.get(scn).add(ccap);
+ } else {
+ final List<Ccaps> ccapList = new ArrayList<>();
+ ccapList.add(ccap);
+ upstreamScnMap.put(scn, ccapList);
+ }
+ }
+ // ccap to downstream SCN map
+ for (final ServiceClassName scn : ccap.getDownstreamScns()) {
+ if (downstreamScnMap.containsKey(scn)) {
+ downstreamScnMap.get(scn).add(ccap);
+ } else {
+ final List<Ccaps> ccapList = new ArrayList<>();
+ ccapList.add(ccap);
+ downstreamScnMap.put(scn, ccapList);
+ }
+ }
+ }
+
+ private void removeCcapFromAllMaps(final Ccaps ccap) {
+ // remove the ccap from all maps
+ // subscriberSubnets map
+ for (final Map.Entry<Subnet, Ccaps> entry : subscriberSubnetsMap.entrySet()) {
+ if (entry.getValue() == ccap) {
+ subscriberSubnetsMap.remove(entry.getKey());
+ }
+ }
+ // ccap to upstream SCN map
+ for (final Map.Entry<ServiceClassName, List<Ccaps>> entry : upstreamScnMap.entrySet()) {
+ final List<Ccaps> ccapList = entry.getValue();
+ ccapList.remove(ccap);
+ if (ccapList.isEmpty()) {
+ upstreamScnMap.remove(entry.getKey());
+ }
+ }
+ // ccap to downstream SCN map
+ for (final Map.Entry<ServiceClassName, List<Ccaps>> entry : downstreamScnMap.entrySet()) {
+ final List<Ccaps> ccapList = entry.getValue();
+ ccapList.remove(ccap);
+ if (ccapList.isEmpty()) {
+ downstreamScnMap.remove(entry.getKey());
+ }
+ }
+
+ final PCMMService service = pcmmServiceMap.remove(ccap);
+ if (service != null) service.disconect();
+ }
+
+ private Ccaps findCcapForSubscriberId(final InetAddress inetAddr) {
+ Ccaps matchedCcap = null;
+ int longestPrefixLen = -1;
+ for (final Map.Entry<Subnet, Ccaps> entry : subscriberSubnetsMap.entrySet()) {
+ final Subnet subnet = entry.getKey();
+ if (subnet.isInNet(inetAddr)) {
+ int prefixLen = subnet.getPrefixLen();
+ if (prefixLen > longestPrefixLen) {
+ matchedCcap = entry.getValue();
+ longestPrefixLen = prefixLen;
+ }
+ }
+ }
+ return matchedCcap;
+ }
+
+ private ServiceFlowDirection findScnOnCcap(final ServiceClassName scn, final Ccaps ccap) {
+ if (upstreamScnMap.containsKey(scn)) {
+ final List<Ccaps> ccapList = upstreamScnMap.get(scn);
+ if (ccapList.contains(ccap)) {
+ return ServiceFlowDirection.Us;
+ }
+ } else if (downstreamScnMap.containsKey(scn)) {
+ final List<Ccaps> ccapList = downstreamScnMap.get(scn);
+ if (ccapList.contains(ccap)) {
+ return ServiceFlowDirection.Ds;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Implemented from the DataChangeListener interface.
+ */
+
+ private class InstanceData {
+ // CCAP Identity
+ public final Map<InstanceIdentifier<Ccaps>, Ccaps> ccapIidMap = new HashMap<>();
+ // Gate Identity
+ public String subId;
+ public final Map<String, String> gatePathMap = new HashMap<>();
+ public String gatePath;
+ public final Map<InstanceIdentifier<Gates>, Gates> gateIidMap = new HashMap<>();
+ // remove path for either CCAP or Gates
+ public final Set<String> removePathList = new HashSet<>();
+
+ public InstanceData(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+ // only used to parse createdData or updatedData
+ getCcaps(thisData);
+ if (ccapIidMap.isEmpty()) {
+ getGates(thisData);
+ if (! gateIidMap.isEmpty()){
+ gatePath = gatePathMap.get("appId") + "/" + gatePathMap.get("subId");
+ }
+ }
+ }
+
+ public InstanceData(final Set<InstanceIdentifier<?>> thisData) {
+ // only used to parse the removedData paths
+ for (final InstanceIdentifier<?> removeThis : thisData) {
+ getGatePathMap(removeThis);
+ if (gatePathMap.containsKey("ccapId")) {
+ gatePath = gatePathMap.get("ccapId");
+ removePathList.add(gatePath);
+ } else if (gatePathMap.containsKey("gateId")) {
+ gatePath = gatePathMap.get("appId") + "/" + gatePathMap.get("subId") + "/" + gatePathMap.get("gateId");
+ removePathList.add(gatePath);
+ }
+ }
+ }
+ private void getGatePathMap(final InstanceIdentifier<?> thisInstance) {
+ logger.info("onDataChanged().getGatePathMap(): " + thisInstance);
+ try {
+ final InstanceIdentifier<Ccaps> ccapInstance = thisInstance.firstIdentifierOf(Ccaps.class);
+ if (ccapInstance != null) {
+ final CcapsKey ccapKey = InstanceIdentifier.keyOf(ccapInstance);
+ if (ccapKey != null) {
+ gatePathMap.put("ccapId", ccapKey.getCcapId());
+ }
+ } else {
+ // get the gate path keys from the InstanceIdentifier Map key set if they are there
+ final InstanceIdentifier<Apps> appsInstance = thisInstance.firstIdentifierOf(Apps.class);
+ if (appsInstance != null) {
+ final AppsKey appKey = InstanceIdentifier.keyOf(appsInstance);
+ if (appKey != null) {
+ gatePathMap.put("appId", appKey.getAppId());
+ }
+ }
+ final InstanceIdentifier<Subs> subsInstance = thisInstance.firstIdentifierOf(Subs.class);
+ if (subsInstance != null) {
+ final SubsKey subKey = InstanceIdentifier.keyOf(subsInstance);
+ if (subKey != null) {
+ subId = subKey.getSubId();
+ gatePathMap.put("subId", subId);
+ }
+ }
+ final InstanceIdentifier<Gates> gatesInstance = thisInstance.firstIdentifierOf(Gates.class);
+ if (gatesInstance != null) {
+ final GatesKey gateKey = InstanceIdentifier.keyOf(gatesInstance);
+ if (gateKey != null) {
+ gatePathMap.put("gateId", gateKey.getGateId());
+ }
+ }
+ }
+ } catch (ClassCastException err) {
+ logger.warn("Unexpected exception", err);
+ }
+ }
+
+ private void getCcaps(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+ 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());
+ }
+ }
+ }
+
+ private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+ logger.info("onDataChanged().getGates(): " + thisData);
+ 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);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+ logger.info("onDataChanged");
+ // Determine what change action took place by looking at the change object's InstanceIdentifier sets
+ // and validate all instance data
+ if (!change.getCreatedData().isEmpty()) {
+ if (!new ValidateInstanceData(dataBroker, change.getCreatedData()).validateYang()) {
+ // leave now -- a bad yang object has been detected and a response object has been inserted
+ return;
+ }
+ onCreate(new InstanceData(change.getCreatedData()));
+ } else if (!change.getRemovedPaths().isEmpty()) {
+ onRemove(new InstanceData(change.getRemovedPaths()));
+ } else if (!change.getUpdatedData().isEmpty()) {
+ if (new ValidateInstanceData(dataBroker, change.getUpdatedData()).isResponseEcho()) {
+ // leave now -- this is an echo of the inserted response object
+ return;
+ }
+ onUpdate(new InstanceData(change.getUpdatedData()));
+ } else {
+ // we should not be here -- complain bitterly and return
+ logger.error("onDataChanged(): Unknown change action: " + change);
+ }
+ }
+
+ private void onCreate(final InstanceData thisData) {
+ logger.info("onCreate(): " + thisData);
+
+ // get the CCAP parameters
+ String message;
+ if (! thisData.ccapIidMap.isEmpty()) {
+ for (Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : thisData.ccapIidMap.entrySet()) {
+ final Ccaps thisCcap = entry.getValue();
+ // get the CCAP node identity from the Instance Data
+ final String ccapId = thisCcap.getCcapId();
+
+ if (pcmmServiceMap.get(thisCcap) == null) {
+ final PCMMService pcmmService = new PCMMService(IPCMMClient.CLIENT_TYPE, thisCcap);
+ // TODO - may want to use the AMID but for the client type but probably not???
+/*
+ final PCMMService pcmmService = new PCMMService(
+ thisCcap.getAmId().getAmType().shortValue(), thisCcap);
+*/
+ pcmmServiceMap.put(thisCcap, pcmmService);
+ message = pcmmService.addCcap();
+ if (message.contains("200 OK")) {
+ ccapMap.put(ccapId, thisCcap);
+ updateCcapMaps(thisCcap);
+ 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
+ executor.execute(new Response(dataBroker, entry.getKey(), thisCcap, message));
+ } else {
+ logger.error("Already monitoring CCAP - " + thisCcap);
+ break;
+ }
+ }
+ } else {
+ // get the PCMM gate parameters from the ccapId/appId/subId/gateId path in the Maps entry (if new gate)
+ for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : thisData.gateIidMap.entrySet()) {
+ message = null;
+ final Gates gate = entry.getValue();
+ final String gateId = gate.getGateId();
+ final String gatePathStr = thisData.gatePath + "/" + gateId ;
+ final InetAddress subId = getInetAddress(thisData.subId);
+ if (subId != null) {
+ final Ccaps thisCcap = findCcapForSubscriberId(subId);
+ if (thisCcap != null) {
+ final String ccapId = thisCcap.getCcapId();
+ // verify SCN exists on CCAP and force gateSpec.Direction to align with SCN direction
+ final ServiceClassName scn = gate.getTrafficProfile().getServiceClassName();
+ if (scn != null) {
+ final ServiceFlowDirection scnDir = findScnOnCcap(scn, thisCcap);
+ if (scnDir != null) {
+ if (pcmmServiceMap.get(thisCcap) != null) {
+ message = pcmmServiceMap.get(thisCcap).sendGateSet(gatePathStr, subId, gate, scnDir);
+ if (message.contains("200 OK")) {
+ gateMap.put(gatePathStr, gate);
+ gateCcapMap.put(gatePathStr, thisCcap.getCcapId());
+ logger.info("onDataChanged(): created QoS gate {} for {}/{}/{} - {}",
+ gateId, ccapId, gatePathStr, gate, message);
+ logger.info("onDataChanged(): created QoS gate {} for {}/{} - {}",
+ gateId, ccapId, gatePathStr, message);
+ } else {
+ logger.info("onDataChanged(): Unable to create QoS gate {} for {}/{}/{} - {}",
+ gateId, ccapId, gatePathStr, gate, message);
+ logger.error("onDataChanged(): Unable to create QoS gate {} for {}/{} - {}",
+ gateId, ccapId, gatePathStr, message);
+ }
+ } else {
+ logger.error("Unable to locate PCMM Service for CCAP - " + thisCcap);
+ break;
+ }
+ } else {
+ logger.error("PCMMService: sendGateSet(): SCN {} not found on CCAP {} for {}/{}",
+ scn.getValue(), thisCcap, gatePathStr, gate);
+ message = String.format("404 Not Found - SCN %s not found on CCAP %s for %s",
+ scn.getValue(), thisCcap.getCcapId(), gatePathStr);
+ }
+ }
+ } else {
+ final String subIdStr = thisData.subId;
+ message = String.format("404 Not Found - no CCAP found for subscriber %s in %s",
+ subIdStr, gatePathStr);
+ logger.info("onDataChanged(): create QoS gate {} FAILED: no CCAP found for subscriber {}: @ {}/{}",
+ gateId, subIdStr, gatePathStr, gate);
+ logger.error("onDataChanged(): create QoS gate {} FAILED: no CCAP found for subscriber {}: @ {}",
+ gateId, subIdStr, gatePathStr);
+ }
+ } else {
+ final String subIdStr = thisData.subId;
+ message = String.format("400 Bad Request - subId must be a valid IP address for subscriber %s in %s",
+ subIdStr, gatePathStr);
+ logger.info("onDataChanged(): create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}/{}",
+ gateId, subIdStr, gatePathStr, gate);
+ logger.error("onDataChanged(): create QoS gate {} FAILED: subId must be a valid IP address for subscriber {}: @ {}",
+ gateId, subIdStr, gatePathStr);
+ }
+ // set the response message in the config gate object using a new thread
+ executor.execute(new Response(dataBroker, entry.getKey(), gate, message));
+ }
+ }
+ }
+
+ private void onRemove(final InstanceData thisData) {
+ logger.info("onRemove(): " + thisData);
+ for (final String gatePathStr: thisData.removePathList) {
+ if (gateMap.containsKey(gatePathStr)) {
+ final Gates thisGate = gateMap.remove(gatePathStr);
+ final String gateId = thisGate.getGateId();
+ final String ccapId = gateCcapMap.remove(gatePathStr);
+ final Ccaps thisCcap = ccapMap.get(ccapId);
+ final PCMMService service = pcmmServiceMap.get(thisCcap);
+ if (service != null) {
+ 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
+ logger.warn("Unable to send to locate PCMMService to send gate delete message with CCAP - "
+ + thisCcap);
+ }
+ }
+ for (final String ccapIdStr: thisData.removePathList) {
+ if (ccapMap.containsKey(ccapIdStr)) {
+ final Ccaps thisCcap = ccapMap.remove(ccapIdStr);
+ removeCcapFromAllMaps(thisCcap);
+ }
+ }
+ }
+
+ private void onUpdate(final InstanceData oldData) {
+ logger.info("onUpdate(): " + oldData);
+ // update operation not allowed -- restore the original config object and complain
+ if (! oldData.ccapIidMap.isEmpty()) {
+ for (final Map.Entry<InstanceIdentifier<Ccaps>, Ccaps> entry : oldData.ccapIidMap.entrySet()) {
+ final Ccaps ccap = entry.getValue();
+ final String ccapId = ccap.getCcapId();
+ String message = String.format("405 Method Not Allowed - %s: CCAP update not permitted (use delete); ",
+ ccapId);
+ // push new error message onto existing response
+ message += ccap.getResponse();
+ // set the response message in the config object using a new thread -- also restores the original data
+ executor.execute(new Response(dataBroker, entry.getKey(), ccap, message));
+ logger.error("onDataChanged(): CCAP update not permitted {}/{}", ccapId, ccap);
+ }
+ } else {
+ for (final Map.Entry<InstanceIdentifier<Gates>, Gates> entry : oldData.gateIidMap.entrySet()) {
+ final Gates gate = entry.getValue();
+ final String gatePathStr = oldData.gatePath + "/" + gate.getGateId() ;
+ String message = String.format("405 Method Not Allowed - %s: QoS Gate update not permitted (use delete); ", gatePathStr);
+ // push new error message onto existing response
+ message += gate.getResponse();
+ // set the response message in the config object using a new thread -- also restores the original data
+ executor.execute(new Response(dataBroker, entry.getKey(), gate, message));
+ logger.error("onDataChanged(): QoS Gate update not permitted: {}/{}", gatePathStr, gate);
+ }
+ }
+ }
+
+}
--- /dev/null
+/**
+ * The Response object inserts a "response" message object into the given CCAP or Gate object in the
+ * config data store.
+ *
+ * N.B. Updates to the config datastore must be run in a separate thread from the onDataChange() notification.
+ * Therefore, the Response object must always be invoked via executor.execute(resonse) after it is
+ * configured during new Response(dataBroker, ccapIID, ccapbase, message) for example.
+ *
+ * Also note well that when a CCAP or Gate object is updated with this "response" message, it will trigger
+ * another recursive onDataChange() notification seen in the change.getUpdatedData() -- this update must be ignored.
+ */
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.Ccaps;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.CcapsBuilder;
+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.gates.apps.subs.GatesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Response implements Runnable {
+
+ private Logger logger = LoggerFactory.getLogger(Response.class);
+ private DataBroker dataBroker;
+ private String message = null;
+ private InstanceIdentifier<Ccaps> ccapIID = null;
+ private Ccaps ccapBase = null;
+ private InstanceIdentifier<Gates> gateIID = null;
+ private Gates gateBase = null;
+
+ public Response(DataBroker dataBroker, InstanceIdentifier<Ccaps> ccapIID, Ccaps ccapBase, String message) {
+ this.dataBroker = dataBroker;
+ this.ccapIID = ccapIID;
+ this.ccapBase = ccapBase;
+ this.message = message;
+ }
+ public Response(DataBroker dataBroker, InstanceIdentifier<Gates> gateIID, Gates gateBase, String message) {
+ this.dataBroker = dataBroker;
+ this.gateIID = gateIID;
+ this.gateBase = gateBase;
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+ public void setMessage(String message) {
+ this.message = message;
+ }
+ public void addMessage(String message) {
+ this.message += message;
+ }
+ public InstanceIdentifier<Ccaps> getCcapIID() {
+ return ccapIID;
+ }
+ public void setCcapIID(InstanceIdentifier<Ccaps> ccapIID) {
+ this.ccapIID = ccapIID;
+ }
+ public Ccaps getCcapBase() {
+ return ccapBase;
+ }
+ public void setCcapBase(Ccaps ccapBase) {
+ this.ccapBase = ccapBase;
+ }
+ public InstanceIdentifier<Gates> getGateIID() {
+ return gateIID;
+ }
+ public void setGateIID(InstanceIdentifier<Gates> gateIID) {
+ this.gateIID = gateIID;
+ }
+ public Gates getGateBase() {
+ return gateBase;
+ }
+ public void setGateBase(Gates gateBase) {
+ this.gateBase = gateBase;
+ }
+
+ @SuppressWarnings("deprecation")
+ public void setResponse(InstanceIdentifier<Ccaps> ccapIID, Ccaps ccapBase, String message) {
+ CcapsBuilder ccapBuilder = new CcapsBuilder(ccapBase);
+ ccapBuilder.setResponse(message);
+ Ccaps ccap = ccapBuilder.build();
+ WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
+ writeTx.merge(LogicalDatastoreType.CONFIGURATION, ccapIID, ccap, true);
+ writeTx.commit();
+ logger.debug("Response.setResponse(ccap) complete {} {} {}", message, ccap, ccapIID);
+ }
+ @SuppressWarnings("deprecation")
+ public void setResponse(InstanceIdentifier<Gates> gateIID, Gates gateBase, String message) {
+ GatesBuilder gateBuilder = new GatesBuilder(gateBase);
+ gateBuilder.setResponse(message);
+ Gates gate = gateBuilder.build();
+ WriteTransaction writeTx = dataBroker.newWriteOnlyTransaction();
+ writeTx.merge(LogicalDatastoreType.CONFIGURATION, gateIID, gate, true);
+ writeTx.commit();
+ logger.debug("Response.setResponse(gate) complete: {} {} {}", message, gate, gateIID);
+ }
+
+ @Override
+ public void run() {
+ if (ccapIID != null) {
+ setResponse(ccapIID, ccapBase, message);
+ } else if (gateIID != null) {
+ setResponse(gateIID, gateBase, message);
+ } else {
+ logger.error("Unknown Response: must be for a CCAP or Gate instance");
+ }
+ }
+}
+
--- /dev/null
+package org.opendaylight.controller.packetcable.provider;
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author c3oe.de, based on snippets from Scott Plante, John Kugelmann
+ */
+public class Subnet
+{
+ final private int bytesSubnetCount;
+ final private BigInteger bigMask;
+ final private BigInteger bigSubnetMasked;
+ final private int prefixLen;
+
+ /** For use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57" */
+ public Subnet( final InetAddress subnetAddress, final int bits )
+ {
+ this.prefixLen = bits;
+ this.bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
+ this.bigMask = BigInteger.valueOf( -1 ).shiftLeft( this.bytesSubnetCount*8 - bits ); // mask = -1 << 32 - bits
+ this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
+ }
+
+ /** For use via format "192.168.0.0/255.255.255.0" or single address */
+ public Subnet( final InetAddress subnetAddress, final InetAddress mask )
+ {
+ this.bytesSubnetCount = subnetAddress.getAddress().length;
+ this.bigMask = null == mask ? BigInteger.valueOf( -1 ) : new BigInteger( mask.getAddress() ); // no mask given case is handled here.
+ this.bigSubnetMasked = new BigInteger( subnetAddress.getAddress() ).and( this.bigMask );
+ int lowestSetBit = bigMask.getLowestSetBit();
+ this.prefixLen = lowestSetBit == -1 ? 0 : 32 - lowestSetBit;
+ }
+
+ /**
+ * Subnet factory method.
+ * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
+ * or single address or "2001:db8:85a3:880:0:0:0:0/57"
+ * @return a new instance
+ * @throws UnknownHostException thrown if unsupported subnet mask.
+ */
+ public static Subnet createInstance( final String subnetMask )
+ throws UnknownHostException
+ {
+ final String[] stringArr = subnetMask.split("/");
+ if ( 2 > stringArr.length )
+ return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), null);
+ else if ( stringArr[ 1 ].contains(".") || stringArr[ 1 ].contains(":") )
+ return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), InetAddress.getByName( stringArr[ 1 ] ) );
+ else
+ return new Subnet( InetAddress.getByName( stringArr[ 0 ] ), Integer.parseInt( stringArr[ 1 ] ) );
+ }
+
+ public int getPrefixLen() {
+ return prefixLen;
+ }
+
+ public boolean isInNet( final InetAddress address )
+ {
+ final byte[] bytesAddress = address.getAddress();
+ if ( this.bytesSubnetCount != bytesAddress.length )
+ return false;
+ final BigInteger bigAddress = new BigInteger( bytesAddress );
+ return bigAddress.and( this.bigMask ).equals( this.bigSubnetMasked );
+ }
+
+ @Override
+ final public boolean equals( Object obj )
+ {
+ if ( ! (obj instanceof Subnet) )
+ return false;
+ final Subnet other = (Subnet)obj;
+ return this.bigSubnetMasked.equals( other.bigSubnetMasked ) &&
+ this.bigMask.equals( other.bigMask ) &&
+ this.bytesSubnetCount == other.bytesSubnetCount;
+ }
+
+ @Override
+ final public int hashCode()
+ {
+ return this.bytesSubnetCount;
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder buf = new StringBuilder();
+ bigInteger2IpString( buf, this.bigSubnetMasked, this.bytesSubnetCount );
+ buf.append( '/' );
+ bigInteger2IpString( buf, this.bigMask, this.bytesSubnetCount );
+ return buf.toString();
+ }
+
+ static private void bigInteger2IpString( final StringBuilder buf, final BigInteger bigInteger, final int displayBytes )
+ {
+ final boolean isIPv4 = 4 == displayBytes;
+ byte[] bytes = bigInteger.toByteArray();
+ int diffLen = displayBytes - bytes.length;
+ final byte fillByte = 0 > (int)bytes[ 0 ] ? (byte)0xFF : (byte)0x00;
+
+ int integer;
+ for ( int i = 0; i < displayBytes; i++ )
+ {
+ if ( 0 < i && ! isIPv4 && i % 2 == 0 )
+ buf.append( ':' );
+ else if ( 0 < i && isIPv4 )
+ buf.append( '.' );
+ integer = 0xFF & (i < diffLen ? fillByte : bytes[ i - diffLen ]);
+ if ( ! isIPv4 && 0x10 > integer )
+ buf.append( '0' );
+ buf.append( isIPv4 ? integer : Integer.toHexString( integer ) );
+ }
+ }
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Validate all instance data received from the config datastore via the onDataChange() notification.
+ *
+ * N.B. that yang typedefs are not validated when a PUT operation places them into the config datastore.
+ * This means that they can arrive at onDataChange() with invalid values.
+ *
+ * In particular integer range values and string patterns (such as IP prefix/len) are not checked
+ * and accessing these values via any object.getValue() method call will cause an exception (as yang
+ * finally gets around to actually enforcing the typedef).
+ */
+package org.opendaylight.controller.packetcable.provider;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.*;
+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.CcapsBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmId;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.AmIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.Connection;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.ccap.attributes.ConnectionBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.classifier.ExtClassifierBuilder;
+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.gate.spec.GateSpecBuilder;
+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.gates.apps.subs.GatesBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6Classifier;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ipv6.classifier.Ipv6ClassifierBuilder;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfile;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.traffic.profile.TrafficProfileBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class ValidateInstanceData {
+
+ private final static Logger logger = LoggerFactory.getLogger(ValidateInstanceData.class);
+
+ // Final members
+ private final DataBroker dataBroker;
+ private final ExecutorService executor;
+
+ // Gate Identities
+ private final Map<InstanceIdentifier<Gates>, Gates> gateIidMap;
+
+ // CCAP Identity
+ private transient Ccaps ccap;
+ private transient InstanceIdentifier<Ccaps> ccapIID;
+
+ public ValidateInstanceData(final DataBroker dataBroker, final Map<InstanceIdentifier<?>, DataObject> thisData) {
+ executor = Executors.newCachedThreadPool();
+ this.dataBroker = dataBroker;
+ getCcap(thisData);
+
+ // Must be instantiated prior to retreiving the gates below
+ gateIidMap = new ConcurrentHashMap<>();
+
+ // TODO FIXME - this value is always null???
+ if (ccap == null) {
+ getGates(thisData);
+ }
+ }
+ public boolean isResponseEcho() {
+ // see if there is a response object in the updated data
+ // if so this is an echo of the response message insertion so our caller can exit right away
+ if (ccap != null && ccap.getResponse() != null) {
+ return true;
+ } else if (! gateIidMap.isEmpty() && gateIidMap.values().iterator().next().getResponse() != null) {
+ return true;
+ }
+ return false;
+ }
+ public boolean validateYang() {
+ final String badText = "400 Bad Request - Invalid Element Values in json object - ";
+ if (isResponseEcho()) {
+ // don't validiate the echo again
+ return true;
+ }
+ if (ccap != null) {
+ Response response = new Response(dataBroker, ccapIID, ccap, badText);
+ if (! validateCcap(ccap, response)) {
+ logger.error("Validate CCAP {} failed - {}", ccap.getCcapId(), response.getMessage());
+ executor.execute(response);
+ return false;
+ }
+ } else if (! gateIidMap.isEmpty()) {
+ for (Map.Entry<InstanceIdentifier<Gates>, Gates> entry : gateIidMap.entrySet()) {
+ InstanceIdentifier<Gates> gateIID = entry.getKey();
+ Gates gate = entry.getValue();
+ Response response = new Response(dataBroker, gateIID, gate, badText);
+ if (! validateGate(gate, response)) {
+ logger.error("Validate Gate {} failed - {}", gate.getGateId(), response.getMessage());
+ executor.execute(response);
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private void getCcap(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+ if (entry.getValue() instanceof Ccaps) {
+ ccap = (Ccaps)entry.getValue();
+ // TODO FIXME - ClassCastException waiting to occur here!!!
+ ccapIID = (InstanceIdentifier<Ccaps>) entry.getKey();
+ }
+ }
+ }
+
+ private void getGates(final Map<InstanceIdentifier<?>, DataObject> thisData) {
+ for (final Map.Entry<InstanceIdentifier<?>, DataObject> entry : thisData.entrySet()) {
+ if (entry.getValue() instanceof Gates) {
+ final Gates gate = (Gates)entry.getValue();
+ // TODO FIXME - ClassCastException waiting to occur here!!!
+ final InstanceIdentifier<Gates> gateIID = (InstanceIdentifier<Gates>)entry.getKey();
+ gateIidMap.put(gateIID, gate);
+ }
+ }
+ }
+ private String validateMethod(final Class<?> thisClass, final Object thisObj, final String methodName) {
+ try {
+ final Method method = thisClass.getMethod(methodName);
+ method.invoke(thisObj);
+ } catch (IllegalArgumentException e) {
+ return e.getMessage();
+ } catch (Exception e) {
+ return " ";
+// error = String.format("%s.%s(): Method failed: %s ", thisClass.getSimpleName(), methodName, e.getMessage());
+ }
+ return null;
+ }
+
+ private boolean validateGateSpec(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+ // gate-spec
+ String message = "";
+ String error;
+ boolean valid = true;
+ GateSpec gateSpec = gate.getGateSpec();
+ if (gateSpec != null) {
+ final ServiceFlowDirection dir;
+ error = validateMethod(GateSpec.class, gateSpec, "getDirection");
+ if (error == null) {
+ dir = gateSpec.getDirection();
+ if (dir != null) {
+ if (gate.getTrafficProfile().getServiceClassName() != null) {
+ message += " gate-spec.direction not allowed for traffic-profile.SCN;";
+ valid = false;
+ }
+ }
+ } else {
+ message += " gate-spec.direction invalid: must be 'us' or 'ds' -" + error;
+ dir = null;
+ valid = false;
+ }
+ final TosByte tosByte;
+ error = validateMethod(GateSpec.class, gateSpec, "getDscpTosOverwrite");
+ if (error == null) {
+ tosByte = gateSpec.getDscpTosOverwrite();
+ } else {
+ message += " gate-spec.dscp-tos-overwrite invalid: " + error;
+ tosByte = null;
+ valid = false;
+ }
+ final TosByte tosMask;
+ error = validateMethod(GateSpec.class, gateSpec, "getDscpTosMask");
+ if (error == null) {
+ tosMask = gateSpec.getDscpTosMask();
+ if (tosByte != null && tosMask == null) {
+ message += " gate-spec.dscp-tos-mask missing;";
+ valid = false;
+ }
+ } else {
+ message += " gate-spec.dscp-tos-mask invalid: " + error;
+ tosMask = null;
+ valid = false;
+ }
+ if (! valid) {
+ // rebuild the gateSpec with nulls replacing bad values
+ final GateSpecBuilder gateSpecBuilder = new GateSpecBuilder();
+ gateSpecBuilder.setDirection(dir);
+ gateSpecBuilder.setDscpTosOverwrite(tosByte);
+ gateSpecBuilder.setDscpTosMask(tosMask);
+ gateSpec = gateSpecBuilder.build();
+ // update the gate
+ gateBuilder.setGateSpec(gateSpec);
+ }
+ }
+ if (! valid) {
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ private boolean validateTrafficProfile(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+ // traffic-profile
+ String message = "";
+ boolean valid = true;
+ TrafficProfile profile = gate.getTrafficProfile();
+ if (profile == null) {
+ message += " traffic-profile is required;";
+ valid = false;
+ } else {
+ final ServiceClassName scn;
+ final String error = validateMethod(TrafficProfile.class, profile, "getServiceClassName");
+ if (error == null) {
+ scn = profile.getServiceClassName();
+ if (scn == null) {
+ message += " traffic-profile.service-class-name missing;";
+ valid = false;
+ }
+ } else {
+ message += " traffic-profile.service-class-name invalid: must be 2-16 characters " + error;
+ scn = null;
+ valid = false;
+ }
+ if (! valid) {
+ final TrafficProfileBuilder profileBuilder = new TrafficProfileBuilder();
+ // TODO FIXME - scn is always null???
+ profileBuilder.setServiceClassName(scn);
+ profile = profileBuilder.build();
+ // update the gate
+ gateBuilder.setTrafficProfile(profile);
+ }
+ }
+ if (! valid) {
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ // TODO FIXME - Break this method apart
+ private boolean validateClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+ // validate classifier
+ String message = "";
+ boolean valid = true;
+ int count = 0;
+ Classifier classifier = gate.getClassifier();
+ // SIP
+ final Ipv4Address sip;
+ String error = validateMethod(Classifier.class, classifier, "getSrcIp");
+ if (error == null) {
+ sip = classifier.getSrcIp();
+ count++;
+ } else {
+ message += " classifier.srcIp invalid: - " + error;
+ sip = null;
+ valid = false;
+ }
+ // DIP
+ final Ipv4Address dip;
+ error = validateMethod(Classifier.class, classifier, "getDstIp");
+ if (error == null) {
+ dip = classifier.getDstIp();
+ count++;
+ } else {
+ message += " classifier.dstIp invalid: - " + error;
+ dip = null;
+ valid = false;
+ }
+ // Protocol
+ final TpProtocol proto;
+ error = validateMethod(Classifier.class, classifier, "getProtocol");
+ if (error == null) {
+ proto = classifier.getProtocol();
+ count++;
+ } else {
+ message += " classifier.protocol invalid: - " + error;
+ proto = null;
+ valid = false;
+ }
+ // Source Port
+ final PortNumber sport;
+ error = validateMethod(Classifier.class, classifier, "getSrcPort");
+ if (error == null) {
+ sport = classifier.getSrcPort();
+ count++;
+ } else {
+ message += " classifier.srcPort invalid: - " + error;
+ sport = null;
+ valid = false;
+ }
+ // Destination Port
+ final PortNumber dport;
+ error = validateMethod(Classifier.class, classifier, "getDstPort");
+ if (error == null) {
+ dport = classifier.getDstPort();
+ count++;
+ } else {
+ message += " classifier.dstPort invalid: - " + error;
+ dport = null;
+ valid = false;
+ }
+ // TOS
+ final TosByte tosByte;
+ error = validateMethod(Classifier.class, classifier, "getTosByte");
+ if (error == null) {
+ tosByte = classifier.getTosByte();
+ count++;
+ } else {
+ message += " classifier.tosByte invalid: " + error;
+ tosByte = null;
+ valid = false;
+ }
+ final TosByte tosMask;
+ error = validateMethod(Classifier.class, classifier, "getTosMask");
+ if (error == null) {
+ tosMask = classifier.getTosMask();
+ if (tosByte != null && tosMask == null) {
+ message += " classifier.tosMask missing;";
+ valid = false;
+ }
+ } else {
+ message += " classifier.tosMask invalid: " + error;
+ tosMask = null;
+ valid = false;
+ }
+ if (count == 0) {
+ message += " classifer must have at least one match field";
+ valid = false;
+ }
+ if (! valid) {
+ final ClassifierBuilder cBuilder = new ClassifierBuilder();
+ cBuilder.setSrcIp(sip);
+ cBuilder.setDstIp(dip);
+ cBuilder.setProtocol(proto);
+ cBuilder.setSrcPort(sport);
+ cBuilder.setDstPort(dport);
+ cBuilder.setTosByte(tosByte);
+ cBuilder.setTosMask(tosMask);
+ classifier = cBuilder.build();
+ gateBuilder.setClassifier(classifier);
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ // TODO FIXME - breakup this method
+ private boolean validateExtClassifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+ // validate ext-classifier
+ String message = "";
+ String error;
+ boolean valid = true;
+ int count = 0;
+ ExtClassifier extClassifier = gate.getExtClassifier();
+ // SIP & mask
+ final Ipv4Address sip;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIp");
+ if (error == null) {
+ sip = extClassifier.getSrcIp();
+ count++;
+ } else {
+ message += " ext-classifier.srcIp invalid: - " + error;
+ sip = null;
+ valid = false;
+ }
+ final Ipv4Address sipMask;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getSrcIpMask");
+ if (error == null) {
+ sipMask = extClassifier.getSrcIpMask();
+ count++;
+ } else {
+ message += " ext-classifier.srcIpMask invalid: - " + error;
+ sipMask = null;
+ valid = false;
+ }
+ if (sip != null && sipMask == null) {
+ message += " ext-classifier.srcIpMask missing";
+ valid = false;
+ }
+ // DIP & mask
+ final Ipv4Address dip;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getDstIp");
+ if (error == null) {
+ dip = extClassifier.getDstIp();
+ count++;
+ } else {
+ message += " ext-classifier.dstIp invalid: - " + error;
+ dip = null;
+ valid = false;
+ }
+ final Ipv4Address dipMask;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getDstIpMask");
+ if (error == null) {
+ dipMask = extClassifier.getDstIpMask();
+ count++;
+ } else {
+ message += " ext-classifier.srcIpMask invalid: - " + error;
+ dipMask = null;
+ valid = false;
+ }
+ if (dip != null && dipMask == null) {
+ message += " ext-classifier.dstIpMask missing;";
+ valid = false;
+ }
+ // Protocol
+ final TpProtocol proto;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getProtocol");
+ if (error == null) {
+ proto = extClassifier.getProtocol();
+ count++;
+ } else {
+ message += " ext-classifier.protocol invalid: - " + error;
+ proto = null;
+ valid = false;
+ }
+ // Source port range
+ final PortNumber sportStart;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortStart");
+ if (error == null) {
+ sportStart = extClassifier.getSrcPortStart();
+ count++;
+ } else {
+ message += " ext-classifier.srcPortStart invalid: - " + error;
+ sportStart = null;
+ valid = false;
+ }
+ final PortNumber sportEnd;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getSrcPortEnd");
+ if (error == null) {
+ sportEnd = extClassifier.getSrcPortEnd();
+ count++;
+ } else {
+ message += " ext-classifier.srcPortEnd invalid: - " + error;
+ sportEnd = null;
+ valid = false;
+ }
+ if (sportStart != null && sportEnd != null) {
+ if (sportStart.getValue() > sportEnd.getValue()) {
+ message += " ext-classifier.srcPortStart greater than srcPortEnd";
+ valid = false;
+ }
+ }
+ // Destination port range
+ final PortNumber dportStart;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortStart");
+ if (error == null) {
+ dportStart = extClassifier.getDstPortStart();
+ count++;
+ } else {
+ message += " ext-classifier.dstPortStart invalid: - " + error;
+ dportStart = null;
+ valid = false;
+ }
+ final PortNumber dportEnd;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getDstPortEnd");
+ if (error == null) {
+ dportEnd = extClassifier.getDstPortEnd();
+ count++;
+ } else {
+ message += " ext-classifier.dstPortEnd invalid: - " + error;
+ dportEnd = null;
+ valid = false;
+ }
+ if (dportStart != null && dportEnd != null) {
+ if (dportStart.getValue() > dportEnd.getValue()) {
+ message += " ext-classifier.dstPortStart greater than dstPortEnd";
+ valid = false;
+ }
+ }
+ // TOS byte
+ final TosByte tosByte;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getTosByte");
+ if (error == null) {
+ tosByte = extClassifier.getTosByte();
+ count++;
+ } else {
+ message += " ext-classifier.tosByte invalid: " + error;
+ tosByte = null;
+ valid = false;
+ }
+ final TosByte tosMask;
+ error = validateMethod(ExtClassifier.class, extClassifier, "getTosMask");
+ if (error == null) {
+ tosMask = extClassifier.getTosMask();
+ if (tosByte != null && tosMask == null) {
+ message += " ext-classifier.tosMask missing;";
+ valid = false;
+ }
+ } else {
+ message += " ext-classifier.tosMask invalid: " + error;
+ tosMask = null;
+ valid = false;
+ }
+ if (count == 0) {
+ message += " ext-classifer must have at least one match field";
+ valid = false;
+ }
+ if (! valid) {
+ final ExtClassifierBuilder cBuilder = new ExtClassifierBuilder();
+ cBuilder.setSrcIp(sip);
+ cBuilder.setSrcIpMask(sipMask);
+ cBuilder.setDstIp(dip);
+ cBuilder.setDstIpMask(dipMask);
+ cBuilder.setProtocol(proto);
+ cBuilder.setSrcPortStart(sportStart);
+ cBuilder.setSrcPortEnd(sportEnd);
+ cBuilder.setDstPortStart(dportStart);
+ cBuilder.setDstPortEnd(dportEnd);
+ cBuilder.setTosByte(tosByte);
+ cBuilder.setTosMask(tosMask);
+ extClassifier = cBuilder.build();
+ gateBuilder.setExtClassifier(extClassifier);
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ // TODO FIXME - break apart this method.
+ private boolean validateIpv6Classifier(final Gates gate, final GatesBuilder gateBuilder, final Response response) {
+ // validate ipv6-classifier
+ String message = "";
+ String error;
+ boolean valid = true;
+ int count = 0;
+ Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
+ // Source IPv6 prefix
+ final Ipv6Prefix sip6;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcIp6");
+ if (error == null) {
+ sip6 = ipv6Classifier.getSrcIp6();
+ count++;
+ } else {
+ message += " ipv6-classifier.srcIp invalid: - " + error;
+ sip6 = null;
+ valid = false;
+ }
+ // Destination IPv6 prefix
+ final Ipv6Prefix dip6;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstIp6");
+ if (error == null) {
+ dip6 = ipv6Classifier.getDstIp6();
+ count++;
+ } else {
+ message += " ipv6-classifier.dstIp invalid: - " + error;
+ dip6 = null;
+ valid = false;
+ }
+ // Flow label
+ Long flowLabel;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getFlowLabel");
+ if (error == null) {
+ flowLabel = ipv6Classifier.getFlowLabel();
+ if (flowLabel > 1048575) {
+ message += " ipv6-classifier.flowLabel invalid: - must be 0..1048575";
+ flowLabel = null;
+ valid = false;
+ } else {
+ count++;
+ }
+ } else {
+ message += " ipv6-classifier.flowLabel invalid: - " + error;
+ flowLabel = null;
+ valid = false;
+ }
+ // Next Hdr
+ final TpProtocol nxtHdr;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getNextHdr");
+ if (error == null) {
+ nxtHdr = ipv6Classifier.getNextHdr();
+ count++;
+ } else {
+ message += " ipv6-classifier.nextHdr invalid: - " + error;
+ nxtHdr = null;
+ valid = false;
+ }
+ // Source port range
+ final PortNumber sportStart;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortStart");
+ if (error == null) {
+ sportStart = ipv6Classifier.getSrcPortStart();
+ count++;
+ } else {
+ message += " ipv6-classifier.srcPortStart invalid: - " + error;
+ sportStart = null;
+ valid = false;
+ }
+ final PortNumber sportEnd;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getSrcPortEnd");
+ if (error == null) {
+ sportEnd = ipv6Classifier.getSrcPortEnd();
+ count++;
+ } else {
+ message += " ipv6-classifier.srcPortEnd invalid: - " + error;
+ sportEnd = null;
+ valid = false;
+ }
+ if (sportStart != null && sportEnd != null) {
+ if (sportStart.getValue() > sportEnd.getValue()) {
+ message += " ipv6-classifier.srcPortStart greater than srcPortEnd";
+ valid = false;
+ }
+ }
+ // Destination port range
+ final PortNumber dportStart;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortStart");
+ if (error == null) {
+ dportStart = ipv6Classifier.getDstPortStart();
+ count++;
+ } else {
+ message += " ipv6-classifier.dstPortStart invalid: - " + error;
+ dportStart = null;
+ valid = false;
+ }
+ final PortNumber dportEnd;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getDstPortEnd");
+ if (error == null) {
+ dportEnd = ipv6Classifier.getDstPortEnd();
+ count++;
+ } else {
+ message += " ipv6-classifier.dstPortEnd invalid: - " + error;
+ dportEnd = null;
+ valid = false;
+ }
+ if (dportStart != null && dportEnd != null) {
+ if (dportStart.getValue() > dportEnd.getValue()) {
+ message += " ipv6-classifier.dstPortStart greater than dstPortEnd";
+ valid = false;
+ }
+ }
+ // TC byte
+ final TosByte tcLow;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcLow");
+ if (error == null) {
+ tcLow = ipv6Classifier.getTcLow();
+ count++;
+ } else {
+ message += " ipv6-classifier.tc-low invalid: " + error;
+ tcLow = null;
+ valid = false;
+ }
+ final TosByte tcHigh;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcHigh");
+ if (error == null) {
+ tcHigh = ipv6Classifier.getTcHigh();
+ count++;
+ } else {
+ message += " ipv6-classifier.tc-high invalid: " + error;
+ tcHigh = null;
+ valid = false;
+ }
+ if (tcLow != null && tcHigh != null) {
+ if (tcLow.getValue() > tcHigh.getValue()) {
+ message += " ipv6-classifier.tc-low is greater than tc-high";
+ valid = false;
+ }
+ }
+ final TosByte tcMask;
+ error = validateMethod(Ipv6Classifier.class, ipv6Classifier, "getTcMask");
+ if (error == null) {
+ tcMask = ipv6Classifier.getTcMask();
+ } else {
+ message += " ipv6-classifier.tc-mask invalid: " + error;
+ tcMask = null;
+ valid = false;
+ }
+ if (tcLow != null && tcHigh != null && tcMask == null) {
+ message += " ipv6-classifier.tc-mask missing;";
+ valid = false;
+ }
+ if (count == 0) {
+ message += " ipv6-classifer must have at least one match field";
+ valid = false;
+ }
+ // rebuild ?
+ if (! valid) {
+ final Ipv6ClassifierBuilder cBuilder = new Ipv6ClassifierBuilder();
+ cBuilder.setSrcIp6(sip6);
+ cBuilder.setDstIp6(dip6);
+ cBuilder.setFlowLabel(flowLabel);
+ cBuilder.setNextHdr(nxtHdr);
+ cBuilder.setSrcPortStart(sportStart);
+ cBuilder.setSrcPortEnd(sportEnd);
+ cBuilder.setDstPortStart(dportStart);
+ cBuilder.setDstPortEnd(dportEnd);
+ cBuilder.setTcLow(tcLow);
+ cBuilder.setTcHigh(tcHigh);
+ cBuilder.setTcMask(tcMask);
+ ipv6Classifier = cBuilder.build();
+ gateBuilder.setIpv6Classifier(ipv6Classifier);
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ // TODO FIXME - Do we really want the gate parameter object to be muted by this method?
+ private boolean validateGate(Gates gate, final Response response) {
+ // validate gate elements and null out invalid elements as we go
+ final GatesBuilder gateBuilder = new GatesBuilder();
+ String message = "";
+ boolean rebuild = false;
+ // gate-spec
+ if (! validateGateSpec(gate, gateBuilder, response)) {
+ rebuild = true;
+ }
+ // traffic-profile
+ if (! validateTrafficProfile(gate, gateBuilder, response)) {
+ rebuild = true;
+ }
+ // classifiers (one of legacy classifier, ext-classifier, or ipv6 classifier
+ final Classifier classifier = gate.getClassifier();
+ final ExtClassifier extClassifier = gate.getExtClassifier();
+ final Ipv6Classifier ipv6Classifier = gate.getIpv6Classifier();
+ int count = 0;
+ if (classifier != null) { count++; }
+ if (extClassifier != null) { count++; }
+ if (ipv6Classifier != null) { count++; }
+ if (count < 1){
+ response.addMessage(" Missing classifer: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
+ rebuild = true;
+ } else if (count > 1) {
+ response.addMessage(" Multiple classifiers: must have only 1 of classifier, ext-classifier, or ipv6-classifier");
+ rebuild = true;
+ } else if (count == 1) {
+ if (classifier != null) {
+ // validate classifier
+ if (! validateClassifier(gate, gateBuilder, response)) {
+ rebuild = true;
+ }
+ } else if (extClassifier != null) {
+ //validate ext-classifier
+ if (! validateExtClassifier(gate, gateBuilder, response)) {
+ rebuild = true;
+ }
+ } else if (ipv6Classifier != null) {
+ // TODO FIXME - ipv6Classifier is always null???
+ // validate ipv6-classifier
+ if (! validateIpv6Classifier(gate, gateBuilder, response)) {
+ rebuild = true;
+ }
+ }
+ }
+ // rebuild the gate object with valid data and set the response
+ if (rebuild) {
+ gateBuilder.setGateId(gate.getGateId());
+ gateBuilder.setKey(gate.getKey());
+ // TODO FIXME - the input parameter "gate" is being muted here???
+ gate = gateBuilder.build();
+ response.setGateBase(gate);
+ response.addMessage(message);
+ }
+ return (! rebuild);
+ }
+
+ private boolean validateAmId(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+ // amId
+ String message = "";
+ String error;
+ boolean valid = true;
+ AmId amId = ccap.getAmId();
+ if (amId == null) {
+ message += " amId is required;";
+ valid = false;
+ } else {
+ final Integer amTag;
+ error = validateMethod(AmId.class, amId, "getAmTag");
+ if (error == null) {
+ amTag = amId.getAmTag();
+ if (amTag == null) {
+ message += " amId.amTag missing;";
+ valid = false;
+ }
+ } else {
+ message += " amId.amTag invalid: " + error;
+ amTag = null;
+ valid = false;
+ }
+ final Integer amType;
+ error = validateMethod(AmId.class, amId, "getAmType");
+ if (error == null) {
+ amType = amId.getAmType();
+ if (amType == null) {
+ message += " amId.amType missing;";
+ valid = false;
+ }
+ } else {
+ message += " amId.amType invalid: " + error;
+ amType = null;
+ valid = false;
+ }
+ if (! valid) {
+ final AmIdBuilder amIdBuilder = new AmIdBuilder();
+ amIdBuilder.setAmTag(amTag);
+ amIdBuilder.setAmType(amType);
+ amId = amIdBuilder.build();
+ ccapBuilder.setAmId(amId);
+ }
+ }
+ if (! valid) {
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ private boolean validateConnection(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+ // connection
+ String message = "";
+ String error;
+ boolean valid = true;
+ Connection conn = ccap.getConnection();
+ if (conn == null) {
+ message += " connection is required;";
+ valid = false;
+ } else {
+ // IP address
+ final IpAddress ipAddress;
+ error = validateMethod(Connection.class, conn, "getIpAddress");
+ if (error == null) {
+ ipAddress = conn.getIpAddress();
+ if (ipAddress == null) {
+ message += " connection.ipAddress missing;";
+ valid = false;
+ }
+ } else {
+ message += " connection.ipAddress invalid: " + error;
+ ipAddress = null;
+ valid = false;
+ }
+ // Port number
+ final PortNumber portNum;
+ error = validateMethod(Connection.class, conn, "getPort");
+ if (error == null) {
+ portNum = conn.getPort();
+ } else {
+ message += " connection.port invalid: " + error;
+ portNum = null;
+ valid = false;
+ }
+ if (! valid) {
+ final ConnectionBuilder connBuilder = new ConnectionBuilder();
+ connBuilder.setIpAddress(ipAddress);
+ connBuilder.setPort(portNum);
+ conn = connBuilder.build();
+ ccapBuilder.setConnection(conn);
+ }
+ }
+ if (! valid) {
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ private boolean validateSubscriberSubnets(final Ccaps ccap, final CcapsBuilder ccapBuilder,
+ final Response response) {
+ // subscriber-subnets
+ String message = "";
+ String error;
+ boolean valid = true;
+ List<IpPrefix> subnets = null;
+ error = validateMethod(Ccaps.class, ccap, "getSubscriberSubnets");
+ if (error == null) {
+ subnets = ccap.getSubscriberSubnets();
+ if (subnets == null) {
+ message += " subscriber-subnets is required;";
+ valid = false;
+ }
+ } else {
+ message += " subscriber-subnets contains invalid IpPrefix - must be <ipaddress>/<prefixlen> format;" + error;
+ valid = false;
+ }
+ if (! valid) {
+ // TODO FIXME - subnets is always null???
+ ccapBuilder.setSubscriberSubnets(subnets);
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ private boolean validateUpstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+ // upstream-scns
+ String message = "";
+ String error;
+ boolean valid = true;
+ List<ServiceClassName> usScns = null;
+ error = validateMethod(Ccaps.class, ccap, "getUpstreamScns");
+ if (error == null) {
+ usScns = ccap.getUpstreamScns();
+ if (usScns == null) {
+ message += " upstream-scns is required;";
+ valid = false;
+ }
+ } else {
+ message += " upstream-scns contains invalid SCN - must be 2-16 characters;" + error;
+ valid = false;
+ }
+ if (! valid) {
+ // TODO FIXME - usScns is always null???
+ ccapBuilder.setUpstreamScns(usScns);
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+ private boolean validateDownstreamScns(final Ccaps ccap, final CcapsBuilder ccapBuilder, final Response response) {
+ // downstream-scns
+ String message = "";
+ boolean valid = true;
+ List<ServiceClassName> dsScns = null;
+ final String error = validateMethod(Ccaps.class, ccap, "getDownstreamScns");
+ if (error == null) {
+ dsScns = ccap.getDownstreamScns();
+ if (dsScns == null) {
+ message += " downstream-scns is required;";
+ valid = false;
+ }
+ } else {
+ message += " downstream-scns contains invalid SCN - must be 2-16 characters;" + error;
+ valid = false;
+ }
+ if (! valid) {
+ // TODO FIXME - dsScns is always null???
+ ccapBuilder.setDownstreamScns(dsScns);
+ response.addMessage(message);
+ }
+ return valid;
+ }
+
+
+ // TODO FIXME - Do we really want the ccap parameter object to be muted by this method?
+ private boolean validateCcap(Ccaps ccap, final Response response) {
+ // validate ccap and null out invalid elements as we go
+ final CcapsBuilder ccapBuilder = new CcapsBuilder();
+ String message = "";
+ boolean rebuild = false;
+ // amId
+ if ( ! validateAmId(ccap, ccapBuilder, response)) {
+ rebuild = true;
+ }
+ // connection
+ if ( ! validateConnection(ccap, ccapBuilder, response)) {
+ rebuild = true;
+ }
+ // subscriber-subnets
+ if ( ! validateSubscriberSubnets(ccap, ccapBuilder, response)) {
+ rebuild = true;
+ }
+ // upstream-scns
+ if ( ! validateUpstreamScns(ccap, ccapBuilder, response)) {
+ rebuild = true;
+ }
+ // downstream-scns
+ if ( ! validateDownstreamScns(ccap, ccapBuilder, response)) {
+ rebuild = true;
+ }
+ // rebuild the ccap object with valid data and set the response
+ if (rebuild) {
+ ccapBuilder.setCcapId(ccap.getCcapId());
+ ccapBuilder.setKey(ccap.getKey());
+ // TODO FIXME - the input parameter "ccap" is being muted here???
+ ccap = ccapBuilder.build();
+ response.setCcapBase(ccap);
+ response.addMessage(message);
+ }
+ return (! rebuild);
+ }
+}
+
--- /dev/null
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.packetcable.provider.PacketcableProvider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PacketcableProviderModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131.AbstractPacketcableProviderModule {
+ private static final Logger logger = LoggerFactory.getLogger(PacketcableProviderModule.class);
+
+ public PacketcableProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public PacketcableProviderModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131.PacketcableProviderModule oldModule, java.lang.AutoCloseable oldInstance) {
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ public void customValidation() {
+ // add custom validation form module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ logger.info("Creating PacketcableProvider instance");
+
+ final DataBroker dataBrokerService = getDataBrokerDependency();
+ final PacketcableProvider provider = new PacketcableProvider(dataBrokerService);
+
+ final ListenerRegistration<DataChangeListener> ccapDataChangeListenerRegistration =
+ dataBrokerService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ PacketcableProvider.ccapIID, provider, DataBroker.DataChangeScope.SUBTREE );
+
+ final ListenerRegistration<DataChangeListener> qosDataChangeListenerRegistration =
+ dataBrokerService.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ PacketcableProvider.qosIID, provider, DataBroker.DataChangeScope.SUBTREE );
+
+
+ logger.info("PacketCableProvider Registered with DataBroker");
+ return provider;
+ }
+
+}
--- /dev/null
+/*
+* Generated file
+*
+* Generated from: yang module name: packetcable-policy-server-impl yang module local name: packetcable-policy-server-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Tue Apr 21 12:24:46 MDT 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131;
+public class PacketcableProviderModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.packetcable.packetcable.policy.server.impl.rev140131.AbstractPacketcableProviderModuleFactory {
+
+}
--- /dev/null
+module packetcable-policy-server-impl {
+
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:packetcable:packetcable-policy-server:impl";
+ prefix "packetcable-policy-server-impl";
+
+ import config { prefix config; revision-date 2013-04-05; }
+ import rpc-context { prefix rpcx; revision-date 2013-06-17; }
+ import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
+ import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
+
+ description
+ "This module contains the base YANG definitions for
+ packetcable-policy-server impl implementation.";
+
+ revision "2014-01-31" {
+ description
+ "Initial revision.";
+ }
+
+ // This is the definition of the service implementation as a module identity.
+ identity packetcable-policy-server-impl {
+ base config:module-type;
+ config:java-name-prefix PacketcableProvider;
+ }
+
+ // Augments the 'configuration' choice node under modules/module.
+ augment "/config:modules/config:module/config:configuration" {
+ case packetcable-policy-server-impl {
+ when "/config:modules/config:module/config:type = 'packetcable-policy-server-impl'";
+
+ //wires in the data-broker and rpc services
+ container data-broker {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-async-data-broker;
+ }
+ }
+ }
+ container rpc-registry {
+ uses config:service-ref {
+ refine type {
+ mandatory true;
+ config:required-identity mdsal:binding-rpc-registry;
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.packetcable.provider;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
+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;
+import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.classifier.Classifier;
+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.
+ */
+public class PCMMServiceTest {
+
+ /**
+ * 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();
+
+ cmAddr[0] = 10;
+ cmAddr[1] = 32;
+ cmAddr[2] = 110;
+ cmAddr[3] = (byte)180;
+ }
+
+ @After
+ public void tearDown() {
+ if (icmts != null) icmts.stopServer();
+ }
+
+ @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.assertNotNull(message);
+ Assert.assertTrue(message, message.startsWith("200"));
+ Assert.assertNotNull(service.ccapClient.pcmmPdp.getClientHandle());
+ service.disconect();
+ }
+
+ @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 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(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(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;
+ }
+
+ 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());
+
+ // 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;
+ }
+ }
+
+}
*/
package org.opendaylight.controller.packetcable.provider.processors;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.traffic.profile.best.effort.attributes.BeCommittedEnvelope;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.traffic.profile.rev140908.traffic.profile.best.effort.attributes.BeReservedEnvelope;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.SubscriberIdRpcAddFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.TcpMatchRangesAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.TcpMatchRangesRpcAddFlow;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesAttributes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.UdpMatchRangesRpcAddFlow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.*;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.tcp.match.ranges.attributes.TcpMatchRanges;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packetcable.match.types.rev140909.udp.match.ranges.attributes.UpdMatchRanges;
import org.pcmm.gates.IClassifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
/**
*
* PacketCable data processor
public IClassifier process(Match match) {
ExtendedClassifier classifier = new ExtendedClassifier();
- classifier.setProtocol(IClassifier.Protocol.NONE);
+// classifier.setProtocol(IClassifier.Protocol.NONE);
getUdpMatchRangeValues(match.getAugmentation(UdpMatchRangesRpcAddFlow.class), classifier);
getTcpMatchRangesValues(match.getAugmentation(TcpMatchRangesRpcAddFlow.class), classifier);
SubscriberIdRpcAddFlow subId = match.getAugmentation(SubscriberIdRpcAddFlow.class);
short srcPortStart, srcPortEnd, dstPortStart, dstPortEnd;
srcPortStart = srcPortEnd = dstPortStart = dstPortEnd = 0;
if (tcpRange != null) {
- classifier.setProtocol(IClassifier.Protocol.TCP);
+// classifier.setProtocol(IClassifier.Protocol.TCP);
TcpMatchRanges tcpMatchRanges = tcpRange.getTcpMatchRanges();
PortNumber tcpDestinationPortStart = tcpMatchRanges.getTcpDestinationPortStart();
if (tcpDestinationPortStart != null && tcpDestinationPortStart.getValue() != null)
short srcPortStart, srcPortEnd, dstPortStart, dstPortEnd;
srcPortStart = srcPortEnd = dstPortStart = dstPortEnd = 0;
if (updRange != null) {
- classifier.setProtocol(IClassifier.Protocol.UDP);
+// classifier.setProtocol(IClassifier.Protocol.UDP);
UpdMatchRanges updMatchRanges = updRange.getUpdMatchRanges();
PortNumber udpDestinationPortStart = updMatchRanges.getUdpDestinationPortStart();
if (udpDestinationPortStart != null && udpDestinationPortStart.getValue() != null)
<module>features-packetcable</module>
<module>packetcable-config</module>
<module>packetcable-karaf</module>
+
+ <!-- New modules for the new Arris API -->
+ <module>packetcable-policy-model</module>
+ <module>packetcable-policy-server</module>
+ <module>features-packetcable-policy</module>
+ <module>packetcable-policy-config</module>
+ <module>packetcable-policy-karaf</module>
</modules>
<scm>
<connection>scm:git:ssh://git.opendaylight.org:29418/packetcable.git</connection>