From: Steven Pisarski Date: Thu, 13 Aug 2015 18:52:28 +0000 (-0600) Subject: Refactor PCMM aspects of COPS message data objects. X-Git-Tag: release/beryllium~30 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=commitdiff_plain;h=3e6a8ae8c2dcfa808502f9acf94cad3ba2e28716;hp=a06a930e945e767e04f20486711a666d86d85e4c;p=packetcable.git Refactor PCMM aspects of COPS message data objects. Made immutable, added enumerations & unit tests. Change-Id: I47f44fe2a863d9d933902bc33bb11046613728ef Signed-off-by: Steven Pisarski --- diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java index dd6e88d..5c99ac2 100644 --- a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java +++ b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpDataProcess.java @@ -1,10 +1,10 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ package org.pcmm; -import org.pcmm.gates.ITransactionID; +import org.pcmm.gates.ITransactionID.GateCommandType; import org.pcmm.gates.impl.PCMMGateReq; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,7 +71,7 @@ public class PCMMPdpDataProcess implements COPSPdpDataProcess { public void successReport(final COPSPdpReqStateMan man, final PCMMGateReq gateMsg) { logger.info("Success Report notified."); - if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateDeleteAck ) { + if ( gateMsg.getTransactionID().getGateCommandType().equals(GateCommandType.GATE_DELETE_ACK)) { logger.info("GateDeleteAck: GateID = " + gateMsg.getGateID().getGateID()); if (gateMsg.getGateID().getGateID() == PCMMGlobalConfig.getGateID1()) PCMMGlobalConfig.setGateID1(0); @@ -79,7 +79,7 @@ public class PCMMPdpDataProcess implements COPSPdpDataProcess { PCMMGlobalConfig.setGateID2(0); } - if ( gateMsg.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck ) { + if ( gateMsg.getTransactionID().getGateCommandType().equals(GateCommandType.GATE_SET_ACK)) { logger.info("GateSetAck : GateID = " + gateMsg.getGateID().getGateID()); if (0 == PCMMGlobalConfig.getGateID1()) PCMMGlobalConfig.setGateID1(gateMsg.getGateID().getGateID()); diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java index da1be39..4e19ffb 100644 --- a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java +++ b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpMsgSender.java @@ -1,19 +1,20 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ package org.pcmm; -import org.pcmm.gates.*; -import org.pcmm.gates.IGateSpec.DSCPTOS; -import org.pcmm.gates.IGateSpec.Direction; -import org.pcmm.gates.impl.*; +import org.pcmm.gates.IGateID; +import org.pcmm.gates.IPCMMGate; +import org.pcmm.gates.ITransactionID; +import org.pcmm.gates.ITransactionID.GateCommandType; +import org.pcmm.gates.impl.PCMMGateReq; +import org.pcmm.gates.impl.TransactionID; 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; @@ -22,9 +23,7 @@ import org.umu.cops.stack.COPSObjHeader.CNum; import org.umu.cops.stack.COPSObjHeader.CType; import java.io.IOException; -import java.net.InetAddress; import java.net.Socket; -import java.net.UnknownHostException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -49,7 +48,7 @@ public class PCMMPdpMsgSender extends COPSMsgSender { public final static Logger logger = LoggerFactory.getLogger(PCMMPdpMsgSender.class); - protected short _transactionID; + protected final short _transactionID; protected final short _classifierID; // XXX - this does not need to be here @@ -72,19 +71,10 @@ public class PCMMPdpMsgSender extends COPSMsgSender { public PCMMPdpMsgSender(final short clientType, final short tID, final COPSHandle clientHandle, final Socket sock) { super(clientType, clientHandle, sock); - _transactionID = tID; + _transactionID = tID == 0 ? (short) (Math.random() * hashCode()) : tID; _classifierID = 0; } - /** - * Gets the transaction-id - * - * @return transaction-id value - */ - public short getTransactionID() { - return _transactionID; - } - /** * Gets the gate-id * @@ -100,12 +90,8 @@ public class PCMMPdpMsgSender extends COPSMsgSender { * @throws COPSPdpException */ public void sendGateSet(final IPCMMGate gate) throws COPSPdpException { - final ITransactionID trID = new TransactionID(); - // set transaction ID to gate set - trID.setGateCommandType(ITransactionID.GateSet); - _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID); - trID.setTransactionIdentifier(_transactionID); + final ITransactionID trID = new TransactionID(_transactionID, GateCommandType.GATE_SET); gate.setTransactionID(trID); // retain the transactionId to gate request mapping for gateID recovery after response @@ -136,335 +122,6 @@ public class PCMMPdpMsgSender extends COPSMsgSender { } - /** - * Sends a PCMM GateSet COPS Decision message - * - * @param num - the number - * @throws COPSPdpException - */ - public void sendGateSetDemo(int num) throws COPSPdpException { - 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 IClassifier classifier = new Classifier(); - final IExtendedClassifier eclassifier = new ExtendedClassifier(); - final int trafficRate; - if (num == 1) - trafficRate = PCMMGlobalConfig.DefaultBestEffortTrafficRate; - else - trafficRate = PCMMGlobalConfig.DefaultLowBestEffortTrafficRate; - - final ITrafficProfile trafficProfile = new BestEffortService( - (byte) 7); //BestEffortService.DEFAULT_ENVELOP); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setMaximumSustainedTrafficRate( - trafficRate); - // PCMMGlobalConfig.DefaultLowBestEffortTrafficRate ); - // PCMMGlobalConfig.DefaultBestEffortTrafficRate); - - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setMaximumSustainedTrafficRate( - trafficRate); - // PCMMGlobalConfig.DefaultLowBestEffortTrafficRate ); - // PCMMGlobalConfig.DefaultBestEffortTrafficRate); - - - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setMaximumSustainedTrafficRate( - trafficRate); - // PCMMGlobalConfig.DefaultLowBestEffortTrafficRate ); - // PCMMGlobalConfig.DefaultBestEffortTrafficRate); - - - - // set transaction ID to gate set - trID.setGateCommandType(ITransactionID.GateSet); - _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID); - trID.setTransactionIdentifier(_transactionID); - - amid.setApplicationType((short) 1); - amid.setApplicationMgrTag((short) 1); - gateSpec.setDirection(Direction.UPSTREAM); - gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE); - gateSpec.setTimerT1(PCMMGlobalConfig.GateT1); - gateSpec.setTimerT2(PCMMGlobalConfig.GateT2); - gateSpec.setTimerT3(PCMMGlobalConfig.GateT3); - gateSpec.setTimerT4(PCMMGlobalConfig.GateT4); - - // XXX - if the version major is less than 4 we need to use Classifier - // TODO - Use some variable here or remove... - if (true) { - //eclassifier.setProtocol(IClassifier.Protocol.NONE); -// eclassifier.setProtocol(IClassifier.Protocol.TCP); - try { - InetAddress subIP = InetAddress - .getByName(PCMMGlobalConfig.SubscriberID); - InetAddress srcIP = InetAddress - .getByName(PCMMGlobalConfig.srcIP); - InetAddress dstIP = InetAddress - .getByName(PCMMGlobalConfig.dstIP); - InetAddress mask = InetAddress.getByName("0.0.0.0"); - subscriberID.setSourceIPAddress(subIP); - eclassifier.setSourceIPAddress(srcIP); - eclassifier.setDestinationIPAddress(dstIP); - eclassifier.setIPDestinationMask(mask); - eclassifier.setIPSourceMask(mask); - } catch (UnknownHostException unae) { - logger.error("Error getByName", unae); - } - eclassifier.setSourcePortStart(PCMMGlobalConfig.srcPort); - eclassifier.setSourcePortEnd(PCMMGlobalConfig.srcPort); - eclassifier.setDestinationPortStart(PCMMGlobalConfig.dstPort); - eclassifier.setDestinationPortEnd(PCMMGlobalConfig.dstPort); - eclassifier.setActivationState((byte) 0x01); - // check if we have a stored value of classifierID else we just - // create - // one - // eclassifier.setClassifierID((short) 0x01); - eclassifier.setClassifierID((short) (_classifierID == 0 ? Math - .random() * hashCode() : _classifierID)); - // XXX - testie - // eclassifier.setClassifierID((short) 1); - - eclassifier.setAction((byte) 0x00); - // XXX - temp default until Gate Modify is hacked in - // eclassifier.setPriority(PCMMGlobalConfig.EClassifierPriority); - eclassifier.setPriority((byte) 65); - - } else { -// classifier.setProtocol(IClassifier.Protocol.TCP); - try { - InetAddress subIP = InetAddress - .getByName(PCMMGlobalConfig.SubscriberID); - InetAddress srcIP = InetAddress - .getByName(PCMMGlobalConfig.srcIP); - InetAddress dstIP = InetAddress - .getByName(PCMMGlobalConfig.dstIP); - subscriberID.setSourceIPAddress(subIP); - classifier.setSourceIPAddress(srcIP); - classifier.setDestinationIPAddress(dstIP); - } catch (UnknownHostException unae) { - logger.error("Error getByName", unae); - } - classifier.setSourcePort(PCMMGlobalConfig.srcPort); - classifier.setDestinationPort(PCMMGlobalConfig.dstPort); - } - - gate.setTransactionID(trID); - gate.setAMID(amid); - gate.setSubscriberID(subscriberID); - gate.setGateSpec(gateSpec); - gate.setTrafficProfile(trafficProfile); - gate.setClassifier(eclassifier); - - final byte[] data = gate.getData(); - - final Set decisionSet = new HashSet<>(); - decisionSet.add(new COPSDecision(CType.NA, Command.INSTALL, DecisionFlag.REQERROR)); - final Map> 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(), _handle, decisionMap, null, clientSD); - - // ** Send the GateSet Decision - // ** - try { - decisionMsg.writeData(_sock); - } catch (IOException e) { - logger.error("Failed to send the decision", e); - } - - } - /** - * Sends a PCMM GateSet COPS Decision message - * @throws COPSPdpException - */ - public void sendGateSetBestEffortWithExtendedClassifier() throws COPSPdpException { - 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 IClassifier classifier = new Classifier(); - final IExtendedClassifier eclassifier = new ExtendedClassifier(); - - // XXX check if other values should be provided - // - final ITrafficProfile trafficProfile = new BestEffortService( - (byte) 7); //BestEffortService.DEFAULT_ENVELOP); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setMaximumSustainedTrafficRate( - PCMMGlobalConfig.DefaultLowBestEffortTrafficRate ); - // PCMMGlobalConfig.DefaultBestEffortTrafficRate); - - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - ((BestEffortService) trafficProfile).getReservedEnvelop() - .setMaximumSustainedTrafficRate( - PCMMGlobalConfig.DefaultLowBestEffortTrafficRate ); - // PCMMGlobalConfig.DefaultBestEffortTrafficRate); - - - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - ((BestEffortService) trafficProfile).getCommittedEnvelop() - .setMaximumSustainedTrafficRate( - PCMMGlobalConfig.DefaultLowBestEffortTrafficRate ); - // PCMMGlobalConfig.DefaultBestEffortTrafficRate); - - - - // set transaction ID to gate set - trID.setGateCommandType(ITransactionID.GateSet); - _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID); - trID.setTransactionIdentifier(_transactionID); - - amid.setApplicationType((short) 1); - amid.setApplicationMgrTag((short) 1); - gateSpec.setDirection(Direction.UPSTREAM); - gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE); - gateSpec.setTimerT1(PCMMGlobalConfig.GateT1); - gateSpec.setTimerT2(PCMMGlobalConfig.GateT2); - gateSpec.setTimerT3(PCMMGlobalConfig.GateT3); - gateSpec.setTimerT4(PCMMGlobalConfig.GateT4); - - // 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); - try { - InetAddress subIP = InetAddress - .getByName(PCMMGlobalConfig.SubscriberID); - InetAddress srcIP = InetAddress - .getByName(PCMMGlobalConfig.srcIP); - InetAddress dstIP = InetAddress - .getByName(PCMMGlobalConfig.dstIP); - InetAddress mask = InetAddress.getByName("0.0.0.0"); - subscriberID.setSourceIPAddress(subIP); - eclassifier.setSourceIPAddress(srcIP); - eclassifier.setDestinationIPAddress(dstIP); - eclassifier.setIPDestinationMask(mask); - eclassifier.setIPSourceMask(mask); - } catch (UnknownHostException unae) { - logger.error("Error getByName", unae); - } - eclassifier.setSourcePortStart(PCMMGlobalConfig.srcPort); - eclassifier.setSourcePortEnd(PCMMGlobalConfig.srcPort); - eclassifier.setDestinationPortStart(PCMMGlobalConfig.dstPort); - eclassifier.setDestinationPortEnd(PCMMGlobalConfig.dstPort); - eclassifier.setActivationState((byte) 0x01); - // check if we have a stored value of classifierID else we just - // create - // one - // eclassifier.setClassifierID((short) 0x01); - eclassifier.setClassifierID((short) (_classifierID == 0 ? Math - .random() * hashCode() : _classifierID)); - // XXX - testie - // eclassifier.setClassifierID((short) 1); - - eclassifier.setAction((byte) 0x00); - // XXX - temp default until Gate Modify is hacked in - // eclassifier.setPriority(PCMMGlobalConfig.EClassifierPriority); - eclassifier.setPriority((byte) 65); - - } else { -// classifier.setProtocol(IClassifier.Protocol.TCP); - try { - InetAddress subIP = InetAddress - .getByName(PCMMGlobalConfig.SubscriberID); - InetAddress srcIP = InetAddress - .getByName(PCMMGlobalConfig.srcIP); - InetAddress dstIP = InetAddress - .getByName(PCMMGlobalConfig.dstIP); - subscriberID.setSourceIPAddress(subIP); - classifier.setSourceIPAddress(srcIP); - classifier.setDestinationIPAddress(dstIP); - } catch (UnknownHostException unae) { - logger.error("Error getByName", unae); - } - classifier.setSourcePort(PCMMGlobalConfig.srcPort); - classifier.setDestinationPort(PCMMGlobalConfig.dstPort); - } - - gate.setTransactionID(trID); - gate.setAMID(amid); - gate.setSubscriberID(subscriberID); - gate.setGateSpec(gateSpec); - gate.setTrafficProfile(trafficProfile); - gate.setClassifier(eclassifier); - - byte[] data = gate.getData(); - - final Set decisionSet = new HashSet<>(); - decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR)); - final Map> 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, _handle, decisionMap, null, clientSD); - - // ** Send the GateSet Decision - // ** - try { - decisionMsg.writeData(_sock); - } catch (IOException e) { - logger.error("Failed to send the decision", e); - } - - } - - public boolean handleGateReport(final Socket socket) throws COPSPdpException { try { // waits for the gate-set-ack or error @@ -475,9 +132,9 @@ public class PCMMPdpMsgSender extends COPSMsgSender { if (reportMsg.getClientSI() == null) { return false; } - final IPCMMGate responseGate = new PCMMGateReq(reportMsg.getClientSI().getData().getData()); + final IPCMMGate responseGate = PCMMGateReq.parse(reportMsg.getClientSI().getData().getData()); if (responseGate.getTransactionID() != null - && responseGate.getTransactionID().getGateCommandType() == ITransactionID.GateSetAck) { + && responseGate.getTransactionID().getGateCommandType().equals(GateCommandType.GATE_SET_ACK)) { 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... @@ -494,94 +151,6 @@ public class PCMMPdpMsgSender extends COPSMsgSender { } - /** - * Sends a PCMM GateSet COPS Decision message - * - * @throws COPSPdpException - */ - public void sendGateSet() throws COPSPdpException { - // 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 IClassifier classifier = new Classifier(); - // XXX check if other values should be provided - final ITrafficProfile trafficProfile = new BestEffortService( - BestEffortService.DEFAULT_ENVELOP); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setTrafficPriority(BestEffortService.DEFAULT_TRAFFIC_PRIORITY); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setMaximumTrafficBurst( - BestEffortService.DEFAULT_MAX_TRAFFIC_BURST); - ((BestEffortService) trafficProfile).getAuthorizedEnvelop() - .setRequestTransmissionPolicy( - PCMMGlobalConfig.BETransmissionPolicy); - - // set transaction ID to gate set - trID.setGateCommandType(ITransactionID.GateSet); - _transactionID = (_transactionID == 0 ? (short) (Math.random() * hashCode()) : _transactionID); - trID.setTransactionIdentifier(_transactionID); - - amid.setApplicationType((short) 1); - amid.setApplicationMgrTag((short) 1); - gateSpec.setDirection(Direction.UPSTREAM); - gateSpec.setDSCP_TOSOverwrite(DSCPTOS.OVERRIDE); - gateSpec.setTimerT1(PCMMGlobalConfig.GateT1); - gateSpec.setTimerT2(PCMMGlobalConfig.GateT2); - gateSpec.setTimerT3(PCMMGlobalConfig.GateT3); - gateSpec.setTimerT4(PCMMGlobalConfig.GateT4); - - /* - * ((DOCSISServiceClassNameTrafficProfile) trafficProfile) - * .setServiceClassName("S_up"); - */ - -// classifier.setProtocol(IClassifier.Protocol.TCP); - try { - InetAddress subIP = InetAddress.getByName(PCMMGlobalConfig.SubscriberID); - InetAddress srcIP = InetAddress.getByName(PCMMGlobalConfig.srcIP); - InetAddress dstIP = InetAddress.getByName(PCMMGlobalConfig.dstIP); - subscriberID.setSourceIPAddress(subIP); - classifier.setSourceIPAddress(srcIP); - classifier.setDestinationIPAddress(dstIP); - } catch (UnknownHostException unae) { - logger.error("Error getByName", unae); - } - classifier.setSourcePort(PCMMGlobalConfig.srcPort); - classifier.setDestinationPort(PCMMGlobalConfig.dstPort); - - gate.setTransactionID(trID); - gate.setAMID(amid); - gate.setSubscriberID(subscriberID); - gate.setGateSpec(gateSpec); - gate.setTrafficProfile(trafficProfile); - gate.setClassifier(classifier); - - final byte[] data = gate.getData(); - - final Set decisionSet = new HashSet<>(); - decisionSet.add(new COPSDecision(CType.CSI, Command.INSTALL, DecisionFlag.REQERROR)); - final Map> 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(), _handle, decisionMap, null, clientSD); - - // ** Send the GateSet Decision - // ** - try { - decisionMsg.writeData(_sock); - } catch (IOException e) { - logger.error("Failed to send the decision", e); - } - } - /** * Sends a message asking that the request state be deleted * @@ -589,10 +158,7 @@ public class PCMMPdpMsgSender extends COPSMsgSender { */ 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); + final ITransactionID trID = new TransactionID(_transactionID, GateCommandType.GATE_DELETE); gate.setTransactionID(trID); Short trIDnum = trID.getTransactionIdentifier(); diff --git a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java index 79470ff..9aed78c 100644 --- a/packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java +++ b/packetcable-driver/src/main/java/org/pcmm/PCMMPdpReqStateMan.java @@ -1,12 +1,14 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ package org.pcmm; import org.pcmm.gates.IGateID; +import org.pcmm.gates.IPCMMError.ErrorCode; import org.pcmm.gates.IPCMMGate; import org.pcmm.gates.ITransactionID; +import org.pcmm.gates.ITransactionID.GateCommandType; import org.pcmm.gates.impl.PCMMError; import org.pcmm.gates.impl.PCMMGateReq; import org.slf4j.Logger; @@ -69,7 +71,7 @@ public class PCMMPdpReqStateMan extends COPSPdpReqStateMan { // PCMMUtils.WriteBinaryDump("COPSReportClientSI", data); logger.info("PCMMGateReq Parse Gate Message"); - final PCMMGateReq gateMsg = new PCMMGateReq(data); + final PCMMGateReq gateMsg = PCMMGateReq.parse(data); // TODO FIXME - Why is this Map being filled but never used??? final Map repSIs = new HashMap<>(); @@ -125,9 +127,9 @@ public class PCMMPdpReqStateMan extends COPSPdpReqStateMan { _thisProcess.successReport(this, gateMsg); } else { final String cmdType; - if ( trID.getGateCommandType() == ITransactionID.GateDeleteAck ) { + if (trID.getGateCommandType().equals(GateCommandType.GATE_DELETE_ACK)) { cmdType = "GateDeleteAck"; - } else if ( trID.getGateCommandType() == ITransactionID.GateSetAck ) { + } else if (trID.getGateCommandType().equals(GateCommandType.GATE_SET_ACK)) { cmdType = "GateSetAck"; } else cmdType = null; // capture the gateId from the response message @@ -152,9 +154,8 @@ public class PCMMPdpReqStateMan extends COPSPdpReqStateMan { if (gateMsg.getError() != null) logger.info("Gate message error - " + gateMsg.getError().toString()); else { - final PCMMError error = new PCMMError(); - // TODO - figure out correct error code - error.setErrorCode((short)19); + // TODO - Determine if this is the correct error code + final PCMMError error = new PCMMError(ErrorCode.UNK_GATE_CMD); gate.setError(error); logger.warn("Gate request failed without an error, setting one - " + error); } diff --git a/packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java b/packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java index 2114004..8c65867 100644 --- a/packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java +++ b/packetcable-driver/src/main/java/org/pcmm/base/IPCMMBaseObject.java @@ -1,5 +1,5 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ package org.pcmm.base; @@ -7,8 +7,6 @@ package org.pcmm.base; import java.io.IOException; import java.net.Socket; -import org.umu.cops.stack.COPSData; - /** * Base interface for all PCMM objects, it define the {@code S-Type}, * {@code S-Num} and the data length @@ -16,65 +14,10 @@ import org.umu.cops.stack.COPSData; */ public interface IPCMMBaseObject { - /** - * sets the S-Type - * - * @param stype - */ - void setSType(byte stype); - - /** - * - * @return S-Type - */ - byte getSType(); - - /** - * sets the S-Num - * - * @param snum - * S-Num - */ - void setSNum(byte snum); - - /** - * gets the S-Num - * - * @return S-Num - */ - byte getSNum(); - - /** - * sets the length; - * - * @param len - */ - void setLength(short len); - - /** - * gets the length; - * - * @return length - */ - short getLength(); - - /** - * sets the COPS data - * - * @param data - * COPS data - */ - void setData(COPSData data); - - /** - * gets the COPS data - * - * @return COPS data - */ - COPSData getData(); - void writeData(Socket id) throws IOException; +// short getDataLen(); + byte[] getAsBinaryArray(); } diff --git a/packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java b/packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java index 79e26de..586f2b9 100644 --- a/packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java +++ b/packetcable-driver/src/main/java/org/pcmm/base/impl/PCMMBaseObject.java @@ -1,244 +1,185 @@ -/** - * +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ -package org.pcmm.base.impl; -import java.io.IOException; -import java.net.Socket; -import java.util.Arrays; +package org.pcmm.base.impl; +import com.google.common.primitives.Bytes; import org.pcmm.base.IPCMMBaseObject; import org.umu.cops.stack.COPSData; +import org.umu.cops.stack.COPSMsgParser; +import org.umu.cops.stack.COPSObjectParser; + +import java.io.IOException; +import java.net.Socket; +import java.util.ArrayList; +import java.util.List; /** * - * Implementation of the base class {@link IPCMMBaseObject} - * + * Abstract implementation of the base class {@link IPCMMBaseObject} + * Implementations of this class are used for sending/receiving PCMM data to/from a COPS client */ -public class PCMMBaseObject /* extends COPSPrObjBase */implements - IPCMMBaseObject { - - private byte sType; - private byte sNum; - private short len; - private COPSData copsData; - private COPSData pad; - protected final short offset = (short) 4; - - public PCMMBaseObject(byte[] data) { - parse(data); - } +public abstract class PCMMBaseObject implements IPCMMBaseObject { - public PCMMBaseObject(short len, byte sType, byte sNum) { - this.len = (len); - this.sType = (sType); - this.sNum = (sNum); - byte[] array = new byte[len - offset]; - Arrays.fill(array, (byte) 0); - setData(new COPSData(array, 0, array.length)); - } + protected static final short HEADER_OFFSET = (short) 4; + protected static final short PADDING_OFFSET = (short) 4; - protected COPSData getPadding(int len) { - byte[] padBuf = new byte[len]; - Arrays.fill(padBuf, (byte) 0); - COPSData d = new COPSData(padBuf, 0, len); - return d; - } + // The following two attributes denote the type of PCMMBaseObject + private final SNum sNum; + private final byte sType; /** - * Add head padding to the specified byte array filled with zeros - * - * @param off - * offset - * @param array - * input array - * @return byte array + * Constructor + * @param sNum - the S-Num + * @param sType - the S-Type */ - protected byte[] headPadding(int off, byte[] array) { - byte[] returnArray = new byte[array.length + off]; - Arrays.fill(returnArray, (byte) 0); - System.arraycopy(array, 0, returnArray, off, array.length); - return returnArray; - } - - protected void parse(byte[] data) { - if (data == null || data.length == 0) - throw new IllegalArgumentException("data could not be null"); - len = 0; - len |= ((short) data[0]) << 8; - len |= ((short) data[1]) & 0xFF; - sNum = data[2]; - sType = data[3]; - copsData = new COPSData(data, offset, data.length - offset); + protected PCMMBaseObject(final SNum sNum, final byte sType) { + if (sNum == null) throw new IllegalArgumentException("Invalid or null SNum"); + this.sNum = sNum; + this.sType = sType; } - protected void setShort(short value, short startPos) { - byte[] data = getData().getData(); - data[startPos] = (byte) (value >> 8); - data[startPos + 1] = (byte) value; - setData(new COPSData(data, 0, data.length)); - } - - protected short getShort(short startPos) { - byte[] data = getData().getData(); - short retVal = 0; - retVal |= ((short) data[startPos]) << 8; - retVal |= ((short) data[startPos + 1]) & 0xFF; - return retVal; - } - - protected void setInt(int value, short startPos) { - byte[] data = getData().getData(); - data[startPos] = (byte) (value >> 24); - data[startPos + 1] = (byte) (value >> 16); - data[startPos + 2] = (byte) (value >> 8); - data[startPos + 3] = (byte) value; - setData(new COPSData(data, 0, data.length)); - } - - protected int getInt(short startPos) { - byte[] data = getData().getData(); - int retVal = 0; - retVal |= ((short) data[startPos]) << 24; - retVal |= ((short) data[startPos + 1]) << 16; - retVal |= ((short) data[startPos + 2]) << 8; - retVal |= ((short) data[startPos + 3]) & 0xFF; - return retVal; - } - - protected void setBytes(byte[] value, short startPos) { - byte[] data = getData().getData(); - for (byte b : value) - data[startPos++] = b; - setData(new COPSData(data, 0, data.length)); - } - - protected byte[] getBytes(short startPos, short size) { - return Arrays.copyOfRange(getData().getData(), startPos, startPos - + size); - } - - protected void setByte(byte value, short startPos) { - setBytes(new byte[] { value }, startPos); - } - - protected byte getByte(short startPos) { - return getBytes(startPos, (short) 1)[0]; + @Override + public final void writeData(final Socket socket) throws IOException { + final byte[] data = getAsBinaryArray(); + socket.getOutputStream().write(data, 0, data.length); } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#setSType(byte) - */ @Override - public void setSType(byte stype) { - this.sType = stype; + public final byte[] getAsBinaryArray() { + final byte[] data = getBytes(); + final COPSData padding; + if ((data.length % PADDING_OFFSET) != 0) { + final int padLen = PADDING_OFFSET - (data.length % PADDING_OFFSET); + padding = COPSObjectParser.getPadding(padLen); + } else { + padding = new COPSData(); + } + final int payloadSize = data.length + padding.length() + HEADER_OFFSET; + final List outBytes = new ArrayList<>(); + outBytes.addAll(Bytes.asList(COPSMsgParser.shortToBytes((short) payloadSize))); + outBytes.add(sNum.getValue()); + outBytes.add(sType); + outBytes.addAll(Bytes.asList(data)); + outBytes.addAll(Bytes.asList(padding.getData())); + return Bytes.toArray(outBytes); } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#getSType() - */ @Override - public byte getSType() { - return sType; - } + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PCMMBaseObject)) { + return false; + } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#setSNum(byte) - */ - @Override - public void setSNum(byte snum) { - this.sNum = snum; + final PCMMBaseObject that = (PCMMBaseObject) o; + return sType == that.sType && sNum == that.sNum; } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#getSNum() - */ @Override - public byte getSNum() { - return sNum; + public int hashCode() { + int result = sNum.hashCode(); + result = 31 * result + (int) sType; + return result; } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#setLength(short) + /** + * Returns the byte array consisting of the data contained within the implementation class + * @return - the byte array */ - @Override - public void setLength(short len) { - this.len = len; - } + protected abstract byte[] getBytes(); - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#getLength() + /** + * Enumeration of SNum values that is used by the client to determine which Object type is being sent */ - @Override - public short getLength() { - return (short) (len + (pad != null ? pad.length() : 0)); - } + public enum SNum { + TRANSACTION_ID((byte) 1), + AMID((byte) 2), + SUBSCRIBER_ID((byte) 3), + GATE_ID((byte) 4), + GATE_SPEC((byte) 5), + CLASSIFIERS((byte) 6), + TRAFFIC_PROFILE((byte) 7), + EVENT_GEN_INFO((byte) 8), + VOL_BASED_USAGE_LIMIT((byte) 9), + TIME_BASED_USAGE_LIMIT((byte) 10), + OPAQUE_DATA((byte) 11), + GATE_TIME_INFO((byte) 12), + GATE_USAGE_INFO((byte) 13), + PCMM_ERROR((byte) 14), + GATE_STATE((byte) 15), + VERSION_INFO((byte) 16), + PSID((byte) 17), + SYNC_OPTS((byte) 18), + MSG_RECEIPT_KEY((byte) 19), + USER_ID((byte) 20), + SHARED_RES_ID((byte) 21); + + private byte value; + + SNum(byte value) { + this.value = value; + } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#setData(org.umu.cops.stack.COPSData) - */ - @Override - public void setData(COPSData data) { - this.copsData = data; - if (data.length() % offset != 0) { - int padLen = offset - (data.length() % offset); - pad = getPadding(padLen); + public byte getValue() { + return value; } - len = (short) (data.length() + offset); - } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#getData() - */ - @Override - public COPSData getData() { - return copsData; - } + public static SNum valueOf(byte v) { + switch (v) { + case 1: + return SNum.TRANSACTION_ID; + case 2: + return SNum.AMID; + case 3: + return SNum.SUBSCRIBER_ID; + case 4: + return SNum.GATE_ID; + case 5: + return SNum.GATE_SPEC; + case 6: + return SNum.CLASSIFIERS; + case 7: + return SNum.TRAFFIC_PROFILE; + case 8: + return SNum.EVENT_GEN_INFO; + case 9: + return SNum.VOL_BASED_USAGE_LIMIT; + case 10: + return SNum.TIME_BASED_USAGE_LIMIT; + case 11: + return SNum.OPAQUE_DATA; + case 12: + return SNum.GATE_TIME_INFO; + case 13: + return SNum.GATE_USAGE_INFO; + case 14: + return SNum.PCMM_ERROR; + case 15: + return SNum.GATE_STATE; + case 16: + return SNum.VERSION_INFO; + case 17: + return SNum.PSID; + case 18: + return SNum.SYNC_OPTS; + case 19: + return SNum.MSG_RECEIPT_KEY; + case 20: + return SNum.USER_ID; + case 21: + return SNum.SHARED_RES_ID; + default: + throw new IllegalArgumentException("not supported value"); + } + } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#writeData(java.net.Socket) - */ - public void writeData(Socket id) throws IOException { - byte[] data = getAsBinaryArray(); - id.getOutputStream().write(data, 0, data.length); } - /* - * (non-Javadoc) - * - * @see org.pcmm.base.IPCMMBaseObject#getAsBinaryArray() - */ - @Override - public byte[] getAsBinaryArray() { - byte[] array = new byte[getLength()]; - array[0] = (byte) (len >> 8); - array[1] = (byte) len; - array[2] = sNum; - array[3] = sType; - System.arraycopy(getData().getData(), 0, array, offset, getData() - .length()); - if (pad != null) - System.arraycopy(pad.getData(), 0, array, offset - + getData().length(), pad.length()); - return array; - } + + } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java b/packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java index 71e8116..6cfb72a 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IAMID.java @@ -1,13 +1,17 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; /** + * Class to hold the Application Manager Identification which is the handle that identifies the Application Manager + * and Application Type. + * + * From the Packetcable Multimedia specification section 6.1.2 + * *

* The AMID consists of two fields: the Application Manager Tag and Application * Type. Each Application Manager is pre-provisioned with an Application Manager @@ -36,16 +40,18 @@ import org.pcmm.base.IPCMMBaseObject; */ public interface IAMID extends IPCMMBaseObject { - static final short LENGTH = 8; - static final byte SNUM = 2; - static final byte STYPE = 1; - - void setApplicationType(short type); + byte STYPE = 1; + /** + * Returns the application type value + * @return - a short + */ short getApplicationType(); - void setApplicationMgrTag(short type); - + /** + * Returns the application manager tag value + * @return - a short + */ short getApplicationMgrTag(); } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java index 3226f50..dcac12e 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IClassifier.java @@ -1,8 +1,7 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; @@ -10,47 +9,19 @@ import org.pcmm.base.IPCMMBaseObject; import java.net.InetAddress; /** - * - * - * + * The Classifier object specifies the packet matching rules associated with a Gate. As defined in Sections 6.4.3.1 and + * 6.4.3.2, for Unicast Gates multiple Classifier objects may be included in the Gate-Set to allow for complex + * classifier rules. When an AM is using Classifier objects, at least one Classifier MUST be provided by the PDP in all + * Gate-Set messages. More than one Classifier is allowed for Unicast Gates. Only one classifier is required to be + * supported for Multicast Gates. Unlike DOCSIS DSx signaling, Classifiers have no identifier and have no explicit add, + * change, or remove operations. The entire set of Classifiers present in a Gate-Set message replaces the entire set of + * classifiers for the existing Gate. Equivalence of Classifiers is determined by comparing all fields within the + * Classifier. Classifiers may be provided in any order. */ public interface IClassifier extends IPCMMBaseObject { - short LENGTH = 24; - byte SNUM = 6; byte STYPE = 1; - enum Protocol { - /*ICMP((short) 1), IGMP((short) 2), */ - NONE((short)0), TCP((short) 6), UDP((short) 17); - - Protocol(short v) { - this.value = v; - } - - public static Protocol valueOf(short v) { - switch (v) { - case 0: - return NONE; - /* - case 1: - return ICMP; - case 2: - return IGMP; - */ - case 6: - return TCP; - default: - return UDP; - } - } - private short value; - - public short getValue() { - return value; - } - } - /** * IP Destination Address or IPv6 Destination Address is the termination * point for the IP flow @@ -59,12 +30,12 @@ public interface IClassifier extends IPCMMBaseObject { */ InetAddress getDestinationIPAddress(); - void setDestinationIPAddress(InetAddress address); - + /** + * Returns the destination port value + * @return - the port number + */ short getDestinationPort(); - void setDestinationPort(short p); - /** * Source IP, IP Source Address, or IPv6 Source Address (in the case of * Extended Classifier or IPv6 Classifier) is the IP address (as seen at the @@ -74,12 +45,12 @@ public interface IClassifier extends IPCMMBaseObject { */ InetAddress getSourceIPAddress(); - void setSourceIPAddress(InetAddress a); - + /** + * Returns the source port value + * @return - the port number + */ short getSourcePort(); - void setSourcePort(short p); - /** * Protocol field, in a legacy Classifier or Extended Classifier, identifies * the type of protocol (e.g., IP, ICMP, etc.). The Next Header Type field @@ -87,14 +58,7 @@ public interface IClassifier extends IPCMMBaseObject { * * @return the protocol. */ - short getProtocol(); - - /** - * @see protocols - * @param p - the protocol value - */ - void setProtocol(short p); + Protocol getProtocol(); /** * Priority may be used to distinguish between multiple classifiers that @@ -106,23 +70,49 @@ public interface IClassifier extends IPCMMBaseObject { byte getPriority(); /** - * sets the priority; - * - * @param p - * priority + * Returns the DSCPTOS enumeration value (ENABLE|DISABLE) + * @return the enumeration */ - void setPriority(byte p); - byte getDSCPTOS(); - void setDSCPTOS(byte v); - + /** + * Returns the DSCPTOS mask value + * @return the mask + */ byte getDSCPTOSMask(); - void setDSCPTOSMask(byte v); + /** + * Enumeration of supported protocols + */ + enum Protocol { + /*ICMP((short) 1), IGMP((short) 2), */ + NONE((short)0), TCP((short) 6), UDP((short) 17); - // DSCP/TOS Field - //  - // DSCP/TOS Mask + Protocol(short v) { + this.value = v; + } + + public static Protocol valueOf(short v) { + switch (v) { + case 0: + return NONE; + /* TODO - Determine why these two values are not being supported??? + case 1: + return ICMP; + case 2: + return IGMP; + */ + case 6: + return TCP; + default: + return UDP; + } + } + private short value; + + public short getValue() { + return value; + } + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java index 635bf25..e8ddd31 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IExtendedClassifier.java @@ -1,69 +1,106 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; import java.net.InetAddress; +/** + * The Extended Classifier object specifies the packet matching rules associated with a Gate, but includes more + * detailed information for matching traffic, as well adding, modifying, deleting, activating and inactivating Classifiers. + * As defined in sections 6.4.3.1 and 6.4.3.2, for Unicast Gates multiple Extended Classifier objects may be included + * in the Gate-Set to allow for complex classifier rules. However, since the ordering of objects in a message and the + * order of processing those objects is not mandated, and AM SHOULD NOT send a GateSet with multiple Extended + * Classifiers with the same ClassifierID, yet different Actions. When an AM is using Extended Classifier objects, at + * least one Extended Classifier is allowed. For Multicast Gates, only one Extended Classifier is required to be supported. + * Since the Extended Classifier is based on the DOCSIS IP Classifier, all DOCSIS classifier semantics apply, with the + * exception that at least one Extended Classifier be present in a Gate-Set message. + * + * Message length including header == 40 + */ public interface IExtendedClassifier extends IClassifier { - static final short LENGTH = 40; - static final byte SNUM = 6; - static final byte STYPE = 2; - - void setIPSourceMask(InetAddress a); + byte STYPE = 2; - void setIPDestinationMask(InetAddress m); + /** + * Returns the IP Source Mask value + * @return - the InetAddress object + */ + InetAddress getIPSourceMask(); - void setSourcePortStart(short p); + /** + * Returns the IP Destination Mask value + * @return - the InetAddress object + */ + InetAddress getIPDestinationMask(); - void setSourcePortEnd(short p); + /** + * Returns the Start Source Port value + * @return - the port number + */ + short getSourcePortStart(); - void setDestinationPortStart(short p); + /** + * Returns the End Source Port value + * @return - the port number + */ + short getSourcePortEnd(); - void setDestinationPortEnd(short p); + /** + * Returns the Start Destination Port value + * @return - the port number + */ + short getDestinationPortStart(); - void setClassifierID(short p); + /** + * Returns the End Destination Port value + * @return - the port number + */ + short getDestinationPortEnd(); /** - *

-     * 0x00 Inactive
-     * 0x01 Active
-     * 
- * - * @param s + * The ID value of this classifier + * @return - the ID */ - void setActivationState(byte s); + short getClassifierID(); /** - *
-     * 0x00 Add classifier
-     * 0x01 Replace classifier
-     * 0x02 Delete classifier
-     * 0x03 No change
-     * 
- * - * @param a + * The activation state + * @return */ - void setAction(byte a); + ActivationState getActivationState(); - InetAddress getIPSourceMask(); + byte getAction(); - InetAddress getIPDestinationMask(); + /** + * The valid activation state values + */ + enum ActivationState { - short getSourcePortStart(); + INACTIVE((byte) 0), ACTIVE((byte) 1); - short getSourcePortEnd(); + ActivationState(byte value) { + this.value = value; + } - short getDestinationPortStart(); + public byte getValue() { + return value; + } - short getDestinationPortEnd(); + public static ActivationState valueOf(byte v) { + switch (v) { + case 0: + return ActivationState.INACTIVE; + case 1: + return ActivationState.ACTIVE; + default: + throw new IllegalArgumentException("not supported value"); + } + } - short getClassifierID(); + private byte value; - byte getActivationState(); + } - byte getAction(); } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java b/packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java index d6d9582..0a5da3b 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IGateID.java @@ -1,19 +1,49 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; /** + * GateID is the handle for the Gate. The GateID is assigned by the CMTS and is used by the Application Manager, + * Policy Server, and client to reference the Gate. + * + * From the Packetcable Multimedia specification section 6.1.1 * + * A GateID is an identifier that is locally allocated by the CMTS where the Gate resides. A GateID MUST be + * associated with only one Gate. Whereas the PacketCable 1.x DQoS Gate Control model generally assumed a pair of + * unidirectional Gates (one upstream and one downstream) per GateID in support of a typical two-way voice session, + * here the Gate/GateID relationship is explicitly one-to-one, so that it is easier to support a wide range of Multimedia + * services. + * + * When the Application Manager issues a Gate-Set request, this triggers the Policy Server to issue a Gate-Set message + * to the CMTS. When the CMTS responds with an acknowledgment containing the GateID, the Policy Server + * forwards this response including the GateID back to the Application Manager. Note that since there can be a manyto- + * many relationship between a PS and CMTS, the GateID assigned by one CMTS cannot be guaranteed to be + * unique across the network, so the PSs may use the AMID of the AM along with the SubscriberID and GateID in + * order to uniquely identify the Gate. + * + * An algorithm that may be used to assign values of GateIDs is as follows. Partition the 32-bit word into two parts, an + * index part, and a random part. The index part identifies the Gate by indexing into a small table, while the random + * part provides some level of obscurity to the value. Regardless of the algorithm chosen, the CMTS SHOULD attempt + * to minimize the possibility of GateID ambiguities by ensuring that no GateID gets reused within three minutes of its + * prior closure or deletion. For the algorithm suggested this could be accomplished by simply incrementing the index + * part for each consecutively assigned GateID, wrapping around to zero when the maximum integer value of the index + * part is reached. */ public interface IGateID extends IPCMMBaseObject { - static final short LENGTH = 8; - static final byte SNUM = 4; - static final byte STYPE = 1; - void setGateID(int gateID); + /** + * The S-Type for Gate IDs + */ + byte STYPE = 1; + /** + * Returns the gate ID value + * @return - the ID + */ int getGateID(); + } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java b/packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java index e81d1dc..b31c98e 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IGateSpec.java @@ -1,24 +1,61 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; /** - *

- * The GateSpec describes some high-level attributes of the Gate, and contains - * information regarding the treatment of other objects specified in the Gate - * message. - *

+ * GateSpec describes specific authorization parameters defining a Gate (i.e., QoS limits, timers, etc.). + * + * From the Packetcable Multimedia specification section 6.1.4 + * + * The GateSpec describes some high-level attributes of the Gate, and contains information regarding the treatment of + * other objects specified in the Gate message. Information contained in a GateSpec is outlined below. + * + * * SessionClassID + * * Direction + * * Authorized Timer + * * Reserved Timer + * * Committed Timer + * * Committed Recovery Timer + * * DSCP/TOS Overwrite + * * DSCP/TOS Mask + * + * SessionClassID provides a way for the Application Manager and the Policy Server to group Gates into different + * classes with different authorization characteristics. For example, one could use the SessionClassID to represent + * some prioritization or preemption scheme that would allow either the Policy Server or the CMTS to preempt a preauthorized + * Gate in favor of allowing a new Gate with a higher priority to be authorized. + * + * Direction indicates whether the Gate is for an upstream or downstream flow. Depending on this direction, the CMTS + * MUST reserve and activate the DOCSIS flows accordingly. For Multicast Gates the CMTS needs to only support + * flows or gates in the downstream direction. + * + * Authorized Timer limits the amount of time the authorization must remain valid before it is reserved (see + * Section 6.2). + * + * Reserved Timer limits the amount of time the reservation must remain valid before the resources are committed (see + * Section 6.2). + * + * Committed Timer limits the amount of time a committed service flow may remain idle. + * + * Committed Recovery Timer limits the amount of time that a committed service flow can remain without a + * subsequent refresh message from the PS/AM once the PS/AM has been notified of inactivity (see Section 6.2). + * DSCP/TOS Overwrite field can be used to overwrite the DSCP/TOS field of packets associated with the DOCSIS + * Service Flow that corresponds to the Gate. This field may be unspecified in which case the DSCP/TOS field in the + * packet is not over-written by the CMTS. This field may be used in both the upstream and downstream directions. + * The CMTS MUST support DSCP/TOS overwrite for upstream gates. The CMTS MAY support DSCP/TOS + * overwrite for downstream gates. If DSCP/TOS is enabled in a downstream gate and the CMTS does not support that + * function, then the field is ignored. The manner in which the CMTS interprets the DSCP/TOS Overwrite & Mask + * fields and transforms it into the corresponding DOCSIS Service Flow Parameters is defined in Section 6.4.2.5. */ public interface IGateSpec extends IPCMMBaseObject { - byte SNUM = 5; + /** + * The S-Type for Gate Specifications + */ byte STYPE = 1; - short LENGTH = 16; /** *

@@ -67,46 +104,6 @@ public interface IGateSpec extends IPCMMBaseObject { } - /** - * - */ - enum DSCPTOS { - - ENABLE((byte) 2), OVERRIDE((byte) 0); - - DSCPTOS(byte value) { - this.value = value; - } - - public byte getValue() { - return value; - } - - @Override - public String toString() { - switch (value) { - case 1: - return "Enable"; - default: - return "Override"; - } - } - - public static DSCPTOS valueOf(byte v) { - switch (v) { - case 0: - return DSCPTOS.OVERRIDE; - case 1: - return DSCPTOS.ENABLE; - default: - throw new IllegalArgumentException("not supported value"); - } - } - - private byte value; - - } - /** *

* provides a way for the Application Manager and the Policy Server to group @@ -121,36 +118,12 @@ public interface IGateSpec extends IPCMMBaseObject { */ ISessionClassID getSessionClassID(); - /** - *

- * sets the session class ID; - *

- *

- * SessionClassID is a 1-byte unsigned integer value which identifies the - * proper admission control policy or parameters to be applied for this - * Gate. The SessionClassID is a bit field, defined as follows: Bit 0-2: - * Priority, a number from 0 to 7, where 0 is low priority and 7 is high. - * Bit 3: Preemption, set to enable preemption of bandwidth allocated to - * lower priority sessions if necessary (if supported). Bit 4-7: - * Configurable, default to 0 - *

- */ - void setSessionClassID(ISessionClassID id); - /** * * @return direction. */ Direction getDirection(); - /** - * sets the direction - * - * @param direction - * Direction - */ - void setDirection(Direction direction); - /** * Authorized Timer limits the amount of time the authorization must remain * valid before it is reserved @@ -159,14 +132,6 @@ public interface IGateSpec extends IPCMMBaseObject { */ short getTimerT1(); - /** - * sets the authorized timer - * - * @param authTimer - * : authorized timer - */ - void setTimerT1(short authTimer); - /** * Reserved Timer limits the amount of time the reservation must remain * valid before the resources are committed @@ -175,13 +140,6 @@ public interface IGateSpec extends IPCMMBaseObject { */ short getTimerT2(); - /** - * sets the reserved timer. - * - * @param timer - */ - void setTimerT2(short timer); - /** * Committed Timer limits the amount of time a committed service flow may * remain idle. @@ -190,14 +148,6 @@ public interface IGateSpec extends IPCMMBaseObject { */ short getTimerT3(); - /** - * sets the committed timer. - * - * @param t - * timer - */ - void setTimerT3(short t); - /** * Committed Recovery Timer limits the amount of time that a committed * service flow can remain without a subsequent refresh message from the @@ -207,28 +157,11 @@ public interface IGateSpec extends IPCMMBaseObject { */ short getTimerT4(); - /** - * sets the Committed Recovery Timer. - * - * @param t - * timer - */ - void setTimerT4(short t); - - /** - * - * @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 */ - DSCPTOS getDSCP_TOSOverwrite(); + byte getDSCP_TOSOverwrite(); /** * @@ -236,10 +169,4 @@ public interface IGateSpec extends IPCMMBaseObject { */ byte getDSCP_TOSMask(); - /** - * - * @param dscp_tos_mask - */ - void setDSCP_TOSMask(byte dscp_tos_mask); - } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java index 1a026da..bc6870d 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IIPv6Classifier.java @@ -1,86 +1,77 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; -import java.net.InetAddress; - +/** + * The IPv6 Classifier object also specifies the packet matching rules associated with a Gate, when IPv6 Addresses are + * used. As defined in Sections 6.4.3.1 and 6.4.3.2, for Unicast Gates multiple IPv6 Classifier objects may be included + * in the Gate-Set to allow for complex classifier rules. However, since the ordering of objects in a message and the + * order of processing those objects is not mandated, an AM SHOULD NOT send a GateSet with multiple IPv6 + * Classifiers with the same ClassificationID, yet different Actions. When an AM is using IPv6 Classifier objects, at + * least one IPv6 Classifier MUST be provided by the PDP in all Gate-Set messages. For Unicast Gates more than one + * IPv6 Classifier is allowed. For Multicast Gates only one IPv6 Classifier is required to be supported. Since the IPv6 + * Classifier is based on the DOCSIS IPv6 Classifier, all DOCSIS classifier semantics apply, with the exeption that at + * least one IPv6 Classifier be present in a Gate-Set message. + */ public interface IIPv6Classifier extends IExtendedClassifier { - short LENGTH = 64; - byte SNUM = 6; +// short LENGTH = 64; +// byte SNUM = 6; byte STYPE = 3; // flags: Flow Label match enable flag - void setFlowLabelEnableFlag(byte flag); - byte getFlowLabelEnableFlag(); + FlowLabel 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); + /** + * The valid activation state values + */ + enum FlowLabel { - // Source Port End - short getSourcePortEnd(); - void setSourcePortEnd(short p); + IRRELEVANT((byte) 0), VALID((byte) 1); - // Destination Port Start - short getDestinationPortStart(); - void setDestinationPortStart(short p); + FlowLabel(byte value) { + this.value = value; + } - // Destination Port End - short getDestinationPortEnd(); - void setDestinationPortEnd(short p); + public byte getValue() { + return value; + } - // ClassifierID - short getClassifierID(); - void setClassifierID(short p); + public static FlowLabel valueOf(byte v) { + switch (v) { + case 0: + return FlowLabel.IRRELEVANT; + case 1: + return FlowLabel.VALID; + default: + throw new IllegalArgumentException("not supported value"); + } + } - // Priority - void setPriority(byte p); - byte getPriority(); + private byte value; - // Activation State - void setActivationState(byte s); - byte getActivationState(); + } - // Action - void setAction(byte a); - byte getAction(); } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java b/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java index 394f0bf..47dd0d6 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMError.java @@ -7,55 +7,74 @@ package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; /** - * + * The aPacketCable Error object contains information on the type of error that has occurred. The error is generated in + * response to a Gate Control command and is contained in Gate-Set-Err, Gate-Info-Err and Gate-Delete-Err messages. */ public interface IPCMMError extends IPCMMBaseObject { - short LENGTH = 8; - byte SNUM = 14; + byte STYPE = 1; - String[] errors = { "Insufficient Resources", "Unknown GateID", - "Missing Required Object", "Invalid Object", - "Volume Based Usage Limit Exceeded", - "Time Based Usage Limit Exceeded", "Session Class Limit Exceeded", - "Undefined Service Class Name", "Incompatible Envelope", - "Invalid SubscriberID", "Unauthorized AMID", - "Number of Classifiers Not Supported", "Policy Exception", - "Invalid Field Value in Object", "Transport Error", - "Unknown Gate Command", "DOCSIS 1.0 CM", - "Number of SIDs exceeded in CM", "Number of SIDs exceeded in CMTS", - "Unauthorized PSID", "No State for PDP", "Unsupported Synch Type", - "State Data Incomplete", "Upstream Drop Unsupported", - "Multicast Gate Error", "Multicast Volume Limit Unsupported", - "Uncommitted Multicast Not Supported", - "Multicast Gate Modification Not Supported", - "Upstream Multicast Not Supported", - "Multicast GateSpec incompatibility", "Multicast QoS Error", - "Multicast Downstream Resequencing mismatch", - "Other, Unspecified Error" }; - enum Description { - ERROR_01((short) 1, errors[0]), ERROR_02((short) 2, errors[1]), ERROR_06( - (short) 6, errors[2]), ERROR_07((short) 7, errors[3]), ERROR_08( - (short) 8, errors[4]), ERROR_09((short) 9, errors[5]), ERROR_10( - (short) 10, errors[6]), ERROR_11((short) 11, errors[7]), ERROR_12( - (short) 12, errors[8]), ERROR_13((short) 13, errors[9]), ERROR_14( - (short) 14, errors[10]), ERROR_15((short) 15, errors[11]), ERROR_16( - (short) 16, errors[12]), ERROR_17((short) 17, errors[13]), ERROR_18( - (short) 18, errors[14]), ERROR_19((short) 19, errors[15]), ERROR_20( - (short) 20, errors[16]), ERROR_21((short) 21, errors[17]), ERROR_22( - (short) 22, errors[18]), ERROR_23((short) 23, errors[19]), ERROR_24( - (short) 24, errors[20]), ERROR_25((short) 25, errors[21]), ERROR_26( - (short) 26, errors[22]), ERROR_27((short) 27, errors[23]), ERROR_28( - (short) 28, errors[24]), ERROR_29((short) 29, errors[25]), ERROR_30( - (short) 30, errors[26]), ERROR_31((short) 31, errors[27]), ERROR_32( - (short) 32, errors[28]), ERROR_33((short) 33, errors[29]), ERROR_34( - (short) 34, errors[30]), ERROR_35((short) 35, errors[31]), ERROR_127( - (short) 127, errors[28]); + /** + * Returns the error code + * @return - not null or NA + */ + ErrorCode getErrorCode(); + + /** + * Returns the error sub-code + * @return - not null (mostly will be NA) + */ + ErrorCode getErrorSubcode(); + + /** + * Returns the error's description + * @return - not null + */ + String getDescription(); + + /** + * The supported PCMM error codes with description. + */ + enum ErrorCode { + NA((short) 0, "NA"), + INSUFF_RES((short) 1, "Insufficient Resources"), + UNK_GATE_ID((short) 2, "Unknown GateID"), + MISSING_REQ_OBJ((short) 6, "Missing Required Object"), + INVALID_OBJ((short) 7, "Invalid Object"), + VOL_USG_LMT((short) 8, "Volume Based Usage Limit Exceeded"), + TIME_USG_LMT((short) 9, "Time Based Usage Limit Exceeded"), + SESSN_CLASS_LMT((short) 10, "Session Class Limit Exceeded"), + UNDEF_SCN_NAME((short) 11, "Undefined Service Class Name"), + INCOMPAT_ENV((short) 12, "Incompatible Envelope"), + INVALID_SUB_ID((short) 13, "Invalid SubscriberID"), + UNAUTH_AMID((short) 14, "Unauthorized AMID"), + NUM_CLASSIFIERS((short) 15, "Number of Classifiers Not Supported"), + POLICY_EXCEPTION((short) 16, "Policy Exception"), + INVALID_FIELD((short) 17, "Invalid Field Value in Object"), + TRANSPORT_ERROR((short) 18, "Transport Error"), + UNK_GATE_CMD((short) 19, "Unknown Gate Command"), + DOCSIS_1_CM((short) 20, "DOCSIS 1.0 CM"), + NUM_CM_SID((short) 21, "Number of SIDs exceeded in CM"), + NUM_CMTS_SID((short) 22, "Number of SIDs exceeded in CMTS"), + UNAUTH_PSID((short) 23, "Unauthorized PSID"), + NO_STATE_PDP((short) 24, "No State for PDP"), + UNSUP_SYNC_TYPE((short) 25, "Unsupported Synch Type"), + STATE_INCMPL((short) 26, "State Data Incomplete"), + UP_DROP_UNSUPPORT((short) 27, "Upstream Drop Unsupported"), + MULTI_GATE_ERR((short) 28, "Multicast Gate Error"), + MULTI_VOL_LIMIT((short) 29, "Multicast Volume Limit Unsupported"), + MULTI_UNCOMMITTED((short) 30, "Uncommitted Multicast Not Supported"), + MULTI_GATE_MOD((short) 31, "Multicast Gate Modification Not Supported"), + MULTI_UP_ERR((short) 32, "Upstream Multicast Not Supported"), + MULTI_GATE_INCOMPAT((short) 33, "Multicast GateSpec incompatibility"), + MULTI_QOS_ERR((short) 34, "Multicast QoS Error"), + MULTI_DN_RESEQ((short) 35, "Multicast Downstream Resequencing mismatch"), + OTHER_UNSPECIFIED((short) 127, "Other, Unspecified Error"); private final short code; private final String description; - Description(short code, String description) { + ErrorCode(short code, String description) { this.code = code; this.description = description; } @@ -68,29 +87,80 @@ public interface IPCMMError extends IPCMMBaseObject { return code; } - public static String valueOf(short errCode) { - switch (errCode) { - case 1: - case 2: - case 4: - return errors[errCode - 1]; - case 127: - return errors[32]; - default: - if (errCode > 35 || errCode < 1) - throw new IllegalArgumentException("unrecongnized error code : " + errCode); - return errors[errCode - 4]; + public static ErrorCode valueOf(final short index) { + switch (index) { + case 0: + return NA; + case 1: + return INSUFF_RES; + case 2: + return UNK_GATE_ID; + case 6: + return MISSING_REQ_OBJ; + case 7: + return INVALID_OBJ; + case 8: + return VOL_USG_LMT; + case 9: + return TIME_USG_LMT; + case 10: + return SESSN_CLASS_LMT; + case 11: + return UNDEF_SCN_NAME; + case 12: + return INCOMPAT_ENV; + case 13: + return INVALID_SUB_ID; + case 14: + return UNAUTH_AMID; + case 15: + return NUM_CLASSIFIERS; + case 16: + return POLICY_EXCEPTION; + case 17: + return INVALID_FIELD; + case 18: + return TRANSPORT_ERROR; + case 19: + return UNK_GATE_CMD; + case 20: + return DOCSIS_1_CM; + case 21: + return NUM_CM_SID; + case 22: + return NUM_CMTS_SID; + case 23: + return UNAUTH_PSID; + case 24: + return NO_STATE_PDP; + case 25: + return UNSUP_SYNC_TYPE; + case 26: + return STATE_INCMPL; + case 27: + return UP_DROP_UNSUPPORT; + case 28: + return MULTI_GATE_ERR; + case 29: + return MULTI_VOL_LIMIT; + case 30: + return MULTI_UNCOMMITTED; + case 31: + return MULTI_GATE_MOD; + case 32: + return MULTI_UP_ERR; + case 33: + return MULTI_GATE_INCOMPAT; + case 34: + return MULTI_QOS_ERR; + case 35: + return MULTI_DN_RESEQ; + case 127: + return OTHER_UNSPECIFIED; + default: + return null; } } } - void setErrorCode(short ErrorCode); - - short getErrorCode(); - - void setErrorSubcode(short ErrorSubcode); - - short getErrorSubcode(); - - String getDescription(); } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java b/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java index ada6a51..f140675 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/IPCMMGate.java @@ -42,20 +42,6 @@ public interface IPCMMGate { */ void setGateID(IGateID gateid); - /** - * AMID is the handle that identifies the Application Manager and - * Application Type - * - */ - void setAMID(IAMID iamid); - - /** - * SubscriberID uniquely identifies the Client for which the policy is being - * set. - * - */ - void setSubscriberID(ISubscriberID subscriberID); - /** * (i.e., QoS limits, timers, etc.). * diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java b/packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java index 11ca7f2..fabe097 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/ISessionClassID.java @@ -1,6 +1,7 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates; /** @@ -15,14 +16,6 @@ public interface ISessionClassID { */ byte getPriority(); - /** - * sets the priority value (0-7) - * - * @param value - * priority - */ - void setPriority(byte value); - /** * gets the preemption value; * @@ -30,14 +23,6 @@ public interface ISessionClassID { */ byte getPreemption(); - /** - * * sets the preemption - * - * @param value - * preemption - */ - void setPreemption(byte value); - /** * compress the priority and preemption to a single byte value; * diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java b/packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java index d71e194..48f1597 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/ISubscriberID.java @@ -1,14 +1,13 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; -import java.net.InetAddress; - import org.pcmm.base.IPCMMBaseObject; +import java.net.InetAddress; + /** *

* The SubscriberID, consisting of the IPv4 or IPv6 address of either the CM or @@ -33,9 +32,8 @@ import org.pcmm.base.IPCMMBaseObject; */ public interface ISubscriberID extends IPCMMBaseObject { - static final short LENGTH = 8; - static final byte SNUM = 3; - static final byte STYPE = 1; + + byte STYPE = 1; /** * source IP address for the PCMM gate. @@ -44,6 +42,4 @@ public interface ISubscriberID extends IPCMMBaseObject { */ InetAddress getSourceIPAddress(); - void setSourceIPAddress(InetAddress address); - } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java b/packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java index 9e21675..3360ecd 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/ITrafficProfile.java @@ -1,22 +1,15 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ - package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; public interface ITrafficProfile extends IPCMMBaseObject { - static final byte SNUM = 7; - - /** - * 0x001, 0x011 and 0x111 (Authorized, Reserved, and Committed) are allowed - * - * @param en - */ - void setEnvelop(byte en); + // Authorized + byte DEFAULT_ENVELOP = 0x7; byte getEnvelop(); diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java b/packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java index e835b39..f44618d 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/ITransactionID.java @@ -1,43 +1,110 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates; import org.pcmm.base.IPCMMBaseObject; /** + * TransactionID is a 2-byte unsigned integer quantity, which contains a token that is used by the Application Manager + * to match responses from the Policy Server and by the Policy Server to match responses from the CMTS to the + * previous requests. The TransactionID MUST also contain the command type that identifies the action to be taken or + * response. */ public interface ITransactionID extends IPCMMBaseObject { - static final byte SNUM = 1; - static final byte STYPE = 1; - static final short LENGTH = 8; - - static final short GateSet = 4; - static final short GateSetAck = 5; - static final short GateSetErr = 6; - static final short GateInfo = 7; - static final short GateInfoAck = 8; - static final short GateInfoErr = 9; - static final short GateDelete = 10; - static final short GateDeleteAck = 11; - static final short GateDeleteErr = 12; - static final short GateReportState = 15; - static final short GateCmdErr = 16; - static final short PDPConfig = 17; - static final short PDPConfigAck = 18; - static final short PDPConfigErr = 19; - static final short SynchRequest = 20; - static final short SynchReport = 21; - static final short SynchComplete = 22; - static final short MsgReceipt = 23; - - void setTransactionIdentifier(short id); + byte STYPE = 1; + /** + * Returns the transaction identifier value + * @return - the ID + */ short getTransactionIdentifier(); - void setGateCommandType(short type); + /** + * Returns the command type + * @return - the command type + */ + GateCommandType getGateCommandType(); + + /** + * The supported Synchronization types + */ + enum GateCommandType { + + GATE_SET((short) 4), + GATE_SET_ACK((short) 5), + GATE_SET_ERR((short) 6), + GATE_INFO((short) 7), + GATE_INFO_ACK((short) 8), + GATE_INFO_ERR((short) 9), + GATE_DELETE((short) 10), + GATE_DELETE_ACK((short) 11), + GATE_DELETE_ERR((short) 12), + GATE_RPT_STATE((short) 15), + GATE_CMD_ERR((short) 16), + PDP_CONFIG((short) 17), + PDP_CONFIG_ACK((short) 18), + PDP_CONFIG_ERR((short) 19), + SYNC_REQUEST((short) 20), + SYNC_RPT((short) 21), + SYNC_COMPLETE((short) 22), + MSG_RECEIPT((short) 23); + + GateCommandType(short value) { + this.value = value; + } + + public short getValue() { + return value; + } + + public static GateCommandType valueOf(short v) { + switch (v) { + case 4: + return GateCommandType.GATE_SET; + case 5: + return GateCommandType.GATE_SET_ACK; + case 6: + return GateCommandType.GATE_SET_ERR; + case 7: + return GateCommandType.GATE_INFO; + case 8: + return GateCommandType.GATE_INFO_ACK; + case 9: + return GateCommandType.GATE_INFO_ERR; + case 10: + return GateCommandType.GATE_DELETE; + case 11: + return GateCommandType.GATE_DELETE_ACK; + case 12: + return GateCommandType.GATE_DELETE_ERR; + case 15: + return GateCommandType.GATE_RPT_STATE; + case 16: + return GateCommandType.GATE_CMD_ERR; + case 17: + return GateCommandType.PDP_CONFIG; + case 18: + return GateCommandType.PDP_CONFIG_ACK; + case 19: + return GateCommandType.PDP_CONFIG_ERR; + case 20: + return GateCommandType.SYNC_REQUEST; + case 21: + return GateCommandType.SYNC_RPT; + case 22: + return GateCommandType.SYNC_COMPLETE; + case 23: + return GateCommandType.MSG_RECEIPT; + default: + throw new IllegalArgumentException("not supported value"); + } + } + + private short value; - short getGateCommandType(); + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java index 4f1c3af..678dab2 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/AMID.java @@ -1,77 +1,93 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.IAMID; +import org.umu.cops.stack.COPSMsgParser; /** - * + * Implementation of the IAMID interface */ public class AMID extends PCMMBaseObject implements IAMID { /** - * + * Application Type is a 2-byte unsigned integer value which identifies the type of application that this gate is + * associated with. The Application Manager MUST include this object in all messages it issues to the Policy Server. + * The Policy Server MUST include the received AMID in all messages it issues down the CMTS in response to the + * messages it receives from the Application Manager. */ - public AMID() { - this(LENGTH, STYPE, SNUM); - } + private final short appType; /** - * @param data + * The application manager tag */ - public AMID(byte[] data) { - super(data); - } + private final short appMgrTag; /** - * @param len - * @param sType - * @param sNum + * Constructor + * @param appType - the application type + * @param appMgrTag - the application manager tag */ - public AMID(short len, byte sType, byte sNum) { - super(len, sType, sNum); + public AMID(final short appType, final short appMgrTag) { + super(SNum.AMID, STYPE); + this.appType = appType; + this.appMgrTag = appMgrTag; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IAMID#setApplicationType(short) - */ @Override - public void setApplicationType(short type) { - setShort(type, (short) 0); + public short getApplicationType() { + return appType; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IAMID#getApplicationType() - */ @Override - public short getApplicationType() { - return getShort((short) 0); + public short getApplicationMgrTag() { + return appMgrTag; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IAMID#setApplicationMgrTag(short) - */ @Override - public void setApplicationMgrTag(short type) { - setShort(type, (short) 2); + protected byte[] getBytes() { + final byte[] appTypeBytes = COPSMsgParser.shortToBytes(appType); + final byte[] appMgrBytes = COPSMsgParser.shortToBytes(appMgrTag); + final byte[] data = new byte[appTypeBytes.length + appMgrBytes.length]; + System.arraycopy(appTypeBytes, 0, data, 0, appTypeBytes.length); + System.arraycopy(appMgrBytes, 0, data, appTypeBytes.length, appMgrBytes.length); + return data; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IAMID#getApplicationMgrTag() - */ @Override - public short getApplicationMgrTag() { - return getShort((short) 2); + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof AMID)) { + return false; + } + if (!super.equals(o)) { + return false; + } + + final AMID amid = (AMID) o; + return appType == amid.appType && appMgrTag == amid.appMgrTag; } + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (int) appType; + result = 31 * result + (int) appMgrTag; + return result; + } + + /** + * Returns an AMID object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static AMID parse(final byte[] data) { + return new AMID(COPSMsgParser.bytesToShort(data[0], data[1]), COPSMsgParser.bytesToShort(data[2], data[3])); + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/BEEnvelop.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/BEEnvelop.java new file mode 100644 index 0000000..4552550 --- /dev/null +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/BEEnvelop.java @@ -0,0 +1,262 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import com.google.common.primitives.Bytes; +import org.umu.cops.stack.COPSMsgParser; + +import java.util.ArrayList; +import java.util.List; + +/** + * Class for use as member to the ITrafficProfile#BestEffortService class. + */ +public class BEEnvelop { + + public static final byte DEFAULT_TRAFFIC_PRIORITY = 0; + + public static final int DEFAULT_MAX_TRAFFIC_BURST = 3044; + + /** + * Traffic Priority is a 1-byte unsigned integer field specifying the relative priority assigned to the Service Flow + * in comparison with other flows. This field is fully defined in section C.2.2.5.1 of [1]. A default Traffic + * Priority of SHOULD be used if a specific Traffic Priority value is not required. + */ + private final byte trafficPriority; + + /** + * Request/Transmission Policy is a 4-byte bit field as defined in section C.2.2.6.3. A default Request/Transmission + * policy of 0 SHOULD be used if a specific Request/Transmission Policy value is not required. + */ + private final int transPolicy; + + /** + * Maximum Sustained Traffic Rate is a 4-byte unsigned integer field specifying the rate parameter, in bits/sec. + * A value of 0 indicates that no explicitly-enforced Maximum Sustained Rate is requested. A default Maximum + * Sustained Traffic Rate of 0 SHOULD be used if a specific Maximum Sustained Traffic Rate is not required. + */ + private final int maxSusTrafficRate; + + /** + * Maximum Traffic Burst is a 4-byte unsigned integer field specifying the token bucket size, in bytes, for a + * tokenbucket-based rate limit for this Service Flow. This field is fully defined in section C.2.2.5.3 of [1]. + * A default Maximum Traffic Burst of 3044 bytes SHOULD be used if a specific Maximum Traffic Burst is not required. + * The value of this parameter has no effect unless a non-zero value has been provided Rate parameter. + */ + private final int maxTrafficBurst; + + /** + * Minimum Reserved Traffic Rate is a 4-byte unsigned integer field specifying the minimum rate, in bits/sec, + * reserved for this Service Flow. This field is fully defined in section C.2.2.5.4. A default Mini Rate of 0 SHOULD + * be used if a specific Minimum Reserved Traffic Rate is not required. + */ + private final int minResTrafficRate; + + /** + * Assumed Minimum Reserved Traffic Rate Packet Size is a 2-byte unsigned integer field specifying an assumed + * minimum packet size, in bytes, for which the Minimum Reserved Traffic Rate will be provided for this flow. This + * field is fully defined in section C.2.2.5.5. A default Assumed Minimum Reserved Traffic Rate Packet Size of + * 0 SHOULD be used if a specific Assumed Minimum Reserved Traffic Rate Packet size is not required. Upon receip + * of a value of 0 the CMTS MUST utilize its implementation-specific default size for this parameter, not 0 bytes. + */ + private final short assumedMinConcatBurst; + + /** + * Maximum Concatenated Burst is a 2-byte unsigned integer specifying the maximum concatenated burst (in bytes) + * which a Service Flow is allowed. This field is fully defined in section C.2.2.6.1. A value of 0 means + * there is no limit. A default Maximum Concatenated Burst of 1522 bytes SHOULD be used if a specific Maximum + * Concatenated Burst is not required. + */ + private final short maxConcatBurst; + + /** + * Upstream Peak Traffic Rate is a 4-byte unsigned integer specifying the Peak traffic rate (in bits per second) + * which a Service Flow is allowed. This field is fully defined in section C.2.2.5.10.1. + */ + private final int upPeakTrafficRate; + + /* + * Attribute Masks define a specific set of attributes associated with a DOCSIS 3.0 service flow. The CMTS MUST + * ignore the bonded bit in the Required and Forbidden Attribute Mask objects if the cable modem associated with the + * service flow is operating in pre-3.0 DOCSIS mode. The Required Attribute Mask limits the set of channels and + * bonding groups to which the CMTS assigns the service flow by requiring certain attributes. This field is fully + * defined in section C.2.2.3.6 of [1]. The Forbidden Attribute Mask limits the set of channels and bonding groups + * to which the CMTS assigns the service flow by forbidding certain attributes. This field is fully defined in + * section C.2.2.3.7. The CMTS is free to assign the service flow to any channel that satisfies the traffic profile + * if no channel is available that satisfies the Required Attribute Mask and Forbidden Attribute Mask for the + * service flow. The Attribute Aggregation Rule Mask provides guidance to the CMTS as to how it might use the + * attribute masks of individual channels to construct a dynamic bonding group for this service flow. This field is + * fully described in section "Service Flow Attribute Aggregation Rule Mask". As described in that section a default + * Attribute Aggregation Rule Mask of 0 SHOULD be used if specific Attribute Aggregation Rules are not required. + * The Buffer Control parameters libit the maximum queue depth of a Service Flow. The service flow buffer holds the + * packets that are enqueued for transmission for the service flow. The size of the service flow buffer sets the + * maximum queue depth, and upper limit on the amount of data that can be enqueued for transmission at any time by + * the service flow. By providing the ability to control per-service flow buffers. the below Buffer Control + * parameters provide a means of balancing throughput and latency in a standardized and configurable manner. + */ + + /** + * Required Attribute Mask (see explanation above) + */ + private final int reqAttrMask; + + /** + * Forbidden Attribute Mask (see explanation above) + */ + private final int forbidAttrMask; + + /** + * Attribute Aggregation Rule Mask (see explanation above) + */ + private final int attrAggRuleMask; + + /** + * Minimum Buffer is a 4-byte unsigned integer parameter that defines a lower limit for the size of the buffer that + * is to be provided for a service flow. This field is fully defined in section C.2.2.5.11.3. If this parameter is + * omitted. The Minimum Buffer defaluts to a value of 0, which indicates that there is no lower limit. + */ + private final int minBuffer; + + /** + * Target Buffer is a 4-byte unsigned integer parameter that defines a desired value for the size of the buffer that + * is to be provided for a service flow. This field is fully defined in section C.2.2.5.11.4. If this parameter is + * omitted or set to a value of 0, the device selects any buffer size within the range of the Minimum and Maximum + * Buffers, via a vendor specific algorithm. + */ + private final int targetBuffer; + + /** + * Maximum Buffer is a 4-byte unsigned integer parameter that defines an upper limit for the size of the buffer that + * is to be provided for a service flow. This field is fully defined in section C.2.2.5.11.5. If this parameter is + * omitted or set to a value of 0, the Maximum Buffer defaults to a value of no limit. + */ + private final int maxBuffer; + + /** + * Constructor + * @param trafficPriority - the Traffic Priority + * @param transPolicy - the Requested Transmission Policy + * @param maxSusTrafficRate - the Maximum Sustained Traffic Rate + * @param maxTrafficBurst - the Maximum Traffic Burst Rate + * @param minResTrafficRate - the Minimum Reserved Traffic Rate + * @param assumedMinConcatBurst - the Assumed Minimum Reserved Traffic Rate Packet Size + * @param maxConcatBurst - the Maximum Concatenated Burst + * @param upPeakTrafficRate - the Upstream Peak Traffic Rate + * @param reqAttrMask - the Required Attribute Mask + * @param forbidAttrMask - the Forbidden Attribute Mask + * @param attrAggRuleMask - the Attribute Aggregation Rule Mask + * @param minBuffer - the Minimum Buffer + * @param targetBuffer - the Target Buffer + * @param maxBuffer - the Maximum Buffer + */ + public BEEnvelop(byte trafficPriority, int transPolicy, int maxSusTrafficRate, int maxTrafficBurst, + int minResTrafficRate, short assumedMinConcatBurst, short maxConcatBurst, int upPeakTrafficRate, + int reqAttrMask, int forbidAttrMask, int attrAggRuleMask, int minBuffer, int targetBuffer, + int maxBuffer) { + this.trafficPriority = trafficPriority; + this.transPolicy = transPolicy; + this.maxSusTrafficRate = maxSusTrafficRate; + this.maxTrafficBurst = maxTrafficBurst; + this.minResTrafficRate = minResTrafficRate; + this.assumedMinConcatBurst = assumedMinConcatBurst; + this.maxConcatBurst = maxConcatBurst; + this.upPeakTrafficRate = upPeakTrafficRate; + this.reqAttrMask = reqAttrMask; + this.forbidAttrMask = forbidAttrMask; + this.attrAggRuleMask = attrAggRuleMask; + this.minBuffer = minBuffer; + this.targetBuffer = targetBuffer; + this.maxBuffer = maxBuffer; + } + + /** + * Returns a List of Bytes which can be parsed back into an equivalent object. This method is generally used when + * streaming this object over a Socket + * @return - the byte translation of this object + */ + public List getBytes() { + final List byteList = new ArrayList<>(); + byteList.addAll(Bytes.asList(trafficPriority, (byte) 0, (byte) 0, (byte) 0)); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(transPolicy))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(maxSusTrafficRate))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(maxTrafficBurst))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(minResTrafficRate))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(assumedMinConcatBurst))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(maxConcatBurst))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(upPeakTrafficRate))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(reqAttrMask))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(forbidAttrMask))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(attrAggRuleMask))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(minBuffer))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(targetBuffer))); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(maxBuffer))); + return byteList; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof BEEnvelop)) { + return false; + } + + final BEEnvelop beEnvelop = (BEEnvelop) o; + + return trafficPriority == beEnvelop.trafficPriority && transPolicy == beEnvelop.transPolicy && + maxSusTrafficRate == beEnvelop.maxSusTrafficRate && maxTrafficBurst == beEnvelop.maxTrafficBurst && + minResTrafficRate == beEnvelop.minResTrafficRate && + assumedMinConcatBurst == beEnvelop.assumedMinConcatBurst && + maxConcatBurst == beEnvelop.maxConcatBurst && upPeakTrafficRate == beEnvelop.upPeakTrafficRate && + reqAttrMask == beEnvelop.reqAttrMask && forbidAttrMask == beEnvelop.forbidAttrMask && + attrAggRuleMask == beEnvelop.attrAggRuleMask && minBuffer == beEnvelop.minBuffer && + targetBuffer == beEnvelop.targetBuffer && maxBuffer == beEnvelop.maxBuffer; + + } + + @Override + public int hashCode() { + int result = (int) trafficPriority; + result = 31 * result + transPolicy; + result = 31 * result + maxSusTrafficRate; + result = 31 * result + maxTrafficBurst; + result = 31 * result + minResTrafficRate; + result = 31 * result + (int) assumedMinConcatBurst; + result = 31 * result + (int) maxConcatBurst; + result = 31 * result + upPeakTrafficRate; + result = 31 * result + reqAttrMask; + result = 31 * result + forbidAttrMask; + result = 31 * result + attrAggRuleMask; + result = 31 * result + minBuffer; + result = 31 * result + targetBuffer; + result = 31 * result + maxBuffer; + return result; + } + + /** + * Returns an BEEnvelop object from a byte array + * @param data - the data to parse + * @return - the object or null if cannot be parsed + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static BEEnvelop parse(final byte[] data) { + if (data.length != 52) return null; + return new BEEnvelop(data[0], + COPSMsgParser.bytesToInt(data[4], data[5], data[6], data[7]), + COPSMsgParser.bytesToInt(data[8], data[9], data[10], data[11]), + COPSMsgParser.bytesToInt(data[12], data[13], data[14], data[15]), + COPSMsgParser.bytesToInt(data[16], data[17], data[18], data[19]), + COPSMsgParser.bytesToShort(data[20], data[21]), + COPSMsgParser.bytesToShort(data[22], data[23]), + COPSMsgParser.bytesToInt(data[24], data[25], data[26], data[27]), + COPSMsgParser.bytesToInt(data[28], data[29], data[30], data[31]), + COPSMsgParser.bytesToInt(data[32], data[33], data[34], data[35]), + COPSMsgParser.bytesToInt(data[36], data[37], data[38], data[39]), + COPSMsgParser.bytesToInt(data[40], data[41], data[42], data[43]), + COPSMsgParser.bytesToInt(data[44], data[45], data[46], data[47]), + COPSMsgParser.bytesToInt(data[48], data[49], data[50], data[51])); + } +} diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java index 4e0e9b0..d7d7e8b 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/BestEffortService.java @@ -1,79 +1,88 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ -package org.pcmm.gates.impl; -import java.util.Arrays; +package org.pcmm.gates.impl; -// import org.junit.Assert; +import com.google.common.primitives.Bytes; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.ITrafficProfile; -import org.umu.cops.stack.COPSData; + +import java.util.ArrayList; +import java.util.List; /** - * + * The Best Effort object defines the Traffic Profile associated with a gate through an upstream DOCSIS-specific + * parameterization scheme. */ -public class BestEffortService extends PCMMBaseObject implements - ITrafficProfile { +public class BestEffortService extends PCMMBaseObject implements ITrafficProfile { + public static final byte STYPE = 3; // XXX -> 60=0x3C, 112 = 0x70, 164=0xA4 // Length = 44=0x2C, 80=0x50 or 116=0x74 - public static final short LENGTH = 44; public static final byte DEFAULT_TRAFFIC_PRIORITY = 0; - // Authorized - public static final byte DEFAULT_ENVELOP = 0x7; public static final int DEFAULT_MAX_TRAFFIC_BURST = 3044; - private BEEnvelop authorizedEnvelop; + /** + * The envelope + */ + private final byte envelope; - private BEEnvelop reservedEnvelop; + /** + * The authorized envelope. See BEEnvelope for description of the attributes. MUST NOT be NULL. + */ + private final BEEnvelop authorizedEnvelop; - private BEEnvelop committedEnvelop; + /** + * The reserved envelope. See BEEnvelope for description of the attributes. CAN BE NULL. + */ + private final BEEnvelop reservedEnvelop; /** - * - * @param e - * envelop + * The committed envelope. See BEEnvelope for description of the attributes. CAN BE NULL. */ - public BestEffortService(byte e) { - super((short) (e == 1 ? LENGTH : (e == 7 ? 116 : 80)), STYPE, SNUM); - setEnvelop(e); - authorizedEnvelop = new BEEnvelop(); - if (e > 1) { - reservedEnvelop = new BEEnvelop(); - if (e == 7) - committedEnvelop = new BEEnvelop(); - } - } + private final BEEnvelop committedEnvelop; - public BestEffortService(byte[] bytes) { - super(bytes); - byte e = getEnvelop(); - authorizedEnvelop = new BEEnvelop(headPadding(offset, Arrays.copyOfRange(bytes, 8, LENGTH))); - if (e > 1) { - reservedEnvelop = new BEEnvelop(headPadding(offset, Arrays.copyOfRange(bytes, LENGTH, 80))); - if (e == 7) - committedEnvelop = new BEEnvelop(headPadding(offset, Arrays.copyOfRange(bytes, 80, 116))); - } + /** + * General use constructor + * @param auth - the authorized envelope (required) + * @param reserved - the reserved envelope (optional) + * @param committed - the committed envelope (optional) + */ + public BestEffortService(final BEEnvelop auth, final BEEnvelop reserved, final BEEnvelop committed) { + this(DEFAULT_ENVELOP, auth, reserved, committed); } - @Override - public void setEnvelop(byte e) { - setLength((short) (e == 1 ? LENGTH : (e == 7 ? 116 : 80))); - // reset cops data to fit the new length - byte[] array = new byte[getLength() - offset]; - Arrays.fill(array, (byte) 0); - setData(new COPSData(array, 0, array.length)); - setByte(e, (short) 0); + /** + * Constructor generally used for byte parsing only. + * @param envelope - the envelope value + * @param auth - the authorized envelope (required) + * @param reserved - the reserved envelope (optional) + * @param committed - the committed envelope (optional) + */ + protected BestEffortService(final byte envelope, final BEEnvelop auth, final BEEnvelop reserved, + final BEEnvelop committed) { + super(SNum.TRAFFIC_PROFILE, STYPE); + if (auth == null) throw new IllegalArgumentException("Authorized envelope must not be null"); + + // TODO - Cannot figure out any other means to parse the bytes unless this is true. Determine if correct??? + if (reserved == null && committed != null) + throw new IllegalArgumentException("Cannot have a committed envelope without a reserved"); + + this.envelope = envelope; + this.authorizedEnvelop = auth; + this.reservedEnvelop = reserved; + this.committedEnvelop = committed; } @Override public byte getEnvelop() { - return getByte((short) 0); + return envelope; } + // Getters public BEEnvelop getAuthorizedEnvelop() { return authorizedEnvelop; } @@ -87,125 +96,64 @@ public class BestEffortService extends PCMMBaseObject implements } @Override - public byte[] getAsBinaryArray() { - byte[] returnBuffer = super.getAsBinaryArray(); - - {// fill buffer with the Authorized Envelop - byte[] authEnv = Arrays.copyOfRange(getAuthorizedEnvelop().getAsBinaryArray(), offset, BEEnvelop.LENGHT); - // offset + 4 since the Envelop data begin from byte nb 8 - System.arraycopy(authEnv, 0, returnBuffer, offset + 4, authEnv.length); - } - if (getReservedEnvelop() != null) { - byte[] reservedEnv = Arrays.copyOfRange(getReservedEnvelop().getAsBinaryArray(), offset, BEEnvelop.LENGHT); - System.arraycopy(reservedEnv, 0, returnBuffer, LENGTH, reservedEnv.length); - } - if (getCommittedEnvelop() != null) { - byte[] commitEnv = Arrays.copyOfRange(getCommittedEnvelop().getAsBinaryArray(), offset, BEEnvelop.LENGHT); - System.arraycopy(commitEnv, 0, returnBuffer, LENGTH + 36, commitEnv.length); - } - return returnBuffer; + public byte[] getBytes() { + final List byteList = new ArrayList<>(); + byteList.addAll(Bytes.asList(envelope, (byte) 0, (byte) 0, (byte) 0)); + byteList.addAll(authorizedEnvelop.getBytes()); + if (reservedEnvelop != null) byteList.addAll(reservedEnvelop.getBytes()); + if (committedEnvelop != null) byteList.addAll(committedEnvelop.getBytes()); + return Bytes.toArray(byteList); } - /** - * - * - */ - public static class BEEnvelop extends PCMMBaseObject { - // basically we need 36 bytes but since PCMMBasedObject needs 4 bytes - // more we allocate 40 bytes and then subtract them when setting BE - // data. - private final static short LENGHT = 40; - - protected BEEnvelop() { - super(LENGHT, (byte) 0, (byte) 0); - setTrafficPriority(DEFAULT_TRAFFIC_PRIORITY); - } - - protected BEEnvelop(byte[] buffer) { - super(buffer); - } - - public void setTrafficPriority(byte p) { - setByte(p, (short) 0); - } - - public byte getTrafficPriority() { - return getByte((short) 0); - } - - // - public void setRequestTransmissionPolicy(int p) { - setInt(p, (short) 4); - } - - public int getRequestTransmissionPolicy() { - return getInt((short) 4); - } - - public int getMaximumSustainedTrafficRate() { - return getInt((short) 8); - } - - public void setMaximumSustainedTrafficRate(int p) { - setInt(p, (short) 8); - } - - public int getMaximumTrafficBurst() { - return getInt((short) 12); - } - - public void setMaximumTrafficBurst(int p) { - setInt(p, (short) 12); - } - - public int getMinimumReservedTrafficRate() { - return getInt((short) 16); - } - - public void setMinimumReservedTrafficRate(int p) { - setInt(p, (short) 16); - } - - public short getAssumedMinimumReservedTrafficRatePacketSize() { - return getShort((short) 20); - } - - public void setAssumedMinimumReservedTrafficRatePacketSize(short p) { - setShort(p, (short) 20); - } - - public short getMaximumConcatenatedBurst() { - return getShort((short) 22); - } - - public void setMaximumConcatenatedBurst(short p) { - setShort(p, (short) 22); - } - - public int getRequiredAttributeMask() { - return getInt((short) 24); + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; } - - public void setRequiredAttributeMask(int p) { - setInt(p, (short) 24); + if (!(o instanceof BestEffortService)) { + return false; } - - public int getForbiddenAttributeMask() { - return getInt((short) 28); + if (!super.equals(o)) { + return false; } + final BestEffortService that = (BestEffortService) o; + return envelope == that.envelope && authorizedEnvelop.equals(that.authorizedEnvelop) && + !(reservedEnvelop != null ? !reservedEnvelop.equals(that.reservedEnvelop) : + that.reservedEnvelop != null) && + !(committedEnvelop != null ? !committedEnvelop.equals(that.committedEnvelop) : + that.committedEnvelop != null); - public void setForbiddenAttributeMask(int p) { - setInt(p, (short) 28); - } - - public int getAttributeAggregationRuleMask() { - return getInt((short) 32); - } + } - public void setAttributeAggregationRuleMask(int p) { - setInt(p, (short) 32); - } + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (int) envelope; + result = 31 * result + authorizedEnvelop.hashCode(); + result = 31 * result + (reservedEnvelop != null ? reservedEnvelop.hashCode() : 0); + result = 31 * result + (committedEnvelop != null ? committedEnvelop.hashCode() : 0); + return result; + } + /** + * Returns a BestEffortService object from a byte array + * @param data - the data to parse + * @return - the object or null if cannot be parsed + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static BestEffortService parse(final byte[] data) { + final List bytes = Bytes.asList(data); + bytes.subList(0, 51); + if (data.length >= 56 && data.length < 108) + return new BestEffortService(data[0], BEEnvelop.parse(Bytes.toArray(bytes.subList(4, 56))), null, null); + else if (data.length >= 108 && data.length < 160) + return new BestEffortService(data[0], BEEnvelop.parse(Bytes.toArray(bytes.subList(4, 56))), + BEEnvelop.parse(Bytes.toArray(bytes.subList(56, 108))), null); + else if (data.length >= 160) + return new BestEffortService(data[0], BEEnvelop.parse(Bytes.toArray(bytes.subList(4, 56))), + BEEnvelop.parse(Bytes.toArray(bytes.subList(56, 108))), + BEEnvelop.parse(Bytes.toArray(bytes.subList(108, 160)))); + else return null; } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java index 6fa5d79..d5d4d71 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/Classifier.java @@ -1,193 +1,223 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; +import com.google.common.primitives.Bytes; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.IClassifier; +import org.umu.cops.stack.COPSMsgParser; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; /** - * TODO - Cleanup this interface + * Implementation of the IClassifier interface */ public class Classifier extends PCMMBaseObject implements IClassifier { /** - * + * The classifier's protocol */ - public Classifier() { - this(LENGTH, STYPE, SNUM); - } + protected final Protocol protocol; /** - * @param data - the data to add + * When enabled, the CMTS must mark the packets traversing the CMTS DSCP/TOS value */ - public Classifier(byte[] data) { - super(data); - } + protected final byte tosOverwrite; /** - * @param len - the classifier's length - * @param sType - the sType value - * @param sNum - the sNum value + * The TOS mask value */ - public Classifier(short len, byte sType, byte sNum) { - super(len, sType, sNum); - } + protected final byte tosMask; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getDestinationIPAddress() + // Instances of this and ExtendedClassifier require Inet4Address objects + + /** + * The source address */ - @Override - public InetAddress getDestinationIPAddress() { - try { - return Inet4Address.getByAddress(getBytes((short) 8, (short) 4)); - } catch (UnknownHostException e) { - return null; - } - } + protected final InetAddress srcAddress; - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.IClassifier#setDestinationIPAddress(java.net.InetAddress) + /** + * The destination address */ - @Override - public void setDestinationIPAddress(InetAddress address) { - setBytes(address.getAddress(), (short) 8); - } + protected final InetAddress dstAddress; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getDestinationPort() + /** + * The source port number */ - @Override - public short getDestinationPort() { - return getShort((short) 14); - } + protected final short srcPort; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setDestinationPort(short) + /** + * The destination port number */ - @Override - public void setDestinationPort(short p) { - setShort(p, (short) 14); - } + protected final short dstPort; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getSourceIPAddress() + /** + * The priority value */ - @Override - public InetAddress getSourceIPAddress() { - try { - return Inet4Address.getByAddress(getBytes((short) 4, (short) 4)); - } catch (UnknownHostException e) { - return null; - } - } + protected final byte priority; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setSourceIPAddress(java.net.InetAddress) + /** + * Constructor for sub-classes + * @param protocol - the protocol being sent through the gate (can be null for IPv6Classifier instances) + * @param tosOverwrite - ENABLE/DISABLE + * @param tosMask - the mask + * @param srcAddress - the source IP + * @param dstAddress - the destination IP + * @param srcPort - the source port + * @param dstPort - the destination port + * @param priority - the priority value */ - @Override - public void setSourceIPAddress(InetAddress a) { - setBytes(a.getAddress(), (short) 4); + public Classifier(final Protocol protocol, final byte tosOverwrite, final byte tosMask, + final Inet4Address srcAddress, final Inet4Address dstAddress, final short srcPort, + final short dstPort, final byte priority) { + this(STYPE, protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort, dstPort, priority); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getSourcePort() + /** + * Constructor for sub-classes + * @param sType - the type of classifier + * @param protocol - the protocol being sent through the gate + * @param tosOverwrite - ENABLE/DISABLE + * @param tosMask - the mask + * @param srcAddress - the source IP + * @param dstAddress - the destination IP + * @param srcPort - the source port + * @param dstPort - the destination port + * @param priority - the priority value */ + protected Classifier(final byte sType, final Protocol protocol, final byte tosOverwrite, final byte tosMask, + final InetAddress srcAddress, final InetAddress dstAddress, final short srcPort, + final short dstPort, final byte priority) { + super(SNum.CLASSIFIERS, sType); + + if (protocol == null && !(this instanceof IPv6Classifier)) + throw new IllegalArgumentException("Protocol value must not be null"); + if (srcAddress == null) throw new IllegalArgumentException("Source address value must not be null"); + if (dstAddress == null) throw new IllegalArgumentException("Destination address value must not be null"); + + this.protocol = protocol; + this.tosOverwrite = tosOverwrite; + this.tosMask = tosMask; + this.srcAddress = srcAddress; + this.dstAddress = dstAddress; + this.srcPort = srcPort; + this.dstPort = dstPort; + this.priority = priority; + } + @Override - public short getSourcePort() { - return getShort((short) 12); + public InetAddress getDestinationIPAddress() { + return dstAddress; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setSourcePort(short) - */ @Override - public void setSourcePort(short p) { - setShort(p, (short) 12); + public short getDestinationPort() { + return dstPort; + } + @Override + public InetAddress getSourceIPAddress() { + return srcAddress; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getProtocol() - */ @Override - public short getProtocol() { - return getShort((short) 0); + public short getSourcePort() { + return srcPort; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setProtocol(short) - */ @Override - public void setProtocol(short p) { - setShort(p, (short) 0); + public Protocol getProtocol() { + return protocol; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getPriority() - */ @Override public byte getPriority() { - return getBytes((short) 16, (short) 1)[0]; + return priority; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setPriority(byte) - */ @Override - public void setPriority(byte p) { - setBytes(new byte[] { p }, (short) 16); + public byte getDSCPTOS() { + return tosOverwrite; } @Override - public byte getDSCPTOS() { - return getBytes((short) 2, (short) 1)[0]; + public byte getDSCPTOSMask() { + return tosMask; } @Override - public void setDSCPTOS(byte v) { - setBytes(new byte[] { v }, (short) 2); + protected byte[] getBytes() { + final List byteList = new ArrayList<>(Bytes.asList(COPSMsgParser.shortToBytes(protocol.getValue()))); + byteList.add(tosOverwrite); + byteList.add(tosMask); + byteList.addAll(Bytes.asList(srcAddress.getAddress())); + byteList.addAll(Bytes.asList(dstAddress.getAddress())); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(srcPort))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(dstPort))); + byteList.add(priority); + // reserved padding + byteList.addAll(Bytes.asList((byte) 0, (byte) 0, (byte) 0)); + + return Bytes.toArray(byteList); } @Override - public byte getDSCPTOSMask() { - return getBytes((short) 3, (short) 1)[0]; + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Classifier)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final Classifier that = (Classifier) o; + return tosMask == that.tosMask && srcPort == that.srcPort && dstPort == that.dstPort && + priority == that.priority && protocol == that.protocol && tosOverwrite == that.tosOverwrite && + srcAddress.equals(that.srcAddress) && dstAddress.equals(that.dstAddress); } @Override - public void setDSCPTOSMask(byte v) { - setBytes(new byte[] { v }, (short) 3); - + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (protocol != null ? protocol.hashCode() : 0); + result = 31 * result + (int) tosOverwrite; + result = 31 * result + (int) tosMask; + result = 31 * result + srcAddress.hashCode(); + result = 31 * result + dstAddress.hashCode(); + result = 31 * result + (int) srcPort; + result = 31 * result + (int) dstPort; + result = 31 * result + (int) priority; + return result; } + /** + * Returns a Classifier object from a byte array + * @param data - the data to parse + * @return - the object or null if cannot be parsed + * TODO - make me more robust as exceptions can be swallowed here. + */ + public static Classifier parse(final byte[] data) { + final List bytes = Bytes.asList(data); + + try { + final byte[] srcAddrBytes = Bytes.toArray(bytes.subList(4, 8)); + final byte[] dstAddrBytes = Bytes.toArray(bytes.subList(8, 12)); + return new Classifier(Protocol.valueOf(COPSMsgParser.bytesToShort(data[0], data[1])), data[2], data[3], + (Inet4Address)InetAddress.getByAddress(srcAddrBytes), + (Inet4Address)InetAddress.getByAddress(dstAddrBytes), + COPSMsgParser.bytesToShort(data[12], data[13]), COPSMsgParser.bytesToShort(data[14], data[15]), + data[16]); + } catch (UnknownHostException e) { + return null; + } + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java index 382b08a..528bb23 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfile.java @@ -1,76 +1,124 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.ITrafficProfile; +import java.util.Arrays; + /** + * The DOCSIS Service Class Name object defines the preconfigured Service Class Name associated with a Gate. * */ -public class DOCSISServiceClassNameTrafficProfile extends PCMMBaseObject - implements ITrafficProfile { +public class DOCSISServiceClassNameTrafficProfile extends PCMMBaseObject implements ITrafficProfile { public static final byte STYPE = 2; - public static final short LENGTH = 24; + public static final int SCN_MAX_LEN = 16; /** - * + * The Service Class Name. REQUIRED and length must be >= 2 and <= 16 characters */ - public DOCSISServiceClassNameTrafficProfile() { - this(LENGTH, STYPE, SNUM); - } + private final String scnName; /** - * @param data - the data bytes to parse + * The envelope */ - public DOCSISServiceClassNameTrafficProfile(byte[] data) { - super(data); - } + private final byte envelope; /** - * @param len - the classifier's length - * @param sType - the sType value - * @param sNum - the sNum value + * Constructor using the default envelope value + * @param scnName - the service class name (required characters >=2 && <=16 */ - public DOCSISServiceClassNameTrafficProfile(short len, byte sType, byte sNum) { - super(len, sType, sNum); - setEnvelop((byte) 0x7); + public DOCSISServiceClassNameTrafficProfile(final String scnName) { + this(DEFAULT_ENVELOP, scnName); } /** - * @return the serviceClassName + * Constructor to set all values + * @param envelope - the envelope value + * @param scnName - the service class name (required number of characters >=2 && <=16) */ - public String getServiceClassName() { - return new String(getBytes((short) 4, (short) 4)); + protected DOCSISServiceClassNameTrafficProfile(final byte envelope, final String scnName) { + super(SNum.TRAFFIC_PROFILE, STYPE); + if (scnName == null || scnName.length() < 2 || scnName.length() > SCN_MAX_LEN) + throw new IllegalArgumentException("Service class name must be between 2-16 characters"); + this.scnName = scnName; + this.envelope = envelope; + } + + @Override + public byte getEnvelop() { + return envelope; } /** - * @param serviceClassName - * the serviceClassName to set + * Returns the service class name value + * @return - the SCN value */ - public void setServiceClassName(String serviceClassName) { - setBytes(serviceClassName.getBytes(), (short) 4); + public String getScnName() { + return scnName; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ITrafficProfile#getEnvelop() - */ @Override - public byte getEnvelop() { - return getBytes((short) 0, (short) 1)[0]; + protected byte[] getBytes() { + final int padLen; + if ((scnName.length() % 4) != 0) padLen = 4 - (scnName.length() % 4); + else padLen = 0; + + final byte[] data = new byte[4 + scnName.getBytes().length + padLen]; + Arrays.fill(data, (byte) 0); + data[0] = envelope; + + System.arraycopy(scnName.getBytes(), 0, data, 4, scnName.getBytes().length); + return data; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof DOCSISServiceClassNameTrafficProfile)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final DOCSISServiceClassNameTrafficProfile that = (DOCSISServiceClassNameTrafficProfile) o; + return envelope == that.envelope && scnName.equals(that.scnName); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ITrafficProfile#setEnvelop(byte) - */ @Override - public void setEnvelop(byte en) { - setBytes(new byte[] { en }, (short) 0); + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + scnName.hashCode(); + result = 31 * result + (int) envelope; + return result; } + + /** + * Returns a DOCSISServiceClassNameTrafficProfile object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static DOCSISServiceClassNameTrafficProfile parse(final byte[] data) { + // variable i will denote the index where the data padding starts (if any) or the end of the array + int i = 4; + for (; i < data.length; i++) { + if (data[i] == 0) { + break; + } + } + final int nameLength = i - 4; + + final byte[] scnNameBytes = new byte[nameLength]; + System.arraycopy(data, 4, scnNameBytes, 0, nameLength); + final String scnName = new String(scnNameBytes); + return new DOCSISServiceClassNameTrafficProfile(data[0], scnName); + } + } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java index 2ebc2bc..2695309 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/ExtendedClassifier.java @@ -1,347 +1,251 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; -import org.pcmm.base.impl.PCMMBaseObject; +import com.google.common.primitives.Bytes; import org.pcmm.gates.IExtendedClassifier; +import org.umu.cops.stack.COPSMsgParser; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; /** - * + * Implementation of the IExtendedClassifier interface */ -public class ExtendedClassifier extends PCMMBaseObject implements - IExtendedClassifier { - - public ExtendedClassifier() { - this(LENGTH, STYPE, SNUM); - } +public class ExtendedClassifier extends Classifier implements IExtendedClassifier { /** - * @param data - the data bytes to parse + * IPv4 (for this class) and IPv6 (for extended IPv6Classifier) mask. When the address is zero, the mask is + * irrelevant else only packets with source IP address 'pkt.ip-src' + * will match if (pkt.ip-src AND classifier.ipmask-src) == classifier.ip-src. */ - public ExtendedClassifier(byte[] data) { - super(data); - } + protected final InetAddress srcMask; /** - * @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); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getDestinationIPAddress() + * IPv4 (for this class) and IPv6 (for extended IPv6Classifier) mask. When the address is zero, the mask is + * irrelevant else only packets with source IP address 'pkt.ip-dst' + * will match if (pkt.ip-dst AND classifier.ipmask-dst) == classifier.ip-dst. */ - @Override - public InetAddress getDestinationIPAddress() { - try { - return InetAddress.getByAddress(getBytes((short) 12, (short) 4)); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - return null; - } + protected final InetAddress dstMask; - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.IClassifier#setDestinationIPAddress(java.net.InetAddress) - */ - @Override - public void setDestinationIPAddress(InetAddress address) { - setBytes(address.getAddress(), (short) 12); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getDestinationPort() - */ - @Override - public short getDestinationPort() { - return getShort((short) 24); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setDestinationPort(short) + /** + * Source Port End specifies the high-end TCP/UDP source port value. See super srcPort for low-end value. */ - @Override - public void setDestinationPort(short p) { - setShort(p, (short) 24); - } + protected final short srcPortEnd; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getSourceIPAddress() - */ - @Override - public InetAddress getSourceIPAddress() { - try { - return InetAddress.getByAddress(getBytes((short) 4, (short) 4)); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - return null; - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setSourceIPAddress(java.net.InetAddress) + /** + * Destination Port End specifies the high-end TCP/UDP source port value. See super dstPort for low-end value. */ - @Override - public void setSourceIPAddress(InetAddress a) { - setBytes(a.getAddress(), (short) 4); - } + protected final short dstPortEnd; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getSourcePort() + /** + * The classifiers identifier */ - @Override - public short getSourcePort() { - return getShort((short) 20); - } + protected final short classifierId; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setSourcePort(short) + /** + * Enumeration of the activation state */ - @Override - public void setSourcePort(short p) { - setShort(p, (short) 20); - } + protected final ActivationState activationState; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getProtocol() + /** + * The action value */ - @Override - public short getProtocol() { - return getShort((short) 0); - } + protected final byte action; - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setProtocol(short) - */ - @Override - public void setProtocol(short p) { - setShort(p, (short) 0); + /** + * Constructor + * @param protocol - the protocol being sent through the gate + * @param tosOverwrite - ENABLE/DISABLE + * @param tosMask - the mask + * @param srcAddress - the source IP + * @param dstAddress - the destination IP + * @param srcPortBegin - the source begin port + * @param dstPortBegin - the destination begin port + * @param priority - the priority value + * @param srcMask - the source IP mask + * @param dstMask - the destination IP mask + * @param srcPortEnd - the source start port + * @param dstPortEnd - the destination end port + * @param classifierId - the classifier identifier + * @param activationState - denotes the activation state + * @param action - the action + */ + public ExtendedClassifier(final Protocol protocol, final byte tosOverwrite, final byte tosMask, + final Inet4Address srcAddress, final Inet4Address dstAddress, final short srcPortBegin, + final short dstPortBegin, final byte priority, final Inet4Address srcMask, + final Inet4Address dstMask, final short srcPortEnd, final short dstPortEnd, + final short classifierId, final ActivationState activationState, final byte action) { + super(IExtendedClassifier.STYPE, protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPortBegin, + dstPortBegin, priority); + if (srcMask == null) throw new IllegalArgumentException("Source IP Mask cannot be null"); + if (dstMask == null) throw new IllegalArgumentException("Destination IP Mask cannot be null"); + if (activationState == null) throw new IllegalArgumentException("Activation state must not be null"); + this.srcMask = srcMask; + this.dstMask = dstMask; + this.srcPortEnd = srcPortEnd; + this.dstPortEnd = dstPortEnd; + this.classifierId = classifierId; + this.activationState = activationState; + this.action = action; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#getPriority() - */ - @Override - public byte getPriority() { - return getByte((short) 30); + /** + * Constructor for IPv6Classifier subclass + * @param sType - the type of classifier + * @param srcAddress - the source IP + * @param dstAddress - the destination IP + * @param srcPortBegin - the source begin port + * @param dstPortBegin - the destination begin port + * @param priority - the priority value + * @param srcPortEnd - the source start port + * @param dstPortEnd - the destination end port + * @param classifierId - the classifier identifier + * @param activationState - denotes the activation state + * @param action - the action + */ + protected ExtendedClassifier(final byte sType, final InetAddress srcAddress, final InetAddress dstAddress, + final short srcPortBegin, final short dstPortBegin, final byte priority, + final short srcPortEnd, final short dstPortEnd, final short classifierId, + final ActivationState activationState, final byte action) { + super(sType, null, (byte)0, (byte)0, srcAddress, dstAddress, srcPortBegin, dstPortBegin, priority); + if (activationState == null) throw new IllegalArgumentException("Activation state must not be null"); + this.srcMask = null; + this.dstMask = null; + this.srcPortEnd = srcPortEnd; + this.dstPortEnd = dstPortEnd; + this.classifierId = classifierId; + this.activationState = activationState; + this.action = action; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IClassifier#setPriority(byte) - */ - @Override - public void setPriority(byte p) { - setByte(p, (short) 30); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getIPSourceMask() - */ @Override public InetAddress getIPSourceMask() { - try { - return InetAddress.getByAddress(getBytes((short) 8, (short) 4)); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - return null; + return srcMask; } - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.IExtendedClassifier#setIPSourceMask(java.net.InetAddress) - */ - @Override - public void setIPSourceMask(InetAddress a) { - setBytes(a.getAddress(), (short) 8); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getIPDestinationMask() - */ @Override public InetAddress getIPDestinationMask() { - try { - return InetAddress.getByAddress(getBytes((short) 16, (short) 4)); - } catch (UnknownHostException e) { - e.printStackTrace(); - } - return null; - } - - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.IExtendedClassifier#setIPDestinationMask(java.net.InetAddress - * ) - */ - @Override - public void setIPDestinationMask(InetAddress m) { - setBytes(m.getAddress(), (short) 16); + return dstMask; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getSourcePortStart() - */ @Override public short getSourcePortStart() { - return getShort((short) 20); + return super.getSourcePort(); } - @Override - public void setSourcePortStart(short p) { - setShort(p, (short) 20); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getSourcePortEnd() - */ @Override public short getSourcePortEnd() { - return getShort((short) 22); - } - - @Override - public void setSourcePortEnd(short p) { - setShort(p, (short) 22); + return srcPortEnd; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getDestinationPortStart() - */ @Override public short getDestinationPortStart() { - return getShort((short) 24); - } - - @Override - public void setDestinationPortStart(short p) { - setShort(p, (short) 24); + return super.getDestinationPort(); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getDestinationPortEnd() - */ @Override public short getDestinationPortEnd() { - return getShort((short) 26); + return dstPortEnd; } - @Override - public void setDestinationPortEnd(short p) { - setShort(p, (short) 26); - } - - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getClassifierID() - */ @Override public short getClassifierID() { - return getShort((short) 28); + return classifierId; } @Override - public void setClassifierID(short p) { - setShort(p, (short) 28); + public ActivationState getActivationState() { + return activationState; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getActivationState() - */ @Override - public byte getActivationState() { - return getByte((short) 31); + public byte getAction() { + return action; } @Override - public void setActivationState(byte s) { - setByte(s, (short) 31); - } + protected byte[] getBytes() { + final List byteList = new ArrayList<>(Bytes.asList(COPSMsgParser.shortToBytes(protocol.getValue()))); + byteList.add(tosOverwrite); + byteList.add(tosMask); + byteList.addAll(Bytes.asList(srcAddress.getAddress())); + byteList.addAll(Bytes.asList(srcMask.getAddress())); + byteList.addAll(Bytes.asList(dstAddress.getAddress())); + byteList.addAll(Bytes.asList(dstMask.getAddress())); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(srcPort))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(srcPortEnd))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(dstPort))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(dstPortEnd))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(classifierId))); + byteList.add(priority); + byteList.add(activationState.getValue()); + byteList.add(action); - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IExtendedClassifier#getAction() - */ - @Override - public byte getAction() { - return getByte((short) 32); - } + // reserved padding + byteList.addAll(Bytes.asList((byte) 0, (byte) 0, (byte) 0)); - @Override - public void setAction(byte a) { - setByte(a, (short) 32); + return Bytes.toArray(byteList); } @Override - public byte getDSCPTOS() { - return getByte((short) 2); + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof ExtendedClassifier)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final ExtendedClassifier that = (ExtendedClassifier) o; + return srcPortEnd == that.srcPortEnd && dstPortEnd == that.dstPortEnd && classifierId == that.classifierId && + activationState == that.activationState && action == that.action && + !(srcMask != null ? !srcMask.equals(that.srcMask) : that.srcMask != null) && + !(dstMask != null ? !dstMask.equals(that.dstMask) : that.dstMask != null); } @Override - public void setDSCPTOS(byte v) { - setByte(v, (short) 2); + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (srcMask != null ? srcMask.hashCode() : 0); + result = 31 * result + (dstMask != null ? dstMask.hashCode() : 0); + result = 31 * result + (int) srcPortEnd; + result = 31 * result + (int) dstPortEnd; + result = 31 * result + (int) classifierId; + result = 31 * result + (int) activationState.getValue(); + result = 31 * result + (int) action; + return result; } - @Override - public byte getDSCPTOSMask() { - return getByte((short) 3); - } + /** + * Returns a ExtendedClassifier object from a byte array + * @param data - the data to parse + * @return - the object or null if cannot be parsed + * TODO - make me more robust as exceptions can be swallowed here. + */ + public static ExtendedClassifier parse(final byte[] data) { + final List bytes = new ArrayList<>(Bytes.asList(data)); - @Override - public void setDSCPTOSMask(byte v) { - setByte(v, (short) 3); + try { + return new ExtendedClassifier(Protocol.valueOf(COPSMsgParser.bytesToShort(data[0], data[1])), + data[2], data[3], + (Inet4Address)InetAddress.getByAddress(Bytes.toArray(bytes.subList(4, 8))), + (Inet4Address)InetAddress.getByAddress(Bytes.toArray(bytes.subList(8, 12))), + COPSMsgParser.bytesToShort(data[20], data[21]), COPSMsgParser.bytesToShort(data[24], data[25]), + data[30], (Inet4Address)InetAddress.getByAddress(Bytes.toArray(bytes.subList(12, 16))), + (Inet4Address)InetAddress.getByAddress(Bytes.toArray(bytes.subList(16, 20))), + COPSMsgParser.bytesToShort(data[22], data[23]), COPSMsgParser.bytesToShort(data[26], data[27]), + COPSMsgParser.bytesToShort(data[28], data[29]), ActivationState.valueOf(data[31]), data[32]); + } catch (UnknownHostException e) { + return null; + } } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java index 26153a6..f45df91 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateID.java @@ -1,57 +1,71 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.IGateID; +import org.umu.cops.stack.COPSMsgParser; /** - * + * Implementation of the IGateID interface */ public class GateID extends PCMMBaseObject implements IGateID { /** - * + * The gate ID value */ - public GateID() { - this(LENGTH, STYPE, SNUM); - } + final int gateId; /** - * @param data + * Constructor + * @param gateId - the ID value */ - public GateID(byte[] data) { - super(data); + public GateID(final int gateId) { + super(SNum.GATE_ID, STYPE); + this.gateId = gateId; } - /** - * @param len - * @param sType - * @param sNum - */ - public GateID(short len, byte sType, byte sNum) { - super(len, sType, sNum); + @Override + public int getGateID() { + return gateId; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IGateID#setGateID(int) - */ @Override - public void setGateID(int gateID) { - setInt(gateID, (short) 0); + protected byte[] getBytes() { + return COPSMsgParser.intToBytes(gateId); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IGateID#getGateID() - */ @Override - public int getGateID() { - return getInt((short) 0); + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof GateID)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final GateID gateID = (GateID) o; + return gateId == gateID.gateId; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + gateId; + return result; } + /** + * Returns a GateID object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static GateID parse(final byte[] data) { + return new GateID(COPSMsgParser.bytesToInt(data[0], data[1], data[2], data[3])); + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java index c802d32..5be3c9f 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/GateSpec.java @@ -1,118 +1,212 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.IGateSpec; import org.pcmm.gates.ISessionClassID; +import org.umu.cops.stack.COPSMsgParser; /** - * + * Implementation of the IGateSpec interface */ 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); - } - - public GateSpec(byte[] data) { - super(data); + /** + * The gate's direction + */ + private final Direction direction; + + /** + * The DSCP/TOS Overwrite is a 1-byte bit field [8] defined by the following alternative structures, depending upon + network management strategy. + * + * When enabled, the CMTS must mark the packets traversing the CMTS DSCP/TOS value + */ + private final byte tosOverwrite; + + /** + * tosOverwrite field with the TOS mask is used to identify particular bits within the IPv4 DSCP/TOS byte + */ + private final byte tosMask; + + /** + * Session Class ID identifies the proper admission control policy or parameters to be applied for this gate + */ + private final SessionClassID sessionClassID; + + /** + * Timer value in seconds. Value of 0 indicates that the CMTS provisioned value for the timer MUST be used. + */ + private final short timer1; + + /** + * DOCSIS Admitted timer in seconds + */ + private final short timer2; + + /** + * DOCSIS Active timer in seconds + */ + private final short timer3; + + /** + * The fourth timer value in seconds + */ + private final short timer4; + + /** + * General constructor + * @param direction - the gate direction + * @param tosOverwrite - ENABLE/DISABLE + * @param tosMask - the mask + */ + public GateSpec(final Direction direction, final byte tosOverwrite, final byte tosMask) { + this(direction, tosOverwrite, tosMask, new SessionClassID((byte) 0), (short) 0, (short) 0, (short) 0, (short) 0); + } + + /** + * Constructor generally for use when parsing a byte array to create an instance of this object. + * @param direction - the gate direction + * @param tosOverwrite - ENABLE/DISABLE + * @param tosMask - the mask + * @param sessionClassID - the session class ID + * @param timer1 - timer1 in seconds + * @param timer2 - timer2 in seconds + * @param timer3 - timer3 in seconds + * @param timer4 - timer4 in seconds + */ + protected GateSpec(final Direction direction, final byte tosOverwrite, final byte tosMask, + final SessionClassID sessionClassID, final short timer1, final short timer2, final short timer3, + final short timer4) { + + super(SNum.GATE_SPEC, STYPE); + + if (direction == null) throw new IllegalArgumentException("Direction is required"); +// if (tosOverwrite == null) throw new IllegalArgumentException("TOS Overwrite is required"); + if (sessionClassID == null) throw new IllegalArgumentException("Session class ID is required"); + + this.direction = direction; + this.tosOverwrite = tosOverwrite; + this.tosMask = tosMask; + this.sessionClassID = sessionClassID; + this.timer1 = timer1; + this.timer2 = timer2; + this.timer3 = timer3; + this.timer4 = timer4; } @Override - public ISessionClassID getSessionClassID() { - return new SessionClassID(getByte((short) 3)); + public Direction getDirection() { + return direction; } @Override - public void setSessionClassID(ISessionClassID id) { - setByte(id.toSingleByte(), (short) 3); + public byte getDSCP_TOSOverwrite() { + return tosOverwrite; } @Override - public Direction getDirection() { - return Direction.valueOf(getByte((short) 0)); + public byte getDSCP_TOSMask() { + return tosMask; } @Override - public void setDirection(Direction direction) { - // OR in the Direction flag with the DSCPTOS enable flag - flags |= direction.getValue(); - setByte(flags, (short) 0); + public ISessionClassID getSessionClassID() { + return sessionClassID; } @Override public short getTimerT1() { - return getShort((short) 4); - } - - @Override - public void setTimerT1(short authTimer) { - setShort(authTimer, (short) 4); + return timer1; } @Override public short getTimerT2() { - return getShort((short) 6); - } - - @Override - public void setTimerT2(short timer) { - setShort(timer, (short) 6); - + return timer2; } @Override public short getTimerT3() { - return getShort((short) 8); - } - - @Override - public void setTimerT3(short t) { - setShort(t, (short) 8); - + return timer3; } @Override public short getTimerT4() { - return getShort((short) 10); + return timer4; } @Override - public void setTimerT4(short t) { - setShort(t, (short) 10); - } + protected byte[] getBytes() { + final byte[] data = new byte[12]; + data[0] = direction.getValue(); + data[1] = tosOverwrite; + data[2] = tosMask; + data[3] = sessionClassID.toSingleByte(); - @Override - public void setDSCP_TOSOverwrite(DSCPTOS dscpTos) { - // OR in the DSCPTOS enable flag with the Direction flag - setDSCP_TOSOverwrite(dscpTos.getValue()); - } + final byte[] timer1Bytes = COPSMsgParser.shortToBytes(timer1); + data[4] = timer1Bytes[0]; + data[5] = timer1Bytes[1]; - @Override - public void setDSCP_TOSOverwrite(byte dscpTos) { - flags |= dscpTos; - setByte(flags, (short) 1); - } + final byte[] timer2Bytes = COPSMsgParser.shortToBytes(timer2); + data[6] = timer2Bytes[0]; + data[7] = timer2Bytes[1]; + final byte[] timer3Bytes = COPSMsgParser.shortToBytes(timer3); + data[8] = timer3Bytes[0]; + data[9] = timer3Bytes[1]; - @Override - public DSCPTOS getDSCP_TOSOverwrite() { - return DSCPTOS.valueOf(getByte((short) 1)); + final byte[] timer4Bytes = COPSMsgParser.shortToBytes(timer4); + data[10] = timer4Bytes[0]; + data[11] = timer4Bytes[1]; + + return data; } @Override - public byte getDSCP_TOSMask() { - return getByte((short) 2); + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof GateSpec)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final GateSpec gateSpec = (GateSpec) o; + return tosMask == gateSpec.tosMask && timer1 == gateSpec.timer1 && timer2 == gateSpec.timer2 && + timer3 == gateSpec.timer3 && timer4 == gateSpec.timer4 && direction == gateSpec.direction && + tosOverwrite == gateSpec.tosOverwrite && sessionClassID.equals(gateSpec.sessionClassID); + } @Override - public void setDSCP_TOSMask(byte dscp_tos_mask) { - setByte(dscp_tos_mask, (short) 2); + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + direction.hashCode(); + result = 31 * result + (int) tosOverwrite; + result = 31 * result + (int) tosMask; + result = 31 * result + sessionClassID.hashCode(); + result = 31 * result + (int) timer1; + result = 31 * result + (int) timer2; + result = 31 * result + (int) timer3; + result = 31 * result + (int) timer4; + return result; } + /** + * Returns a GateSpec object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static GateSpec parse(final byte[] data) { + return new GateSpec(Direction.valueOf(data[0]), data[1], data[2], + new SessionClassID(data[3]), COPSMsgParser.bytesToShort(data[4], data[5]), + COPSMsgParser.bytesToShort(data[6], data[7]), COPSMsgParser.bytesToShort(data[8], data[9]), + COPSMsgParser.bytesToShort(data[10], data[11])); + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java index 1280865..f47cd60 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/IPv6Classifier.java @@ -9,339 +9,245 @@ */ package org.pcmm.gates.impl; -import org.pcmm.base.impl.PCMMBaseObject; +import com.google.common.primitives.Bytes; import org.pcmm.gates.IIPv6Classifier; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.umu.cops.stack.COPSMsgParser; +import java.net.Inet6Address; import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; /** - * + * Implementation of the IIPv6Classifier interface */ -public class IPv6Classifier extends PCMMBaseObject implements - IIPv6Classifier { +public class IPv6Classifier extends ExtendedClassifier implements IIPv6Classifier { - private Logger logger = LoggerFactory.getLogger(IPv6Classifier.class); + /** + * VALID when there is valid data for comparison with the IPv6 Flow label else IRRELEVANT + */ + private final FlowLabel flowEnabled; - public IPv6Classifier() { - this(LENGTH, STYPE, SNUM); - } + /** + * Allows for matching on the IPv6 Traffic Class value (with tcHigh & tcMask) + */ + private final byte tcLow; /** - * @param data - the data bytes to parse + * Allows for matching on the IPv6 Traffic Class value (with tcLow & tcMask) */ - public IPv6Classifier(byte[] data) { - super(data); - } + private final byte tcHigh; /** - * @param len - the classifier's length - * @param sType - the sType value - * @param sNum - the sNum value + * Allows for matching on the IPv6 Traffic Class value (with tcLow & tcHigh) */ - public IPv6Classifier(short len, byte sType, byte sNum) { - super(len, sType, sNum); - } + private final byte tcMask; - // 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 + /** + * Contains data for comparison When flowEnabled == VALID else this value must be 0 + */ + private final int flowLabel; - // 00:01 Flags: 0000.0001 Flow Label enable match - @Override - public void setFlowLabelEnableFlag(byte flag) { - setByte(flag, (short) 0); + /** + * Next Header Type field specifies the desired next header type value for any header or extension header associated + * with the packet. Typically this value will specify the next layer protocol type. There are two special IPv6 next + * header type field values: "256" matches traffic with any IPv6 next header type value, and "257" matches both TCP + * and UDP traffic. Values greater than 257 are invalid for comparisons (i.e., no traffic can match this entry). + * For further discussion of the IPv6 Next Header Type field, refer to C.2.1.10.3 + */ + private final short nextHdr; + + /** + * Source Prefix Length field specifies the fixed, most significant bits of an IPv6 address that are used to + * determine address range and subnet ID for the IPv6 Source Address. + */ + private final byte srcPrefixLen; + + /** + * Destination Prefix Length field specifies the fixed, most significant bits of an IPv6 address that are used to + * determine address range and subnet ID for the IPv6 Destination Address. + */ + private final byte dstPrefixLen; + + /** + * Constructor + * @param srcAddress - the source IP (not null) + * @param dstAddress - the destination IP (not null) + * @param srcPortBegin - the source begin port + * @param dstPortBegin - the destination begin port + * @param priority - the priority value + * @param srcPortEnd - the source start port + * @param dstPortEnd - the destination end port + * @param classifierId - the classifier identifier + * @param activationState - denotes the activation state (not null) + * @param action - the action + * @param flowEnabled - eumeration of FlowLabel (VALID|IRRELEVANT) + * @param tcLow - low matching on the IPv6 Traffic Class + * @param tcHigh - high matching on the IPv6 Traffic Class + * @param tcMask - mask matching on the IPv6 Traffic Class + * @param flowLabel - data for comparison + * @param nextHdr - the next header type value + * @param srcPrefixLen - source prefix length + * @param dstPrefixLen - destination prefix length + */ + public IPv6Classifier(final Inet6Address srcAddress, final Inet6Address dstAddress, final short srcPortBegin, + final short dstPortBegin, final byte priority, final short srcPortEnd, final short dstPortEnd, + final short classifierId, final ActivationState activationState, final byte action, + final FlowLabel flowEnabled, final byte tcLow, final byte tcHigh, final byte tcMask, + final int flowLabel, final short nextHdr, final byte srcPrefixLen, final byte dstPrefixLen) { + super(IIPv6Classifier.STYPE, srcAddress, dstAddress, srcPortBegin, dstPortBegin, priority, srcPortEnd, + dstPortEnd, classifierId, activationState, action); + if (flowEnabled == null) throw new IllegalArgumentException("Flow enabled enumeration must not be null"); + if (flowEnabled.equals(FlowLabel.IRRELEVANT)) this.flowLabel = 0; + else this.flowLabel = flowLabel; + this.flowEnabled = flowEnabled; + this.tcLow = tcLow; + this.tcHigh = tcHigh; + this.tcMask = tcMask; + this.nextHdr = nextHdr; + this.srcPrefixLen = srcPrefixLen; + this.dstPrefixLen = dstPrefixLen; } + + // 00:01 Flags: 0000.0001 Flow Label enable match @Override - public byte getFlowLabelEnableFlag() { - return getByte((short) 0); + public FlowLabel getFlowLabelEnableFlag() { + return flowEnabled; } // 01:01 Tc-low @Override - public void setTcLow(byte tcLow) { - setByte(tcLow, (short) 1); - } - @Override public byte getTcLow() { - return getByte((short) 1); + return tcLow; } // 02:01 Tc-high @Override - public void setTcHigh(byte tcHigh) { - setByte(tcHigh, (short) 2); - } - @Override public byte getTcHigh() { - return getByte((short) 2); + return tcHigh; } // 03:01 Tc-mask @Override - public void setTcMask(byte tcMask) { - setByte(tcMask, (short) 3); - } - @Override public byte getTcMask() { - return getByte((short) 3); + return tcMask; } // 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); + return flowLabel; } // 08:02 Next Header Type @Override - public void setNextHdr(short nxtHdr) { - setShort(nxtHdr, (short) 8); - } - @Override public short getNextHdr() { - return getShort((short) 8); + return nextHdr; } // 10:01 Source Prefix Length @Override - public void setSourcePrefixLen(byte srcPrefixLen) { - setByte(srcPrefixLen, (short) 10); - } - @Override public byte getSourcePrefixLen() { - return getByte((short) 10); + return srcPrefixLen; } // 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 dstPrefixLen; + } + + @Override + protected byte[] getBytes() { + final List byteList = new ArrayList<>(); + byteList.add(flowEnabled.getValue()); + byteList.add(tcLow); + byteList.add(tcHigh); + byteList.add(tcMask); + byteList.addAll(Bytes.asList(COPSMsgParser.intToBytes(flowLabel))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(nextHdr))); + byteList.add(srcPrefixLen); + byteList.add(dstPrefixLen); + byteList.addAll(Bytes.asList(srcAddress.getAddress())); + byteList.addAll(Bytes.asList(dstAddress.getAddress())); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(srcPort))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(srcPortEnd))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(dstPort))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(dstPortEnd))); + byteList.addAll(Bytes.asList(COPSMsgParser.shortToBytes(classifierId))); + byteList.add(priority); + byteList.add(activationState.getValue()); + byteList.add(action); + return Bytes.toArray(byteList); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; } - 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()); + if (!(o instanceof IPv6Classifier)) { + return false; } - 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 - + if (!super.equals(o)) { + return false; + } + final IPv6Classifier that = (IPv6Classifier) o; + return flowEnabled == that.flowEnabled && tcLow == that.tcLow && tcHigh == that.tcHigh && + tcMask == that.tcMask && flowLabel == that.flowLabel && nextHdr == that.nextHdr && + srcPrefixLen == that.srcPrefixLen && dstPrefixLen == that.dstPrefixLen; } @Override - public byte getDSCPTOSMask() { - // TODO Auto-generated method stub - return 0; + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + (int) flowEnabled.getValue(); + result = 31 * result + (int) tcLow; + result = 31 * result + (int) tcHigh; + result = 31 * result + (int) tcMask; + result = 31 * result + flowLabel; + result = 31 * result + (int) nextHdr; + result = 31 * result + (int) srcPrefixLen; + result = 31 * result + (int) dstPrefixLen; + return result; } - @Override - public void setDSCPTOSMask(byte v) { - // TODO Auto-generated method stub + /** + * Returns a ExtendedClassifier object from a byte array + * @param data - the data to parse + * @return - the object or null if cannot be parsed + * TODO - make me more robust as exceptions can be swallowed here. + */ + public static IPv6Classifier parse(final byte[] data) { + final List bytes = new ArrayList<>(Bytes.asList(data)); + try { + final Inet6Address srcAddress = (Inet6Address)InetAddress.getByAddress(Bytes.toArray(bytes.subList(12, 28))); + final Inet6Address dstAddress = (Inet6Address)InetAddress.getByAddress(Bytes.toArray(bytes.subList(28, 44))); + final short srcPortBegin = COPSMsgParser.bytesToShort(data[44], data[45]); + final short srcPortEnd = COPSMsgParser.bytesToShort(data[46], data[47]); + final short dstPortBegin = COPSMsgParser.bytesToShort(data[48], data[49]); + final short dstPortEnd = COPSMsgParser.bytesToShort(data[50], data[51]); + final short classifierId = COPSMsgParser.bytesToShort(data[52], data[53]); + final byte priority = data[54]; + final ActivationState activationState = ActivationState.valueOf(data[55]); + final byte action = data[56]; + final FlowLabel flowEnabled = FlowLabel.valueOf(data[0]); + final byte tcLow = data[1]; + final byte tcHigh = data[2]; + final byte tcMask = data[3]; + final int flowLabel = COPSMsgParser.bytesToInt(data[4], data[5], data[6], data[7]); + final short nextHdr = COPSMsgParser.bytesToShort(data[8], data[9]); + final byte srcPrefixLen = data[10]; + final byte dstPrefixLen = data[11]; + + return new IPv6Classifier(srcAddress, dstAddress, srcPortBegin, dstPortBegin, priority, srcPortEnd, + dstPortEnd, classifierId, activationState, action, flowEnabled, tcLow, tcHigh, tcMask, flowLabel, + nextHdr, srcPrefixLen, dstPrefixLen); + } catch (UnknownHostException e) { + return null; + } } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java index da686ef..2e203ed 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMError.java @@ -1,98 +1,119 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.IPCMMError; +import org.umu.cops.stack.COPSMsgParser; /** - * + * Implementation of the IPCMMError interface */ public class PCMMError extends PCMMBaseObject implements IPCMMError { + /** - * + * The error code (cannot be NA) */ - public PCMMError() { - this(LENGTH, STYPE, SNUM); - } + private final ErrorCode errorCode; - public PCMMError(short errorCode, short subErrCode) { - this(); - setErrorCode(errorCode); - setErrorSubcode(subErrCode); - } + /** + * The error sub-code (defaults to NA) + */ + private final ErrorCode subErrCode; /** - * @param data + * Constructor without a sub-code which will then be set to NA + * @param errorCode - the error code (required and not NA) */ - public PCMMError(byte[] data) { - super(data); + public PCMMError(final ErrorCode errorCode) { + this(errorCode, null); } /** - * @param len - * @param sType - * @param sNum + * Constructor with a sub-code + * @param errorCode - the error code (required and not NA) + * @param subErrCode - the sub-code (defaults to NA when null) */ - public PCMMError(short len, byte sType, byte sNum) { - super(len, sType, sNum); + public PCMMError(final ErrorCode errorCode, final ErrorCode subErrCode) { + super(SNum.PCMM_ERROR, STYPE); + if (errorCode == null || errorCode.equals(ErrorCode.NA)) + throw new IllegalArgumentException("ErrorCode is required and must not be NA"); + this.errorCode = errorCode; + if (subErrCode == null) this.subErrCode = ErrorCode.NA; + else this.subErrCode = subErrCode; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCError#setErrorCode(int) - */ @Override - public void setErrorCode(short errorCode) { - setShort(errorCode, (short) 0); + public ErrorCode getErrorCode() { + return errorCode; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCError#getErrorCode() - */ @Override - public short getErrorCode() { - return getShort((short) 0); + public ErrorCode getErrorSubcode() { + return subErrCode; } /* * (non-Javadoc) * - * @see org.pcmm.gates.IPCError#setErrorSubcode(int) + * @see org.pcmm.gates.IPCError#getDescription() */ @Override - public void setErrorSubcode(short errorSubcode) { - setShort(errorSubcode, (short) 2); + public String getDescription() { + String hex = Integer.toHexString(subErrCode.getCode() & 0xFFFF); + return "Error Code: " + errorCode.getCode() + " Error Subcode : " + hex + " " + errorCode.getDescription(); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCError#getErrorCode() - */ @Override - public short getErrorSubcode() { - return getShort((short) 2); + public String toString() { + return getDescription(); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCError#getDescription() - */ @Override - public String getDescription() { - String hex = Integer.toHexString(getErrorSubcode() & 0xFFFF); - return "Error Code: " + getErrorCode() + " Error Subcode : " + hex - + " " + Description.valueOf(getErrorCode()); + protected byte[] getBytes() { + final byte[] errorCodeBytes = COPSMsgParser.shortToBytes(errorCode.getCode()); + final byte[] subErrCodeBytes = COPSMsgParser.shortToBytes(subErrCode.getCode()); + final byte[] data = new byte[errorCodeBytes.length + subErrCodeBytes.length]; + System.arraycopy(errorCodeBytes, 0, data, 0, errorCodeBytes.length); + System.arraycopy(subErrCodeBytes, 0, data, errorCodeBytes.length, subErrCodeBytes.length); + return data; } @Override - public String toString() { - return getDescription(); + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof PCMMError)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final PCMMError pcmmError = (PCMMError) o; + return errorCode == pcmmError.errorCode && subErrCode == pcmmError.subErrCode; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + errorCode.hashCode(); + result = 31 * result + subErrCode.hashCode(); + return result; + } + + /** + * Returns a PCMMError object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static PCMMError parse(final byte[] data) { + return new PCMMError(ErrorCode.valueOf(COPSMsgParser.bytesToShort(data[0], data[1])), + ErrorCode.valueOf((COPSMsgParser.bytesToShort(data[2], data[3])))); + } + } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java index 57121b0..1e2eaff 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/PCMMGateReq.java @@ -1,14 +1,18 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; -import org.pcmm.base.IPCMMBaseObject; +import com.google.common.primitives.Bytes; +import org.pcmm.base.impl.PCMMBaseObject.SNum; import org.pcmm.gates.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** *

@@ -20,205 +24,186 @@ public class PCMMGateReq implements IPCMMGate { public final static Logger logger = LoggerFactory.getLogger(PCMMGateReq.class); - private boolean multicast; + // Immutable references + private final boolean multicast; + private final IAMID iamid; + private final ISubscriberID subscriberID; + private transient ITransactionID transactionID; + private transient IGateSpec gateSpec; + private transient ITrafficProfile trafficProfile; + private transient IClassifier classifier; + + // These values are transient as objects of these type will be updated asynchronously and will be used for + // synchronization purposes private IGateID gateID; - private IAMID iamid; private IPCMMError error; - private ISubscriberID subscriberID; - private ITransactionID transactionID; - private IGateSpec gateSpec; - private ITrafficProfile trafficProfile; - private IClassifier classifier; - public PCMMGateReq() { + /** + * Constructor + * @param iamid - the Application Manager ID + * @param subscriberID - the Subscriber ID + * @param transactionID - the transaction ID + * @param gateSpec - the Gate specification + * @param trafficProfile - the traffic profile + * @param classifier - the classifier + * @param gateID - the gate ID + * @param error - the error + */ + public PCMMGateReq(IAMID iamid, ISubscriberID subscriberID, ITransactionID transactionID, + IGateSpec gateSpec, ITrafficProfile trafficProfile, IClassifier classifier, IGateID gateID, + IPCMMError error) { + // TODO - determine if and when this attribute should be used + this.multicast = false; + + this.iamid = iamid; + this.subscriberID = subscriberID; + this.transactionID = transactionID; + this.gateSpec = gateSpec; + this.trafficProfile = trafficProfile; + this.classifier = classifier; + this.gateID = gateID; + this.error = error; } - public PCMMGateReq(byte[] data) { - short len, offset; - byte sNum, sType; - len = offset = 0; - sNum = sType = (byte) 0; + /** + * Creates a PCMM Gate Request object from parsing a byte array + * @param data - the data to parse + * @return - the request + */ + public static PCMMGateReq parse(byte[] data) { + GateID gateID = null; + AMID amid = null; + SubscriberID subscriberID = null; + TransactionID transactionID = null; + GateSpec gateSpec = null; + ITrafficProfile trafficProfile = null; + Classifier classifier = null; + PCMMError error = null; + + short offset = 0; while (offset + 5 < data.length) { - len = 0; + short len = 0; len |= ((short) data[offset]) << 8; len |= ((short) data[offset + 1]) & 0xFF; - sNum = data[offset + 2]; - sType = data[offset + 3]; - byte[] dataBuffer = Arrays.copyOfRange(data, offset, offset + len); + final SNum sNum = SNum.valueOf(data[offset + 2]); + final byte sType = data[offset + 3]; + final int dataIndx = offset + 4; + byte[] dataBuffer = Arrays.copyOfRange(data, dataIndx, dataIndx + len - 4); switch (sNum) { - case IGateID.SNUM: - setGateID(new GateID(dataBuffer)); - break; - case IAMID.SNUM: - setAMID(new AMID(dataBuffer)); - break; - case ISubscriberID.SNUM: - setSubscriberID(new SubscriberID(dataBuffer)); - break; - case ITransactionID.SNUM: - setTransactionID(new TransactionID(dataBuffer)); - break; - case IGateSpec.SNUM: - setGateSpec(new GateSpec(dataBuffer)); - break; - case ITrafficProfile.SNUM: - // TODO - Will need to support other traffic profiles - setTrafficProfile(new DOCSISServiceClassNameTrafficProfile(dataBuffer)); - break; - case IClassifier.SNUM: - setClassifier(new Classifier(dataBuffer)); - break; - case IPCMMError.SNUM: - error = new PCMMError(dataBuffer); - break; + case GATE_ID: + gateID = GateID.parse(dataBuffer); + break; + case AMID: + amid = AMID.parse(dataBuffer); + break; + case SUBSCRIBER_ID: + subscriberID = SubscriberID.parse(dataBuffer); + break; + case TRANSACTION_ID: + transactionID = TransactionID.parse(dataBuffer); + break; + case GATE_SPEC: + gateSpec = GateSpec.parse(dataBuffer); + break; + case TRAFFIC_PROFILE: + switch (sType) { + case DOCSISServiceClassNameTrafficProfile.STYPE: + trafficProfile = DOCSISServiceClassNameTrafficProfile.parse(dataBuffer); + break; + case BestEffortService.STYPE: + trafficProfile = BestEffortService.parse(dataBuffer); + break; + } + break; + case CLASSIFIERS: + switch (sType) { + case IClassifier.STYPE: + classifier = Classifier.parse(dataBuffer); + break; + case IExtendedClassifier.STYPE: + classifier = ExtendedClassifier.parse(dataBuffer); + break; + case IIPv6Classifier.STYPE: + classifier = IPv6Classifier.parse(dataBuffer); + break; + } + break; + case PCMM_ERROR: + error = PCMMError.parse(dataBuffer); + break; default: logger.warn("Unhandled Object skept : S-NUM=" + sNum + " S-TYPE=" + sType + " LEN=" + len); } offset += len; } + + return new PCMMGateReq(amid, subscriberID, transactionID, gateSpec, trafficProfile, classifier, gateID, error); } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#isMulticast() - */ @Override public boolean isMulticast() { // TODO Auto-generated method stub return multicast; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#setGateID(short) - */ @Override public void setGateID(IGateID gateid) { this.gateID = gateid; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#setAMID(org.pcmm.gates.IAMID) - */ @Override - public void setAMID(IAMID iamid) { - this.iamid = iamid; - } + public void setTransactionID(ITransactionID transactionID) { + this.transactionID = transactionID; - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.IPCMMGate#getSubscriberID(org.pcmm.gates.ISubscriberID) - */ - @Override - public void setSubscriberID(ISubscriberID subscriberID) { - this.subscriberID = subscriberID; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getGateSpec(org.pcmm.gates.IGateSpec) - */ @Override public void setGateSpec(IGateSpec gateSpec) { this.gateSpec = gateSpec; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getClassifier(org.pcmm.gates.IClassifier) - */ @Override public void setClassifier(IClassifier classifier) { this.classifier = classifier; } - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.IPCMMGate#getTrafficProfile(org.pcmm.gates.ITrafficProfile - * ) - */ @Override public void setTrafficProfile(ITrafficProfile profile) { this.trafficProfile = profile; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getGateID() - */ @Override public IGateID getGateID() { return gateID; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getAMID() - */ @Override public IAMID getAMID() { return iamid; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getSubscriberID() - */ @Override public ISubscriberID getSubscriberID() { return subscriberID; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getGateSpec() - */ @Override public IGateSpec getGateSpec() { return gateSpec; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getClassifier() - */ @Override public IClassifier getClassifier() { return classifier; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.IPCMMGate#getTrafficProfile() - */ @Override public ITrafficProfile getTrafficProfile() { return trafficProfile; } - @Override - public void setTransactionID(ITransactionID transactionID) { - this.transactionID = transactionID; - } - @Override public ITransactionID getTransactionID() { return transactionID; @@ -234,32 +219,32 @@ public class PCMMGateReq implements IPCMMGate { @Override public byte[] getData() { - byte[] array = new byte[0]; + final List byteList = new ArrayList<>(); if (getTransactionID() != null) { - array = fill(array, getTransactionID()); + byteList.addAll(Bytes.asList(getTransactionID().getAsBinaryArray())); } if (getGateID() != null) { - array = fill(array, getGateID()); + byteList.addAll(Bytes.asList(getGateID().getAsBinaryArray())); } if (getAMID() != null) { - array = fill(array, getAMID()); - + byteList.addAll(Bytes.asList(getAMID().getAsBinaryArray())); } if (getSubscriberID() != null) { - array = fill(array, getSubscriberID()); + byteList.addAll(Bytes.asList(getSubscriberID().getAsBinaryArray())); } if (getGateSpec() != null) { - array = fill(array, getGateSpec()); + byteList.addAll(Bytes.asList(getGateSpec().getAsBinaryArray())); } if (getTrafficProfile() != null) { - array = fill(array, getTrafficProfile()); + byteList.addAll(Bytes.asList(getTrafficProfile().getAsBinaryArray())); } if (getClassifier() != null) { - array = fill(array, getClassifier()); + byteList.addAll(Bytes.asList(getClassifier().getAsBinaryArray())); } - return array; + return Bytes.toArray(byteList); } +/* private byte[] fill(byte[] array, IPCMMBaseObject obj) { byte[] a = obj.getAsBinaryArray(); int offset = array.length; @@ -267,4 +252,5 @@ public class PCMMGateReq implements IPCMMGate { System.arraycopy(a, 0, array, offset, a.length); return array; } +*/ } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java index 7b3ff20..8c5ec22 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/SessionClassID.java @@ -1,85 +1,96 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.gates.ISessionClassID; /** - * + * SessionClassID is a 1-byte unsigned integer value which identifies the proper admission control policy or + * parameters to be applied for this Gate. The SessionClassID is a bit field, defined as follows: + * Bit 0-2: Priority, a number from 0 to 7, where 0 is low priority and 7 is high. + * Bit 3: Preemption, set to enable preemption of bandwidth allocated to lower priority sessions if necessary + * (if supported). + * Bit 4-7: Configurable, default to 0 */ public class SessionClassID implements ISessionClassID { - private byte priority; - private byte preemption; + /** + * The priority field describes the relative importance of the session as compared to other sessions generated by + * the same PDP. The PEP MAY use this value to both implement priority based admission (in conjunction with the + * Preemption bit), and to defend the resulting flow from being preempted. + */ + private transient byte priority; - // TODO check this; - private byte session; + /** + * The preemption bit is used to by a PDP to direct the PEP to apply a priority-based admission control. Preemption + * support is optional; a PEP MAY ignore this bit. If preemption is not requested by the PDP or not implement by the + * PEP, then admission control policy will be on a first-come, first-served basis. + */ + private transient byte preemption; - public SessionClassID() { - this((byte) 0); - } + /** + * The session ID value + */ + private byte session; + /** + * Constructor 1 + * @param value - the session value + */ public SessionClassID(byte value) { - session = value; - priority = 0; - preemption = 0; + this.session = value; + this.priority = 0; + this.preemption = 0; priority |= value >> 2; preemption |= value >> 3; - } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ISessionClassID#getPriority() + /** + * Constructor 2 + * @param value - the session value + * @param priority - overrides the default priority value of 2 + * @param preemption - overrides the default preemption value of 3 */ + public SessionClassID(byte value, final byte priority, final byte preemption) { + this.session = value; + this.priority = priority; + this.preemption = preemption; + } + @Override public byte getPriority() { return priority; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ISessionClassID#setPriority(byte) - */ @Override - public void setPriority(byte value) { - this.priority = value; + public byte getPreemption() { + return preemption; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ISessionClassID#getPreemption() - */ @Override - public byte getPreemption() { - return preemption; + public byte toSingleByte() { + return session; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ISessionClassID#setPreemption(byte) - */ @Override - public void setPreemption(byte value) { - this.preemption = value; + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SessionClassID)) { + return false; + } + final SessionClassID that = (SessionClassID) o; + return priority == that.priority && preemption == that.preemption && session == that.session; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ISessionClassID#toSingleByte() - */ @Override - public byte toSingleByte() { - // byte ret = 0; - // ret |= (priority << 2); - // ret |= (preemption & 0xf); - // return ret; - return session; + public int hashCode() { + int result = (int) priority; + result = 31 * result + (int) preemption; + result = 31 * result + (int) session; + return result; } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java index e933bb2..e98b5dc 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/SubscriberID.java @@ -1,66 +1,78 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ -package org.pcmm.gates.impl; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.UnknownHostException; +package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.ISubscriberID; +import java.net.InetAddress; +import java.net.UnknownHostException; + /** - * + * Implementation of the ISubscriberID interface */ public class SubscriberID extends PCMMBaseObject implements ISubscriberID { /** - * + * The source IPv4 or IPv6 address */ - public SubscriberID() { - this(LENGTH, STYPE, SNUM); - } + private final InetAddress srcIp; /** - * @param data + * Constructor + * @param srcIp - the source host address */ - public SubscriberID(byte[] data) { - super(data); + public SubscriberID(final InetAddress srcIp) { + super(SNum.SUBSCRIBER_ID, STYPE); + if (srcIp == null) throw new IllegalArgumentException("srcIp must not be null"); + this.srcIp = srcIp; } - /** - * @param len - * @param sType - * @param sNum - */ - public SubscriberID(short len, byte sType, byte sNum) { - super(len, sType, sNum); + @Override + public InetAddress getSourceIPAddress() { + return srcIp; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ISubscriberID#getSourceIPAddress() - */ @Override - public InetAddress getSourceIPAddress() { - try { - return Inet4Address.getByAddress(getBytes((short) 0, (short) 4)); - } catch (UnknownHostException e) { - return null; + protected byte[] getBytes() { + return srcIp.getAddress(); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SubscriberID)) { + return false; } + if (!super.equals(o)) { + return false; + } + final SubscriberID that = (SubscriberID) o; + return srcIp.equals(that.srcIp); } - /* - * (non-Javadoc) - * - * @see - * org.pcmm.gates.ISubscriberID#setSourceIPAddress(java.net.InetAddress) - */ @Override - public void setSourceIPAddress(InetAddress address) { - setBytes(address.getAddress(), (short) 0); + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + srcIp.hashCode(); + return result; } + /** + * Returns a SubscriberID object from a byte array + * @param data - the data to parse + * @return - the object or null if cannot be parsed + * TODO - make me more robust as RuntimeExceptions can be thrown here. + */ + public static SubscriberID parse(final byte[] data) { + try { + return new SubscriberID(InetAddress.getByAddress(data)); + } catch (UnknownHostException e) { + return null; + } + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java b/packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java index 16ae63d..29b2b64 100644 --- a/packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java +++ b/packetcable-driver/src/main/java/org/pcmm/gates/impl/TransactionID.java @@ -1,77 +1,70 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.gates.impl; import org.pcmm.base.impl.PCMMBaseObject; import org.pcmm.gates.ITransactionID; +import org.umu.cops.stack.COPSMsgParser; /** - * + * Implementation of the ITransactionID interface */ public class TransactionID extends PCMMBaseObject implements ITransactionID { /** - * + * The transaction identifier */ - public TransactionID() { - this(LENGTH, STYPE, SNUM); - } + private final short transId; /** - * @param data + * The gate command type */ - public TransactionID(byte[] data) { - super(data); - } + private final GateCommandType gateCommandType; /** - * @param len - * @param sType - * @param sNum + * Constructor + * @param transId - the transaction identifier + * @param gateCommandType - the gate command type */ - public TransactionID(short len, byte sType, byte sNum) { - super(len, sType, sNum); + public TransactionID(final short transId, final GateCommandType gateCommandType) { + super(SNum.TRANSACTION_ID, STYPE); + if (gateCommandType == null) + throw new IllegalArgumentException("Invalid gate command type"); + this.transId = transId; + this.gateCommandType = gateCommandType; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ITransactionID#setTransactionIdentifier(short) - */ @Override - public void setTransactionIdentifier(short id) { - setShort(id, (short) 0); + public short getTransactionIdentifier() { + return transId; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ITransactionID#getTransactionIdentifier() - */ @Override - public short getTransactionIdentifier() { - return getShort((short) 0); + public GateCommandType getGateCommandType() { + return gateCommandType; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ITransactionID#setGateCommandType(short) - */ @Override - public void setGateCommandType(short type) { - setShort(type, (short) 2); + protected byte[] getBytes() { + final byte[] transIdBytes = COPSMsgParser.shortToBytes(transId); + final byte[] data = new byte[transIdBytes.length + transIdBytes.length]; + System.arraycopy(transIdBytes, 0, data, 0, transIdBytes.length); + + final byte[] gateCmdBytes = COPSMsgParser.shortToBytes(gateCommandType.getValue()); + System.arraycopy(gateCmdBytes, 0, data, transIdBytes.length, gateCmdBytes.length); + return data; } - /* - * (non-Javadoc) - * - * @see org.pcmm.gates.ITransactionID#getGateCommandType() + /** + * Returns a TransactionID object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. */ - @Override - public short getGateCommandType() { - return getShort((short) 2); + public static TransactionID parse(final byte[] data) { + return new TransactionID(COPSMsgParser.bytesToShort(data[0], data[1]), + GateCommandType.valueOf(COPSMsgParser.bytesToShort(data[2], data[3]))); } - } diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java b/packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java index 4fa90a5..47120f5 100644 --- a/packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java +++ b/packetcable-driver/src/main/java/org/pcmm/objects/MMVersionInfo.java @@ -1,39 +1,42 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.objects; import org.pcmm.base.impl.PCMMBaseObject; +import org.umu.cops.stack.COPSMsgParser; /** - * - * PCMM MM version info Object - * + * The Version Info object is used to enable Multimedia applications to adapt their interactions with other devices so + * that interoperability can be achieved between products supporting different protocol versions. Both the Major + * Version Number and the Minor Version Number are 2 byte unsigned integers. Both the PDP and the PEP must include this + * object as specified in Section 6.5.1 */ public class MMVersionInfo extends PCMMBaseObject { - private short majorVersionNB; - private short minorVersionNB; public static final short DEFAULT_MAJOR_VERSION_INFO = (short) 5; public static final short DEFAULT_MINOR_VERSION_INFO = (short) 0; - public MMVersionInfo() { - this(DEFAULT_MAJOR_VERSION_INFO, DEFAULT_MINOR_VERSION_INFO); - } + /** + * The major version number + */ + private final short majorVersionNB; - public MMVersionInfo(short majorVersionNB, short minorVersionNB) { - super((short) 8, (byte) 1, (byte) 16); - setShort(this.majorVersionNB = majorVersionNB, (short) 0); - setShort(this.minorVersionNB = minorVersionNB, (short) 2); - } + /** + * The minor version number + */ + private final short minorVersionNB; /** - * Parse data and create COPSHandle object + * Constructor + * @param majorVersionNB - the major version number + * @param minorVersionNB - the minor version number */ - public MMVersionInfo(byte[] dataPtr) { - super(dataPtr); - majorVersionNB = getShort((short) 0); - minorVersionNB = getShort((short) 2); + public MMVersionInfo(short majorVersionNB, short minorVersionNB) { + super(SNum.VERSION_INFO, (byte)1); + this.majorVersionNB = majorVersionNB; + this.minorVersionNB = minorVersionNB; } /** @@ -43,14 +46,6 @@ public class MMVersionInfo extends PCMMBaseObject { return majorVersionNB; } - /** - * @param majorVersionNB - * the majorVersionNB to set - */ - public void setMajorVersionNB(short majorVersionNB) { - this.majorVersionNB = majorVersionNB; - } - /** * @return the minorVersionNB */ @@ -58,12 +53,25 @@ public class MMVersionInfo extends PCMMBaseObject { return minorVersionNB; } + @Override + protected byte[] getBytes() { + final byte[] majVerBytes = COPSMsgParser.shortToBytes(majorVersionNB); + final byte[] minVerBytes = COPSMsgParser.shortToBytes(minorVersionNB); + final byte[] data = new byte[majVerBytes.length + minVerBytes.length]; + System.arraycopy(majVerBytes, 0, data, 0, majVerBytes.length); + System.arraycopy(minVerBytes, 0, data, majVerBytes.length, minVerBytes.length); + return data; + } + /** - * @param minorVersionNB - * the minorVersionNB to set + * Returns an MMVersionInfo object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. */ - public void setMinorVersionNB(short minorVersionNB) { - this.minorVersionNB = minorVersionNB; + public static MMVersionInfo parse(final byte[] data) { + return new MMVersionInfo(COPSMsgParser.bytesToShort(data[0], data[1]), + COPSMsgParser.bytesToShort(data[2], data[3])); } } diff --git a/packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java b/packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java index 409862b..8a386f0 100644 --- a/packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java +++ b/packetcable-driver/src/main/java/org/pcmm/objects/SyncOptions.java @@ -1,73 +1,156 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ + package org.pcmm.objects; import org.pcmm.base.impl.PCMMBaseObject; +import org.umu.cops.stack.COPSMsgParser; /** - * * PCMM SyncOptions object - * */ public class SyncOptions extends PCMMBaseObject { - private byte synchType; - - private byte reportType; - - public static final byte STANDARD_REPORT_DATA = (byte) 0; - public static final byte COMPLETE_GATE_DATA = (byte) 1; - public static final byte FULL_SYNCHRONIZATION = (byte) 0; - public static final byte INCREMENTAL_SYNCHRONIZATION = (byte) 1; + /** + * The requested report type + */ + private final ReportType reportType; - public SyncOptions() { - this(STANDARD_REPORT_DATA, FULL_SYNCHRONIZATION); - } + /** + * The requested type of synchronization + */ + private final SyncType syncType; - public SyncOptions(byte reportType, byte synchType) { - super((short) 8, (byte) 1, (byte) 18); - setByte(this.reportType = reportType, (short) 4); - setByte(this.synchType = synchType, (short) 6); + /** + * Constructor + * @param reportType - the requested report type + * @param syncType - the requested synchronization type + */ + public SyncOptions(final ReportType reportType, final SyncType syncType) { + super(SNum.SYNC_OPTS, (byte)1); + if (reportType == null) throw new IllegalArgumentException("Report type must not be null"); + if (syncType == null) throw new IllegalArgumentException("Synchronization type must not be null"); + this.reportType = reportType; + this.syncType = syncType; } /** - * Parse data and create COPSHandle object + * @return the syncType */ - public SyncOptions(byte[] dataPtr) { - super(dataPtr); - reportType = getByte((short) 4); - synchType = getByte((short) 6); + public SyncType getSyncType() { + return syncType; } /** - * @return the synchType + * @return the reportType */ - public byte getSynchType() { - return synchType; + public ReportType getReportType() { + return reportType; + } + + @Override + protected byte[] getBytes() { + final byte[] rptTypeBytes = COPSMsgParser.shortToBytes(reportType.getValue()); + final byte[] syncTypeBytes = COPSMsgParser.shortToBytes(syncType.getValue()); + final byte[] data = new byte[rptTypeBytes.length + syncTypeBytes.length]; + System.arraycopy(rptTypeBytes, 0, data, 0, rptTypeBytes.length); + System.arraycopy(syncTypeBytes, 0, data, rptTypeBytes.length, syncTypeBytes.length); + return data; + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (!(o instanceof SyncOptions)) { + return false; + } + if (!super.equals(o)) { + return false; + } + final SyncOptions that = (SyncOptions) o; + return reportType == that.reportType && syncType == that.syncType; + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + reportType.hashCode(); + result = 31 * result + syncType.hashCode(); + return result; } /** - * @param synchType - * the synchType to set + * Returns a SyncOptions object from a byte array + * @param data - the data to parse + * @return - the object + * TODO - make me more robust as RuntimeExceptions can be thrown here. */ - public void setSynchType(byte synchType) { - this.synchType = synchType; + public static SyncOptions parse(final byte[] data) { + return new SyncOptions(ReportType.valueOf(COPSMsgParser.bytesToShort(data[0], data[1])), + SyncType.valueOf(COPSMsgParser.bytesToShort(data[2], data[3]))); } /** - * @return the reportType + * The supported Report types */ - public byte getReportType() { - return reportType; + public enum ReportType { + + STANDARD_REPORT_DATA((short) 0), COMPLETE_GATE_DATA((short) 1); + + ReportType(short value) { + this.value = value; + } + + public short getValue() { + return value; + } + + public static ReportType valueOf(short v) { + switch (v) { + case 0: + return ReportType.STANDARD_REPORT_DATA; + case 1: + return ReportType.COMPLETE_GATE_DATA; + default: + throw new IllegalArgumentException("not supported value"); + } + } + + private short value; + } /** - * @param reportType - * the reportType to set + * The supported Synchronization types */ - public void setReportType(byte reportType) { - this.reportType = reportType; + public enum SyncType { + + FULL_SYNCHRONIZATION((short) 0), INCREMENTAL_SYNCHRONIZATION((short) 1); + + SyncType(short value) { + this.value = value; + } + + public short getValue() { + return value; + } + + public static SyncType valueOf(short v) { + switch (v) { + case 0: + return SyncType.FULL_SYNCHRONIZATION; + case 1: + return SyncType.INCREMENTAL_SYNCHRONIZATION; + default: + throw new IllegalArgumentException("not supported value"); + } + } + + private short value; + } } diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsDataProcessor.java b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsDataProcessor.java index c63f402..c13a154 100644 --- a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsDataProcessor.java +++ b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsDataProcessor.java @@ -51,9 +51,10 @@ class CmtsDataProcessor implements COPSPepDataProcess { data = installDecs.get(k); break; } - final ITransactionID transactionID = new PCMMGateReq(new COPSData(data).getData()).getTransactionID(); - final IPCMMGate responseGate = new PCMMGateReq(); - responseGate.setTransactionID(transactionID); + final ITransactionID transactionID = PCMMGateReq.parse(new COPSData(data).getData()).getTransactionID(); + + // TODO - Determine how and why a response gate request can have only a transaction ID??? + final IPCMMGate responseGate = new PCMMGateReq(null, null, transactionID, null, null, null, null, null); // TODO FIXME - Why is the key always null??? What value should be used here??? final String key = null; diff --git a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsPepReqStateMan.java b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsPepReqStateMan.java index 58dcfcc..19ef270 100644 --- a/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsPepReqStateMan.java +++ b/packetcable-driver/src/main/java/org/pcmm/rcd/impl/CmtsPepReqStateMan.java @@ -6,6 +6,7 @@ package org.pcmm.rcd.impl; import org.pcmm.gates.IGateSpec.Direction; import org.pcmm.gates.IPCMMError; +import org.pcmm.gates.IPCMMError.ErrorCode; import org.pcmm.gates.impl.GateID; import org.pcmm.gates.impl.PCMMError; import org.pcmm.gates.impl.PCMMGateReq; @@ -88,7 +89,7 @@ public class CmtsPepReqStateMan extends COPSPepReqStateMan { logger.info("processing decision"); // 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()); + final PCMMGateReq gateReq = PCMMGateReq.parse(dMsg.getDecSI().getData().getData()); if (gateReq.getGateSpec() != null) { processGateReq(gateReq, _socket); } @@ -137,18 +138,22 @@ public class CmtsPepReqStateMan extends COPSPepReqStateMan { // Get direction here final Direction gateDir = gateReq.getGateSpec().getDirection(); final Set gateNames = gateConfig.get(gateDir); - final String gateName = gateReq.getTrafficProfile().getData().str(); + // TODO - Determine if this is the best means to derive the gate name??? + final String gateName = new String(gateReq.getTrafficProfile().getAsBinaryArray()); - IPCMMError error = new PCMMError(); - if (subId == null || gateDir == null || gateNames == null || gateName == null) { + final IPCMMError error; + if (subId == null || gateDir == null || gateNames == null) { // Missing required object - error.setErrorCode((short)3); + // TODO - Determine if this is the correct code. 3 was being used previously and I don't see any corresponding code. + error = new PCMMError(ErrorCode.UNK_GATE_ID); } else if (!cmStatus.keySet().contains(subId) || (cmStatus.keySet().contains(subId) && !cmStatus.get(subId))) { // Invalid Object - error.setErrorCode((short)13); + // TODO - Determine if this code is correct + error = new PCMMError(ErrorCode.INVALID_SUB_ID); } else if (!gateNames.contains(gateName.trim())) { - error.setErrorCode((short)11); + // TODO - Determine if this code is correct + error = new PCMMError(ErrorCode.UNDEF_SCN_NAME); } else { error = null; gatesSetMap.get(gateName.trim()).add(subId); @@ -171,8 +176,7 @@ public class CmtsPepReqStateMan extends COPSPepReqStateMan { data.add(val); // Assign a gate ID - final GateID gateID = new GateID(); - gateID.setGateID(UUID.randomUUID().hashCode()); + final GateID gateID = new GateID(UUID.randomUUID().hashCode()); for (final byte val : gateID.getAsBinaryArray()) data.add(val); diff --git a/packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java b/packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java index 01e23e4..3737e1b 100644 --- a/packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java +++ b/packetcable-driver/src/main/java/org/pcmm/utils/PCMMException.java @@ -1,5 +1,5 @@ -/** - @header@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. */ package org.pcmm.utils; @@ -13,7 +13,7 @@ import org.pcmm.gates.IPCMMError; public class PCMMException extends Exception { public PCMMException(IPCMMError error) { - this(error.getDescription(), error.getErrorCode()); + this(error.getDescription(), error.getErrorCode().getCode()); } public PCMMException(String message, int code) { diff --git a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java index 071a11c..7ce4475 100644 --- a/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java +++ b/packetcable-driver/src/main/java/org/umu/cops/prpdp/COPSPdpAgent.java @@ -228,7 +228,7 @@ public class COPSPdpAgent { sendCloseMessage(conn, ErrorTypes.UNKNOWN_OBJECT, ErrorTypes.NA, "Unsupported objects (PdpAddress, Integrity)"); } else { - final MMVersionInfo _mminfo = new MMVersionInfo(cMsg.getClientSI().getData().getData()); + final MMVersionInfo _mminfo = MMVersionInfo.parse(cMsg.getClientSI().getData().getData()); logger.debug("CMTS sent MMVersion info : major:" + _mminfo.getMajorVersionNB() + " minor:" + _mminfo.getMinorVersionNB()); } diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/AMIDTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/AMIDTest.java new file mode 100644 index 0000000..57e5779 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/AMIDTest.java @@ -0,0 +1,34 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class AMID to ensure both construction and byte parsing result in correct object creation. + */ +public class AMIDTest { + + @Test + public void construction() { + final AMID amid = new AMID((short)5, (short)6); + final byte[] dataBytes = amid.getBytes(); + Assert.assertEquals((short)5, amid.getApplicationType()); + Assert.assertEquals((short)6, amid.getApplicationMgrTag()); + Assert.assertEquals(4, dataBytes.length); + Assert.assertEquals(5, COPSMsgParser.bytesToShort(dataBytes[0], dataBytes[1])); + Assert.assertEquals(6, COPSMsgParser.bytesToShort(dataBytes[2], dataBytes[3])); + } + + @Test + public void byteParsing() { + final AMID amid = new AMID((short)7, (short)8); + final AMID parsed = AMID.parse(amid.getBytes()); + Assert.assertEquals(amid, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/BestEffortServiceTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/BestEffortServiceTest.java new file mode 100644 index 0000000..fd9fb7b --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/BestEffortServiceTest.java @@ -0,0 +1,77 @@ +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests the data holder class BestEffortService to ensure both construction and byte parsing result in correct object + * creation. + */ +public class BestEffortServiceTest { + + @Test(expected = IllegalArgumentException.class) + public void nullAllEnvelopes() { + new BestEffortService(null, null, null); + } + + @Test + public void requiredEnvelopeOnly() { + final BEEnvelop auth = new BEEnvelop((byte)0, 1, 2, 3, 4, (short)5, (short)6, 7, 8, 9, 0, 1, 2, 3); + final BestEffortService service = new BestEffortService(auth, null, null); + Assert.assertNotNull(service.getAuthorizedEnvelop()); + Assert.assertNull(service.getReservedEnvelop()); + Assert.assertNull(service.getCommittedEnvelop()); + // TODO - add more validation here + } + + @Test + public void authAndReservedEnvelopes() { + final BEEnvelop auth = new BEEnvelop((byte)0, 1, 2, 3, 4, (short)5, (short)6, 7, 8, 9, 0, 1, 2, 3); + final BEEnvelop resv = new BEEnvelop((byte)10, 11, 12, 13, 14, (short)15, (short)16, 17, 18, 19, 10, 11, 12, 13); + final BestEffortService service = new BestEffortService(auth, resv, null); + Assert.assertNotNull(service.getAuthorizedEnvelop()); + Assert.assertNotNull(service.getReservedEnvelop()); + Assert.assertNull(service.getCommittedEnvelop()); + // TODO - add more validation here + } + + @Test + public void allEnvelopes() { + final BEEnvelop auth = new BEEnvelop((byte)0, 1, 2, 3, 4, (short)5, (short)6, 7, 8, 9, 0, 1, 2, 3); + final BEEnvelop resv = new BEEnvelop((byte)10, 11, 12, 13, 14, (short)15, (short)16, 17, 18, 19, 10, 11, 12, 13); + final BEEnvelop cmmt = new BEEnvelop((byte)20, 21, 22, 23, 24, (short)25, (short)26, 27, 28, 29, 20, 21, 22, 23); + final BestEffortService service = new BestEffortService(auth, resv, cmmt); + Assert.assertNotNull(service.getAuthorizedEnvelop()); + Assert.assertNotNull(service.getReservedEnvelop()); + Assert.assertNotNull(service.getCommittedEnvelop()); + // TODO - add more validation here + } + + @Test + public void byteParsingAuth() { + final BEEnvelop auth = new BEEnvelop((byte)0, 1, 2, 3, 4, (short)5, (short)6, 7, 8, 9, 0, 1, 2, 3); + final BestEffortService service = new BestEffortService(auth, null, null); + final BestEffortService parsed = BestEffortService.parse(service.getBytes()); + Assert.assertEquals(service, parsed); + } + + @Test + public void byteParsingAuthReserved() { + final BEEnvelop auth = new BEEnvelop((byte)0, 1, 2, 3, 4, (short)5, (short)6, 7, 8, 9, 0, 1, 2, 3); + final BEEnvelop resv = new BEEnvelop((byte)10, 11, 12, 13, 14, (short)15, (short)16, 17, 18, 19, 10, 11, 12, 13); + final BestEffortService service = new BestEffortService(auth, resv, null); + final BestEffortService parsed = BestEffortService.parse(service.getBytes()); + Assert.assertEquals(service, parsed); + } + + @Test + public void byteParsingAll() { + final BEEnvelop auth = new BEEnvelop((byte)0, 1, 2, 3, 4, (short)5, (short)6, 7, 8, 9, 0, 1, 2, 3); + final BEEnvelop resv = new BEEnvelop((byte)10, 11, 12, 13, 14, (short)15, (short)16, 17, 18, 19, 10, 11, 12, 13); + final BEEnvelop cmmt = new BEEnvelop((byte)20, 21, 22, 23, 24, (short)25, (short)26, 27, 28, 29, 20, 21, 22, 23); + final BestEffortService service = new BestEffortService(auth, resv, cmmt); + final BestEffortService parsed = BestEffortService.parse(service.getBytes()); + Assert.assertEquals(service, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/ClassifierTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/ClassifierTest.java new file mode 100644 index 0000000..9c1590e --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/ClassifierTest.java @@ -0,0 +1,62 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.gates.IClassifier.Protocol; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Tests the data holder class Classifier to ensure both construction and byte parsing result in correct object + * creation. + */ +public class ClassifierTest { + + @Test(expected = IllegalArgumentException.class) + public void nullProtocol() throws UnknownHostException { + new Classifier(null, (byte)1, (byte)1, (Inet4Address)InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)1, (short)2, (byte)4); + } + + @Test(expected = IllegalArgumentException.class) + public void nullSrcAddr() throws UnknownHostException { + new Classifier(Protocol.NONE, (byte)1, (byte)1, null, (Inet4Address)InetAddress.getByName("localhost"), + (short)1, (short)2, (byte)4); + } + + @Test(expected = IllegalArgumentException.class) + public void nullDstAddr() throws UnknownHostException { + new Classifier(Protocol.NONE, (byte)1, (byte)1, (Inet4Address)InetAddress.getByName("localhost"), null, + (short)1, (short)2, (byte)4); + } + + @Test + public void construction() throws UnknownHostException { + final Classifier classifier = new Classifier(Protocol.NONE, (byte)1, (byte)1, + (Inet4Address)InetAddress.getByName("localhost"), (Inet4Address)InetAddress.getByName("localhost"), + (short)1, (short)2, (byte)4); + Assert.assertEquals(Protocol.NONE, classifier.getProtocol()); + Assert.assertEquals((byte)1, classifier.getDSCPTOS()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getSourceIPAddress()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getDestinationIPAddress()); + Assert.assertEquals((short) 1, classifier.getSourcePort()); + Assert.assertEquals((short) 2, classifier.getDestinationPort()); + Assert.assertEquals((byte) 4, classifier.getPriority()); + } + + @Test + public void byteParsing() throws UnknownHostException { + final Classifier classifier = new Classifier(Protocol.NONE, (byte)1, (byte)4, + (Inet4Address)InetAddress.getByName("localhost"), (Inet4Address)InetAddress.getByName("localhost"), + (short)5, (short)6, (byte)7); + final Classifier parsed = Classifier.parse(classifier.getBytes()); + Assert.assertEquals(classifier, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfileTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfileTest.java new file mode 100644 index 0000000..7edc025 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/DOCSISServiceClassNameTrafficProfileTest.java @@ -0,0 +1,80 @@ +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests the data holder class DOCSISServiceClassNameTrafficProfile to ensure both construction and byte parsing result + * in correct object creation. + */ +public class DOCSISServiceClassNameTrafficProfileTest { + + @Test(expected = IllegalArgumentException.class) + public void constructor1NullSCN() { + new DOCSISServiceClassNameTrafficProfile(null); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor1ShortSCN() { + new DOCSISServiceClassNameTrafficProfile("1"); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor1LongSCN() { + new DOCSISServiceClassNameTrafficProfile("01234567891234567"); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor2NullSCN() { + new DOCSISServiceClassNameTrafficProfile((byte)1, null); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor2ShortSCN() { + new DOCSISServiceClassNameTrafficProfile((byte)1, "1"); + } + + @Test(expected = IllegalArgumentException.class) + public void constructor2LongSCN() { + new DOCSISServiceClassNameTrafficProfile((byte)1, "01234567891234567"); + } + + @Test + public void construction() { + final DOCSISServiceClassNameTrafficProfile profile = + new DOCSISServiceClassNameTrafficProfile((byte)5, "0123456789123456"); + Assert.assertEquals((byte)5, profile.getEnvelop()); + Assert.assertEquals("0123456789123456", profile.getScnName()); + } + + @Test + public void byteParsingWithoutPadding() { + // Name length % 4 == 0 + final DOCSISServiceClassNameTrafficProfile profile = + new DOCSISServiceClassNameTrafficProfile((byte)25, "1234"); + final DOCSISServiceClassNameTrafficProfile parsed = + DOCSISServiceClassNameTrafficProfile.parse(profile.getBytes()); + Assert.assertEquals(profile, parsed); + } + + @Test + public void byteParsingWithOnePaddedChar() { + // Name length % 4 == 1 + final DOCSISServiceClassNameTrafficProfile profile = + new DOCSISServiceClassNameTrafficProfile((byte)25, "123"); + final DOCSISServiceClassNameTrafficProfile parsed = + DOCSISServiceClassNameTrafficProfile.parse(profile.getBytes()); + Assert.assertEquals(profile, parsed); + } + + @Test + public void byteParsingWithThreePaddedChar() { + // Name length % 4 == 3 + final DOCSISServiceClassNameTrafficProfile profile = + new DOCSISServiceClassNameTrafficProfile((byte)25, "12345"); + final DOCSISServiceClassNameTrafficProfile parsed = + DOCSISServiceClassNameTrafficProfile.parse(profile.getBytes()); + Assert.assertEquals(profile, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/ExtendedClassifierTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/ExtendedClassifierTest.java new file mode 100644 index 0000000..8424622 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/ExtendedClassifierTest.java @@ -0,0 +1,138 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.gates.IClassifier.Protocol; +import org.pcmm.gates.IExtendedClassifier.ActivationState; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Tests the data holder class ExtendedClassifier to ensure both construction and byte parsing result in correct object + * creation. + */ +public class ExtendedClassifierTest { + + @Test(expected = IllegalArgumentException.class) + public void nullProtocol() throws UnknownHostException { + new ExtendedClassifier(null, (byte)1, (byte)1, (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)1, (short)2, (byte)4, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9); + } + + @Test(expected = IllegalArgumentException.class) + public void nullSrcAddr() throws UnknownHostException { + new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)1, null, + (Inet4Address)InetAddress.getByName("localhost"), (short)1, (short)2, (byte)4, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9); + } + + @Test(expected = IllegalArgumentException.class) + public void nullDstAddr() throws UnknownHostException { + new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)1, (Inet4Address) InetAddress.getByName("localhost"), + null, (short)1, (short)2, (byte)4, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9); + } + + @Test(expected = IllegalArgumentException.class) + public void nullSrcMask() throws UnknownHostException { + new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)1, (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)1, (short)2, (byte)4, + null, (Inet4Address) InetAddress.getByName("localhost"), + (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9); + } + + @Test(expected = IllegalArgumentException.class) + public void nullDstMask() throws UnknownHostException { + new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)1, (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)1, (short)2, (byte)4, + (Inet4Address) InetAddress.getByName("localhost"), null, + (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9); + } + + @Test(expected = IllegalArgumentException.class) + public void nullActivationState() throws UnknownHostException { + new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)1, (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)1, (short)2, (byte)4, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)5, (short)6, (short)7, null, (byte)9); + } + + @Test + public void constructionActive() throws UnknownHostException { + final ExtendedClassifier classifier = new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)10, + (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)11, (short)12, (byte)14, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)15, (short)16, (short)17, ActivationState.ACTIVE, (byte)19); + Assert.assertEquals(Protocol.NONE, classifier.getProtocol()); + Assert.assertEquals((byte)1, classifier.getDSCPTOS()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getSourceIPAddress()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getDestinationIPAddress()); + Assert.assertEquals((short) 11, classifier.getSourcePort()); + Assert.assertEquals((short) 12, classifier.getDestinationPort()); + Assert.assertEquals((byte) 14, classifier.getPriority()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getIPSourceMask()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getIPDestinationMask()); + Assert.assertEquals((short) 15, classifier.getSourcePortEnd()); + Assert.assertEquals((short) 16, classifier.getDestinationPortEnd()); + Assert.assertEquals((short) 17, classifier.getClassifierID()); + Assert.assertEquals(ActivationState.ACTIVE, classifier.getActivationState()); + Assert.assertEquals((byte) 19, classifier.getAction()); + } + + @Test + public void constructionInactive() throws UnknownHostException { + final ExtendedClassifier classifier = new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)10, + (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)11, (short)12, (byte)14, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)15, (short)16, (short)17, ActivationState.INACTIVE, (byte)19); + Assert.assertEquals(Protocol.NONE, classifier.getProtocol()); + Assert.assertEquals((byte)1, classifier.getDSCPTOS()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getSourceIPAddress()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getDestinationIPAddress()); + Assert.assertEquals((short) 11, classifier.getSourcePort()); + Assert.assertEquals((short) 12, classifier.getDestinationPort()); + Assert.assertEquals((byte) 14, classifier.getPriority()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getIPSourceMask()); + Assert.assertEquals(InetAddress.getByName("localhost"), classifier.getIPDestinationMask()); + Assert.assertEquals((short) 15, classifier.getSourcePortEnd()); + Assert.assertEquals((short) 16, classifier.getDestinationPortEnd()); + Assert.assertEquals((short) 17, classifier.getClassifierID()); + Assert.assertEquals(ActivationState.INACTIVE, classifier.getActivationState()); + Assert.assertEquals((byte) 19, classifier.getAction()); + } + + @Test + public void byteParsingActive() throws UnknownHostException { + final ExtendedClassifier classifier = new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)20, + (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)21, (short)22, (byte)24, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)25, (short)26, (short)27, ActivationState.ACTIVE, (byte)29); + final ExtendedClassifier parsed = ExtendedClassifier.parse(classifier.getBytes()); + Assert.assertEquals(classifier, parsed); + } + + @Test + public void byteParsingInactive() throws UnknownHostException { + final ExtendedClassifier classifier = new ExtendedClassifier(Protocol.NONE, (byte)1, (byte)20, + (Inet4Address) InetAddress.getByName("localhost"), + (Inet4Address)InetAddress.getByName("localhost"), (short)21, (short)22, (byte)24, + (Inet4Address) InetAddress.getByName("localhost"), (Inet4Address) InetAddress.getByName("localhost"), + (short)25, (short)26, (short)27, ActivationState.INACTIVE, (byte)29); + final ExtendedClassifier parsed = ExtendedClassifier.parse(classifier.getBytes()); + Assert.assertEquals(classifier, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/GateIDTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/GateIDTest.java new file mode 100644 index 0000000..32e87e8 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/GateIDTest.java @@ -0,0 +1,38 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class GateId to ensure both construction and byte parsing result in correct object creation. + */ +public class GateIDTest { + + @Test + public void construction() { + final GateID gateID = new GateID(9); + + // Check the object's bytes + final byte[] dataBytes = gateID.getBytes(); + Assert.assertEquals(9, gateID.getGateID()); + Assert.assertEquals(4, dataBytes.length); + Assert.assertEquals(9, COPSMsgParser.bytesToInt(dataBytes[0], dataBytes[1], dataBytes[2], dataBytes[3])); + + // Check the byte parsing + final GateID parsed = GateID.parse(dataBytes); + Assert.assertEquals(gateID, parsed); + } + + @Test + public void byteParsing() { + final GateID gateID = new GateID(10); + final GateID parsed = GateID.parse(gateID.getBytes()); + Assert.assertEquals(gateID, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/GateSpecTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/GateSpecTest.java new file mode 100644 index 0000000..e63e3f5 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/GateSpecTest.java @@ -0,0 +1,63 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.gates.IGateSpec.Direction; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class GateSpec to ensure both construction and byte parsing result in correct object + * creation. + */ +public class GateSpecTest { + + @Test(expected = IllegalArgumentException.class) + public void nullDirection() { + new GateSpec(null, (byte)1, (byte)1, new SessionClassID((byte)1), + (short)1, (short)2, (short)3, (short)4); + } + + @Test(expected = IllegalArgumentException.class) + public void nullSessionClassID() { + new GateSpec(Direction.UPSTREAM, (byte)1, (byte)1, null, + (short)1, (short)2, (short)3, (short)4); + } + + @Test + public void construction() { + final GateSpec spec = new GateSpec(Direction.UPSTREAM, (byte)1, (byte)1, new SessionClassID((byte)1), + (short)1, (short)2, (short)3, (short)4); + Assert.assertEquals(Direction.UPSTREAM, spec.getDirection()); + Assert.assertEquals((byte)1, spec.getDSCP_TOSOverwrite()); + Assert.assertEquals((byte)1, spec.getDSCP_TOSMask()); + Assert.assertEquals(new SessionClassID((byte) 1), spec.getSessionClassID()); + Assert.assertEquals((short)1, spec.getTimerT1()); + Assert.assertEquals((short)2, spec.getTimerT2()); + Assert.assertEquals((short)3, spec.getTimerT3()); + Assert.assertEquals((short)4, spec.getTimerT4()); + + final byte[] data = spec.getBytes(); + + Assert.assertEquals(Direction.UPSTREAM, Direction.valueOf(data[0])); + Assert.assertEquals((byte)1, data[1]); + Assert.assertEquals((byte)1, data[2]); + Assert.assertEquals(new SessionClassID((byte)1), new SessionClassID(data[3])); + Assert.assertEquals((short)1, COPSMsgParser.bytesToShort(data[4], data[5])); + Assert.assertEquals((short)2, COPSMsgParser.bytesToShort(data[6], data[7])); + Assert.assertEquals((short)3, COPSMsgParser.bytesToShort(data[8], data[9])); + Assert.assertEquals((short)4, COPSMsgParser.bytesToShort(data[10], data[11])); + } + + @Test + public void byteParsing() { + final GateSpec spec = new GateSpec(Direction.DOWNSTREAM, (byte)1, (byte)2, new SessionClassID((byte)3), + (short)4, (short)5, (short)6, (short)7); + final GateSpec parsed = GateSpec.parse(spec.getBytes()); + Assert.assertEquals(spec, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/IPv6ClassifierTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/IPv6ClassifierTest.java new file mode 100644 index 0000000..e43abef --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/IPv6ClassifierTest.java @@ -0,0 +1,136 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.gates.IExtendedClassifier.ActivationState; +import org.pcmm.gates.IIPv6Classifier.FlowLabel; + +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Tests the data holder class ExtendedClassifier. + */ +public class IPv6ClassifierTest { + + @Test(expected = IllegalArgumentException.class) + public void nullSrcAddr() throws UnknownHostException { + new IPv6Classifier(null, (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (short)1, (short)2, (byte)4, (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9, + FlowLabel.VALID, (byte)11, (byte)12, (byte)13, 14, (short)15, (byte)16, (byte)17); + } + + @Test(expected = IllegalArgumentException.class) + public void nullDstAddr() throws UnknownHostException { + new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + null, (short)1, (short)2, (byte)4, (short)5, (short)6, (short)7, ActivationState.ACTIVE, (byte)9, + FlowLabel.VALID, (byte)11, (byte)12, (byte)13, 14, (short)15, (byte)16, (byte)17); + } + + @Test(expected = IllegalArgumentException.class) + public void nullActivationState() throws UnknownHostException { + new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), (short)1, (short)2, (byte)4, (short)5, + (short)6, (short)7, null, (byte)9, FlowLabel.VALID, (byte)11, (byte)12, (byte)13, 14, (short)15, + (byte)16, (byte)17); + } + + @Test(expected = IllegalArgumentException.class) + public void nullFlowLabel() throws UnknownHostException { + new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), (short)1, (short)2, (byte)4, (short)5, + (short)6, (short)7, ActivationState.ACTIVE, (byte)9, null, (byte)11, (byte)12, (byte)13, 14, (short)15, + (byte)16, (byte)17); + } + + @Test + public void constructionActiveValid() throws UnknownHostException { + final IPv6Classifier classifier = new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (short)11, (short)12, (byte)14, (short)15, (short)16, (short)17, ActivationState.ACTIVE, (byte)19, + FlowLabel.VALID, (byte)21, (byte)22, (byte)23, 24, (short)25, (byte)26, (byte)27); + + Assert.assertNull(classifier.getProtocol()); + + Assert.assertEquals((byte) 0, classifier.getDSCPTOS()); + + Assert.assertEquals(InetAddress.getByName("00:00:00:00:00:00:00:01"), classifier.getSourceIPAddress()); + Assert.assertEquals(InetAddress.getByName("00:00:00:00:00:00:00:01"), classifier.getDestinationIPAddress()); + Assert.assertEquals((short) 11, classifier.getSourcePort()); + Assert.assertEquals((short) 12, classifier.getDestinationPort()); + Assert.assertEquals((byte) 14, classifier.getPriority()); + Assert.assertEquals((short) 15, classifier.getSourcePortEnd()); + Assert.assertEquals((short) 16, classifier.getDestinationPortEnd()); + Assert.assertEquals((short) 17, classifier.getClassifierID()); + Assert.assertEquals(ActivationState.ACTIVE, classifier.getActivationState()); + Assert.assertEquals((byte) 19, classifier.getAction()); + Assert.assertEquals(FlowLabel.VALID, classifier.getFlowLabelEnableFlag()); + Assert.assertEquals((byte) 21, classifier.getTcLow()); + Assert.assertEquals((byte) 22, classifier.getTcHigh()); + Assert.assertEquals((byte) 23, classifier.getTcMask()); + Assert.assertEquals(24, classifier.getFlowLabel()); + Assert.assertEquals((short)25, classifier.getNextHdr()); + Assert.assertEquals((byte)26, classifier.getSourcePrefixLen()); + Assert.assertEquals((byte)27, classifier.getDestinationPrefixLen()); + } + + @Test + public void constructionInactiveIrrelevant() throws UnknownHostException { + final IPv6Classifier classifier = new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (short)11, (short)12, (byte)14, (short)15, (short)16, (short)17, ActivationState.INACTIVE, (byte)19, + FlowLabel.IRRELEVANT, (byte)21, (byte)22, (byte)23, 24, (short)25, (byte)26, (byte)27); + + Assert.assertNull(classifier.getProtocol()); + + Assert.assertEquals((byte) 0, classifier.getDSCPTOS()); + + Assert.assertEquals(InetAddress.getByName("00:00:00:00:00:00:00:01"), classifier.getSourceIPAddress()); + Assert.assertEquals(InetAddress.getByName("00:00:00:00:00:00:00:01"), classifier.getDestinationIPAddress()); + Assert.assertEquals((short) 11, classifier.getSourcePort()); + Assert.assertEquals((short) 12, classifier.getDestinationPort()); + Assert.assertEquals((byte) 14, classifier.getPriority()); + Assert.assertEquals((short) 15, classifier.getSourcePortEnd()); + Assert.assertEquals((short) 16, classifier.getDestinationPortEnd()); + Assert.assertEquals((short) 17, classifier.getClassifierID()); + Assert.assertEquals(ActivationState.INACTIVE, classifier.getActivationState()); + Assert.assertEquals((byte) 19, classifier.getAction()); + Assert.assertEquals(FlowLabel.IRRELEVANT, classifier.getFlowLabelEnableFlag()); + Assert.assertEquals((byte) 21, classifier.getTcLow()); + Assert.assertEquals((byte) 22, classifier.getTcHigh()); + Assert.assertEquals((byte) 23, classifier.getTcMask()); + + // Per specs, this value must be 0 when IRRELEVANT + Assert.assertEquals(0, classifier.getFlowLabel()); + + Assert.assertEquals((short)25, classifier.getNextHdr()); + Assert.assertEquals((byte)26, classifier.getSourcePrefixLen()); + Assert.assertEquals((byte)27, classifier.getDestinationPrefixLen()); + } + + @Test + public void byteParsingActiveValid() throws UnknownHostException { + final IPv6Classifier classifier = new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (short)21, (short)22, (byte)24, (short)25, (short)26, (short)27, ActivationState.ACTIVE, (byte)29, + FlowLabel.VALID, (byte)31, (byte)32, (byte)33, 34, (short)35, (byte)36, (byte)37); + final IPv6Classifier parsed = IPv6Classifier.parse(classifier.getBytes()); + Assert.assertEquals(classifier, parsed); + } + + @Test + public void byteParsingInactiveIrrelevant() throws UnknownHostException { + final IPv6Classifier classifier = new IPv6Classifier((Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (Inet6Address)InetAddress.getByName("00:00:00:00:00:00:00:01"), + (short)21, (short)22, (byte)24, (short)25, (short)26, (short)27, ActivationState.INACTIVE, (byte)29, + FlowLabel.IRRELEVANT, (byte)31, (byte)32, (byte)33, 34, (short)35, (byte)36, (byte)37); + final IPv6Classifier parsed = IPv6Classifier.parse(classifier.getBytes()); + Assert.assertEquals(classifier, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/PCMMErrorTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/PCMMErrorTest.java new file mode 100644 index 0000000..6896805 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/PCMMErrorTest.java @@ -0,0 +1,55 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.gates.IPCMMError.ErrorCode; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class PCMMError to ensure both construction and byte parsing result in correct object + * creation. + */ +public class PCMMErrorTest { + + @Test(expected = IllegalArgumentException.class) + public void nullErrorAndSubCodes() { + new PCMMError(null, null); + } + + @Test(expected = IllegalArgumentException.class) + public void nullErrorCode() { + new PCMMError(null, ErrorCode.DOCSIS_1_CM); + } + + @Test(expected = IllegalArgumentException.class) + public void naErrorCode() { + new PCMMError(ErrorCode.NA); + } + + @Test + public void construction() { + final PCMMError error = new PCMMError(ErrorCode.TRANSPORT_ERROR, null); + Assert.assertEquals(ErrorCode.TRANSPORT_ERROR, error.getErrorCode()); + Assert.assertEquals(ErrorCode.NA, error.getErrorSubcode()); + + final byte[] dataBytes = error.getBytes(); + Assert.assertEquals(4, dataBytes.length); + Assert.assertEquals(ErrorCode.TRANSPORT_ERROR, + ErrorCode.valueOf(COPSMsgParser.bytesToShort(dataBytes[0], dataBytes[1]))); + final short subCodeVal = COPSMsgParser.bytesToShort(dataBytes[2], dataBytes[3]); + Assert.assertEquals(ErrorCode.NA, + ErrorCode.valueOf(COPSMsgParser.bytesToShort(dataBytes[2], dataBytes[3]))); + } + + @Test + public void byteParsing() { + final PCMMError error = new PCMMError(ErrorCode.INVALID_FIELD, ErrorCode.INVALID_SUB_ID); + final PCMMError parsed = PCMMError.parse(error.getBytes()); + Assert.assertEquals(error, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/SessionClassIDTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/SessionClassIDTest.java new file mode 100644 index 0000000..67d3fa3 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/SessionClassIDTest.java @@ -0,0 +1,27 @@ +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests the data holder class SessionClassID to ensure both construction and byte parsing result in correct object + * creation. + */ +public class SessionClassIDTest { + + @Test + public void constructor1() { + final SessionClassID sessionClassID = new SessionClassID((byte)1); + Assert.assertEquals((byte)1, sessionClassID.toSingleByte()); + Assert.assertEquals((byte)1 >> 2, sessionClassID.getPriority()); + Assert.assertEquals((byte)1 >> 3, sessionClassID.getPreemption()); + } + + @Test + public void constructor2() { + final SessionClassID sessionClassID = new SessionClassID((byte)1, (byte)3, (byte)4); + Assert.assertEquals((byte)1, sessionClassID.toSingleByte()); + Assert.assertEquals((byte)3, sessionClassID.getPriority()); + Assert.assertEquals((byte)4, sessionClassID.getPreemption()); + } +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/SubscriberIDTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/SubscriberIDTest.java new file mode 100644 index 0000000..ba04fbd --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/SubscriberIDTest.java @@ -0,0 +1,80 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; + +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Tests the data holder class SubscriberId to ensure both construction and byte parsing result in correct object + * creation. + */ +public class SubscriberIDTest { + + @Test(expected = IllegalArgumentException.class) + public void nullConstArg() { + new SubscriberID(null); + } + + @Test + public void constructorIpv4() { + final InetAddress addr; + try { + addr = InetAddress.getByName("127.0.0.1"); + if (addr instanceof Inet6Address) Assert.fail("Address should be IPv4"); + } catch (UnknownHostException e) { + throw new RuntimeException("host not found"); + } + final SubscriberID subId = new SubscriberID(addr); + Assert.assertEquals(addr, subId.getSourceIPAddress()); + } + + @Test + public void byteParsingIpv4() { + final InetAddress addr; + try { + addr = InetAddress.getByName("127.0.0.1"); + if (addr instanceof Inet6Address) Assert.fail("Address should be IPv4"); + } catch (UnknownHostException e) { + throw new RuntimeException("host not found"); + } + final SubscriberID subId = new SubscriberID(addr); + final SubscriberID parsed = SubscriberID.parse(subId.getBytes()); + Assert.assertEquals(subId, parsed); + } + + @Test + public void constructorIpv6() { + final InetAddress addr; + try { + addr = InetAddress.getByName("00:00:00:00:00:00:00:01"); + if (addr instanceof Inet4Address) Assert.fail("Address should be IPv6"); + } catch (UnknownHostException e) { + throw new RuntimeException("host not found"); + } + final SubscriberID subId = new SubscriberID(addr); + Assert.assertEquals(addr, subId.getSourceIPAddress()); + } + + @Test + public void byteParsingIpv6() { + final InetAddress addr; + try { + addr = InetAddress.getByName("00:00:00:00:00:00:00:01"); + if (addr instanceof Inet4Address) Assert.fail("Address should be IPv6"); + } catch (UnknownHostException e) { + throw new RuntimeException("host not found"); + } + final SubscriberID subId = new SubscriberID(addr); + final SubscriberID parsed = SubscriberID.parse(subId.getBytes()); + Assert.assertEquals(subId, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/gates/impl/TransactionIDTest.java b/packetcable-driver/src/test/java/org/pcmm/gates/impl/TransactionIDTest.java new file mode 100644 index 0000000..2639c6f --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/gates/impl/TransactionIDTest.java @@ -0,0 +1,40 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.gates.impl; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.gates.ITransactionID.GateCommandType; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class TransactionID to ensure both construction and byte parsing result in correct object + * creation. + */ +public class TransactionIDTest { + + @Test(expected = IllegalArgumentException.class) + public void nullCommandType() { + new TransactionID((short)9, null); + } + + @Test + public void construction() { + final TransactionID transID = new TransactionID((short)9, GateCommandType.GATE_CMD_ERR); + final byte[] dataBytes = transID.getBytes(); + Assert.assertEquals(4, dataBytes.length); + Assert.assertEquals(9, COPSMsgParser.bytesToShort(dataBytes[0], dataBytes[1])); + Assert.assertEquals(GateCommandType.GATE_CMD_ERR, + GateCommandType.valueOf(COPSMsgParser.bytesToShort(dataBytes[2], dataBytes[3]))); + } + + @Test + public void byteParsing() { + final TransactionID transID = new TransactionID((short)11, GateCommandType.GATE_DELETE_ACK); + final TransactionID parsed = TransactionID.parse(transID.getBytes()); + Assert.assertEquals(transID, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/objects/MMVersionInfoTest.java b/packetcable-driver/src/test/java/org/pcmm/objects/MMVersionInfoTest.java new file mode 100644 index 0000000..cc07747 --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/objects/MMVersionInfoTest.java @@ -0,0 +1,33 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.objects; + +import org.junit.Assert; +import org.junit.Test; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class MMVersionInfo to ensure both construction and byte parsing result in correct object + * creation. + */ +public class MMVersionInfoTest { + + @Test + public void construction() { + final MMVersionInfo verInfo = new MMVersionInfo((short)5, (short)6); + final byte[] dataBytes = verInfo.getBytes(); + Assert.assertEquals(4, dataBytes.length); + Assert.assertEquals(5, COPSMsgParser.bytesToShort(dataBytes[0], dataBytes[1])); + Assert.assertEquals(6, COPSMsgParser.bytesToShort(dataBytes[2], dataBytes[3])); + } + + @Test + public void byteParsing() { + final MMVersionInfo verInfo = new MMVersionInfo((short)7, (short)8); + final MMVersionInfo parsed = MMVersionInfo.parse(verInfo.getBytes()); + Assert.assertEquals(verInfo, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/objects/SyncOptionsTest.java b/packetcable-driver/src/test/java/org/pcmm/objects/SyncOptionsTest.java new file mode 100644 index 0000000..65aee3e --- /dev/null +++ b/packetcable-driver/src/test/java/org/pcmm/objects/SyncOptionsTest.java @@ -0,0 +1,47 @@ +/* + * (c) 2015 Cable Television Laboratories, Inc. All rights reserved. + */ + +package org.pcmm.objects; + +import org.junit.Assert; +import org.junit.Test; +import org.pcmm.objects.SyncOptions.ReportType; +import org.pcmm.objects.SyncOptions.SyncType; +import org.umu.cops.stack.COPSMsgParser; + +/** + * Tests the data holder class SyncOptions to ensure both construction and byte parsing result in correct object + * creation. + */ +public class SyncOptionsTest { + + @Test(expected = IllegalArgumentException.class) + public void nullReportType() { + new SyncOptions(null, SyncType.FULL_SYNCHRONIZATION); + } + + @Test(expected = IllegalArgumentException.class) + public void nullSyncType() { + new SyncOptions(ReportType.STANDARD_REPORT_DATA, null); + } + + @Test + public void construction() { + final SyncOptions syncOpts = new SyncOptions(ReportType.STANDARD_REPORT_DATA, SyncType.FULL_SYNCHRONIZATION); + final byte[] dataBytes = syncOpts.getBytes(); + Assert.assertEquals(4, dataBytes.length); + Assert.assertEquals(ReportType.STANDARD_REPORT_DATA, + ReportType.valueOf(COPSMsgParser.bytesToShort(dataBytes[0], dataBytes[1]))); + Assert.assertEquals(SyncType.FULL_SYNCHRONIZATION, + SyncType.valueOf(COPSMsgParser.bytesToShort(dataBytes[2], dataBytes[3]))); + } + + @Test + public void byteParsing() { + final SyncOptions syncOpts = new SyncOptions(ReportType.COMPLETE_GATE_DATA, SyncType.INCREMENTAL_SYNCHRONIZATION); + final SyncOptions parsed = SyncOptions.parse(syncOpts.getBytes()); + Assert.assertEquals(syncOpts, parsed); + } + +} diff --git a/packetcable-driver/src/test/java/org/pcmm/test/BestEffortServiceTest.java b/packetcable-driver/src/test/java/org/pcmm/test/BestEffortServiceTest.java deleted file mode 100644 index defde2e..0000000 --- a/packetcable-driver/src/test/java/org/pcmm/test/BestEffortServiceTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.pcmm.test; - -import static org.junit.Assert.*; - -import org.junit.Before; -import org.junit.Test; -import org.pcmm.gates.impl.BestEffortService; - -public class BestEffortServiceTest { - - private BestEffortService be; - - @Before - public void init() { - be = new BestEffortService((byte) 7); - be.getAuthorizedEnvelop().setMinimumReservedTrafficRate(192); - be.getCommittedEnvelop().setRequiredAttributeMask(938); - be.getReservedEnvelop().setTrafficPriority((byte) 5); - } - - @Test - public void testGetAsBinaryArray() { - assertTrue(be.getAsBinaryArray().length == 116); - } - - @Test - public void testBestEffortServiceByteArray() { - assertTrue(new BestEffortService(be.getAsBinaryArray()) - .getAuthorizedEnvelop().getMinimumReservedTrafficRate() == 192); - assertTrue(new BestEffortService(be.getAsBinaryArray()) - .getReservedEnvelop().getTrafficPriority() == 5); - assertTrue(new BestEffortService(be.getAsBinaryArray()) - .getCommittedEnvelop().getRequiredAttributeMask() == 938); - - } - - @Test - public void testGetEnvelop() { - assertTrue(be.getEnvelop() == 7); - } - -} diff --git a/packetcable-driver/src/test/java/org/pcmm/test/PCErrorTest.java b/packetcable-driver/src/test/java/org/pcmm/test/PCErrorTest.java deleted file mode 100644 index d6f129a..0000000 --- a/packetcable-driver/src/test/java/org/pcmm/test/PCErrorTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.pcmm.test; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.pcmm.gates.IPCMMError; -import org.pcmm.gates.impl.PCMMError; - -public class PCErrorTest { - - IPCMMError error; - - @Before - public void init() { - error = new PCMMError(); - error.setErrorCode((short) 1); - } - - @Test - public void testGetDescription() { - for (IPCMMError.Description d : IPCMMError.Description.values()) { - error.setErrorCode(d.getCode()); - Assert.assertNotNull(error.getDescription()); - System.out.println(error.getDescription()); - } - - } - -} diff --git a/packetcable-driver/src/test/java/org/pcmm/test/PCMMGateReqTest.java b/packetcable-driver/src/test/java/org/pcmm/test/PCMMGateReqTest.java deleted file mode 100644 index bfd622c..0000000 --- a/packetcable-driver/src/test/java/org/pcmm/test/PCMMGateReqTest.java +++ /dev/null @@ -1,40 +0,0 @@ -/** - * - */ -package org.pcmm.test; - -import static org.junit.Assert.fail; - -import org.junit.Test; -import org.pcmm.gates.impl.PCMMGateReq; -import org.pcmm.utils.PCMMUtils; - -/** - * @author RH030971 - * - */ -public class PCMMGateReqTest { - - /** - * Test method for - * {@link org.pcmm.gates.impl.PCMMGateReq#PCMMGateReq(byte[])}. - */ - @Test - public void testPCMMGateReqByteArray() { -/* - new PCMMGateReq( - PCMMUtils - .ReadBinaryDump("traces/COPSReportClientSI09871088-5329-44ff-b1db-0ea3a544de1e.bin")); - -*/ - } - - /** - * Test method for {@link org.pcmm.gates.impl.PCMMGateReq#getData()}. - */ - @Test - public void testGetData() { - // fail("Not yet implemented"); - } - -} diff --git a/packetcable-driver/src/test/java/org/pcmm/test/README.md b/packetcable-driver/src/test/java/org/pcmm/test/README.md deleted file mode 100644 index f32f06a..0000000 --- a/packetcable-driver/src/test/java/org/pcmm/test/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This package contains the test set for the PCMM driver, -To test the whole workflow use the junit based test : PCMMWorkflowTest.java \ No newline at end of file diff --git a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java index 5257632..79523ab 100644 --- a/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java +++ b/packetcable-policy-server/src/main/java/org/opendaylight/controller/packetcable/provider/PCMMGateReqBuilder.java @@ -11,327 +11,340 @@ import org.opendaylight.yang.gen.v1.urn.packetcable.rev150327.pcmm.qos.ext.class 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.IClassifier; +import org.pcmm.gates.IClassifier.Protocol; +import org.pcmm.gates.IExtendedClassifier.ActivationState; 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.pcmm.gates.IIPv6Classifier.FlowLabel; +import org.pcmm.gates.ITrafficProfile; +import org.pcmm.gates.impl.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.net.Inet4Address; +import java.net.Inet6Address; 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); - } + private Logger logger = LoggerFactory.getLogger(PCMMGateReqBuilder.class); + + private GateID gateID = null; + private AMID amid = null; + private SubscriberID subscriberID = null; + private TransactionID transactionID = null; + private org.pcmm.gates.impl.GateSpec gateSpec = null; + private ITrafficProfile trafficProfile = null; + private IClassifier classifier = null; + private PCMMError error = null; + + public PCMMGateReq getGateReq() { + return new PCMMGateReq(amid, subscriberID, transactionID, gateSpec, trafficProfile, classifier, gateID, error); + } + + public void build(final AmId qosAmId) { + amid = new AMID(qosAmId.getAmType().shortValue(), qosAmId.getAmTag().shortValue()); + } + + public void build(final InetAddress qosSubId) { + subscriberID = new SubscriberID(qosSubId); + } + + public void build(final GateSpec qosGateSpec, final ServiceFlowDirection scnDirection) { + + final ServiceFlowDirection qosDir; + if (scnDirection != null) { + qosDir = scnDirection; + } else { + if (qosGateSpec.getDirection() != null) { + qosDir = qosGateSpec.getDirection(); + } else { + // TODO - determine if this is a valid default value + qosDir = ServiceFlowDirection.Ds; + } + } + + final Direction gateDir; + if (qosDir == ServiceFlowDirection.Ds) { + gateDir = Direction.DOWNSTREAM; + } else { + gateDir = Direction.UPSTREAM; + } + + // DSCP/TOS Overwrite + final byte dscptos; + final byte gateTosMask; + + final TosByte tosOverwrite = qosGateSpec.getDscpTosOverwrite(); + if (tosOverwrite != null) { + dscptos = 1; + TosByte tosMask = qosGateSpec.getDscpTosMask(); + if (tosMask != null) { + gateTosMask = tosMask.getValue().byteValue(); + } else { + gateTosMask = (byte) 0xff; + } + } else { + // TODO - These values appear to be required + dscptos = 0; + gateTosMask = 0; + } + gateSpec = new org.pcmm.gates.impl.GateSpec(gateDir, dscptos, gateTosMask); + } + + public void build(final TrafficProfile qosTrafficProfile) { + if (qosTrafficProfile.getServiceClassName() != null) { + trafficProfile = + new DOCSISServiceClassNameTrafficProfile(qosTrafficProfile.getServiceClassName().getValue()); + } + } + + private InetAddress getByName(final String ipAddressStr) { + try { + return InetAddress.getByName(ipAddressStr); + } catch (UnknownHostException e) { + logger.error(e.getMessage()); + } + return null; + } + + public void build(final Classifier qosClassifier) { + // TODO - try and make these variables immutable + Protocol protocol = null; + byte tosOverwrite = 0; + byte tosMask = (byte)0x0; + Inet4Address srcAddress = null; + Inet4Address dstAddress = null; + short srcPort = (short) 0; + short dstPort = (short) 0; + byte priority = (byte) 64; + + // Legacy classifier + if (qosClassifier.getProtocol() != null) { + protocol = Protocol.valueOf(qosClassifier.getProtocol().getValue().shortValue()); + } + if (qosClassifier.getSrcIp() != null) { + final InetAddress sip = getByName(qosClassifier.getSrcIp().getValue()); + if (sip != null && sip instanceof Inet4Address) { + srcAddress = (Inet4Address) sip; + } + } + if (qosClassifier.getDstIp() != null) { + final InetAddress dip = getByName(qosClassifier.getDstIp().getValue()); + if (dip != null && dip instanceof Inet4Address) { + dstAddress = (Inet4Address) dip; + } + } + if (qosClassifier.getSrcPort() != null) { + srcPort = qosClassifier.getSrcPort().getValue().shortValue(); + } + if (qosClassifier.getDstPort() != null) { + dstPort = qosClassifier.getDstPort().getValue().shortValue(); + } + if (qosClassifier.getTosByte() != null) { + tosOverwrite = qosClassifier.getTosByte().getValue().byteValue(); + if (qosClassifier.getTosMask() != null) { + tosMask = qosClassifier.getTosMask().getValue().byteValue(); + } else { + // set default TOS mask + tosMask = (byte) 0xff; + } + } + // push the classifier to the gate request + classifier = + new org.pcmm.gates.impl.Classifier(protocol, tosOverwrite, tosMask, srcAddress, dstAddress, srcPort, + dstPort, priority); + } + + public void build(final ExtClassifier qosExtClassifier) { + // Extended classifier + final byte priority = (byte) 64; + final ActivationState activationState = ActivationState.ACTIVE; + // Protocol -- zero is match any + final Protocol protocol; + if (qosExtClassifier.getProtocol() != null) { + protocol = Protocol.valueOf(qosExtClassifier.getProtocol().getValue().shortValue()); + } else { + protocol = Protocol.NONE; + } + + // 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 + // TODO - try to make these two variables immutable + short srcStartPort = (short) 0; + short srcEndPort = (short) 65535; + if (qosExtClassifier.getSrcPortStart() != null) { + srcStartPort = qosExtClassifier.getSrcPortStart().getValue().shortValue(); + srcEndPort = srcStartPort; + if (qosExtClassifier.getSrcPortEnd() != null) { + srcEndPort = qosExtClassifier.getSrcPortEnd().getValue().shortValue(); + } + if (srcStartPort > srcEndPort) { + logger.warn("Start port %d > End port %d in ext-classifier source port range -- forcing to same", + srcStartPort, srcEndPort); + srcEndPort = srcStartPort; + } + } + // 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 + // TODO - try to make these two variables immutable + short dstStartPort = (short) 0; + short dstEndPort = (short) 65535; + if (qosExtClassifier.getDstPortStart() != null) { + dstStartPort = qosExtClassifier.getDstPortStart().getValue().shortValue(); + dstEndPort = dstStartPort; + if (qosExtClassifier.getDstPortEnd() != null) { + dstEndPort = qosExtClassifier.getDstPortEnd().getValue().shortValue(); + } + if (dstStartPort > dstEndPort) { + logger.warn("Start port %d > End port %d in ext-classifier destination port range -- forcing to same", + dstStartPort, dstEndPort); + dstEndPort = dstStartPort; + } + } + + // DSCP/TOP byte + // TODO - try to make these two variables immutable + byte tosOverwrite = 0; + byte tosMask = (byte)0x00; + if (qosExtClassifier.getTosByte() != null) { + // OR in the DSCP/TOS enable bit 0x01 + tosOverwrite = (byte) (qosExtClassifier.getTosByte().getValue().byteValue() | 0x01); + if (qosExtClassifier.getTosMask() != null) { + tosMask = qosExtClassifier.getTosMask().getValue().byteValue(); + } else { + // set default TOS mask + tosMask = (byte) 0xff; + } + } + + // TODO - find out what the classifier ID should really be. It was never getting set previously + final short classifierId = (short)0; + + // TODO - find out what the action value should really be. It was never getting set previously + final byte action = (byte)0; + + // push the extended classifier to the gate request + classifier = new org.pcmm.gates.impl.ExtendedClassifier(protocol, tosOverwrite, tosMask, + getInet4Address(qosExtClassifier.getSrcIp()), getInet4Address(qosExtClassifier.getDstIp()), + srcStartPort, dstStartPort, priority, getInet4Address(qosExtClassifier.getSrcIpMask()), + getInet4Address(qosExtClassifier.getDstIpMask()), srcEndPort, dstEndPort, classifierId, activationState, + action); + } + + private Inet4Address getInet4Address( + final org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address address) { + if (address != null) { + final InetAddress out = getByName(address.getValue()); + if (out != null && out instanceof Inet4Address) { + return (Inet4Address) out; + } + } + return null; + } + + public void build(final Ipv6Classifier qosIpv6Classifier) { + // Next Header + final short nextHdr; + if (qosIpv6Classifier.getNextHdr() != null) { + nextHdr = qosIpv6Classifier.getNextHdr().getValue().shortValue(); + } + // default: match any nextHdr is 256 because nextHdr 0 is Hop-by-Hop option + else { + nextHdr = (short) 256; + } + + // Source IPv6 address & prefix len + // TODO - try to make these two variables immutable + byte srcPrefixLen = (byte) 128; + Inet6Address srcAddress = null; + if (qosIpv6Classifier.getSrcIp6() != null) { + String[] parts = qosIpv6Classifier.getSrcIp6().getValue().split("/"); + String Ipv6AddressStr = parts[0]; + srcAddress = (Inet6Address) getByName(Ipv6AddressStr); + if (parts.length > 1) { + srcPrefixLen = (byte) Integer.parseInt(parts[1]); + } else { + srcPrefixLen = (byte) 128; + } + + } + + // TODO - try to make these two variables immutable + Inet6Address dstAddress = null; + byte dstPrefLen = (byte) 128; + // Destination IPv6 address & prefix len + if (qosIpv6Classifier.getDstIp6() != null) { + final String[] parts = qosIpv6Classifier.getDstIp6().getValue().split("/"); + final String Ipv6AddressStr = parts[0]; + dstAddress = (Inet6Address)getByName(Ipv6AddressStr); + if (parts.length > 1) dstPrefLen = (byte) Integer.parseInt(parts[1]); + else dstPrefLen = (byte) 128; + } + + // 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 srcPortBegin = (short) 0; + short srcPortEnd = (short) 65535; + if (qosIpv6Classifier.getSrcPortStart() != null) { + srcPortBegin = qosIpv6Classifier.getSrcPortStart().getValue().shortValue(); + srcPortEnd = srcPortBegin; + if (qosIpv6Classifier.getSrcPortEnd() != null) { + srcPortEnd = qosIpv6Classifier.getSrcPortEnd().getValue().shortValue(); + } + if (srcPortBegin > srcPortEnd) { + logger.warn("Start port %d > End port %d in ipv6-classifier source port range -- forcing to same", + srcPortBegin, srcPortEnd); + srcPortEnd = srcPortBegin; + } + } + + // 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 + short dstPortBegin = (short) 0; + short dstPortEnd = (short) 65535; + if (qosIpv6Classifier.getDstPortStart() != null) { + dstPortBegin = qosIpv6Classifier.getDstPortStart().getValue().shortValue(); + dstPortEnd = dstPortBegin; + if (qosIpv6Classifier.getDstPortEnd() != null) { + dstPortEnd = qosIpv6Classifier.getDstPortEnd().getValue().shortValue(); + } + if (dstPortBegin > dstPortEnd) { + logger.warn("Start port %d > End port %d in ipv6-classifier destination port range -- forcing to same", + dstPortBegin, dstPortEnd); + dstPortEnd = dstPortBegin; + } + } + + final byte tcLow; + if (qosIpv6Classifier.getTcLow() != null) + tcLow = qosIpv6Classifier.getTcLow().getValue().byteValue(); + else tcLow = (byte) 0x00; + + final byte tcHigh; + if (qosIpv6Classifier.getTcHigh() != null) + tcHigh = qosIpv6Classifier.getTcHigh().getValue().byteValue(); + else tcHigh = (byte) 0x00; + + final byte tcMask; + if (qosIpv6Classifier.getTcHigh() != null) + tcMask = qosIpv6Classifier.getTcHigh().getValue().byteValue(); + else if (qosIpv6Classifier.getTcLow() != null) tcMask = (byte) 0xff; + else tcMask = (byte) 0x00; + + // TODO - find out what the classifier ID should really be. It was never getting set previously + final short classifierId = (short)0; + + // TODO - find out what the action value should really be. It was never getting set previously + final byte action = (byte)0; + + // push the IPv6 classifier to the gate request + classifier = new org.pcmm.gates.impl.IPv6Classifier(srcAddress, dstAddress, srcPortBegin, dstPortBegin, + (byte) 64, srcPortEnd, dstPortEnd, classifierId, ActivationState.ACTIVE, action, FlowLabel.VALID, tcLow, + tcHigh, tcMask, qosIpv6Classifier.getFlowLabel().intValue(), nextHdr, srcPrefixLen, dstPrefLen); + } } diff --git a/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java b/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java index 12a609b..55b9e6e 100644 --- a/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java +++ b/packetcable-policy-server/src/test/java/org/opendaylight/controller/packetcable/provider/PCMMServiceTest.java @@ -104,7 +104,7 @@ public class PCMMServiceTest { dstAddr = new Ipv4Address("10.32.99.99"); if (realCmts) { - cmAddrInet = InetAddress.getByAddress(new byte[] {10, 32, 110, (byte)180}); + cmAddrInet = InetAddress.getByAddress(new byte[] {10, 32, 110, (byte)172}); invalidCmAddrInet = InetAddress.getByAddress(new byte[] {99, 99, 99, 99}); // Use me when testing against a CMTS or emulator not running in the same JVM @@ -150,12 +150,15 @@ public class PCMMServiceTest { @Test public void testAddInvalidCcapBadPort() { - ccap = makeCcapsObj((icmts.getPort() + 1), cmtsAddr, ccapId); + final int port; + if (icmts != null) port = icmts.getPort() + 1; + else port = PCMMPdpAgent.WELL_KNOWN_PDP_PORT + 1; + ccap = makeCcapsObj(port, cmtsAddr, ccapId); service = new PCMMService(IPCMMClient.CLIENT_TYPE, ccap); final String message = service.addCcap(); Assert.assertNotNull(message); final String expectedMsg = "404 Not Found - CCAP " + ccapId + " failed to connect @ " + cmtsAddr.getValue() - + ':' + (icmts.getPort() + 1) + " - "; + + ':' + port + " - "; Assert.assertTrue(expectedMsg, message.startsWith(expectedMsg)); } @@ -413,7 +416,9 @@ public class PCMMServiceTest { 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); + + // TODO - Can this value be any other value than 0 or 1 (See TosByte enumeration) + final TosByte tosByte = new TosByte((short)0); Mockito.when(classifier.getTosByte()).thenReturn(tosByte); final TosByte tosMask = new TosByte((short)224); Mockito.when(classifier.getTosMask()).thenReturn(tosMask);