diff --git a/skyscraper8/Docsis/AnnexC/ChannelSubcarrierQamModulationSupport.cs b/skyscraper8/Docsis/AnnexC/ChannelSubcarrierQamModulationSupport.cs new file mode 100644 index 0000000..df9e7df --- /dev/null +++ b/skyscraper8/Docsis/AnnexC/ChannelSubcarrierQamModulationSupport.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace skyscraper8.Docsis.AnnexC +{ + public class ChannelSubcarrierQamModulationSupport + { + public ChannelSubcarrierQamModulationSupport(byte a, byte b) + { + QPSK = (b & 0x04) != 0; + _8QAM = (b & 0x08) != 0; + _16QAM = (b & 0x10) != 0; + _32QAM = (b & 0x20) != 0; + _64QAM = (b & 0x40) != 0; + _128QAM = (b & 0x80) != 0; + _256QAM = (a & 0x01) != 0; + _512QAM = (a & 0x02) != 0; + _1024QAM = (a & 0x04) != 0; + _2048QAM = (a & 0x08) != 0; + _4096QAM = (a & 0x10) != 0; + _8192QAM = (a & 0x20) != 0; + _16384QAM = (a & 0x40) != 0; + } + + public bool QPSK { get; } + public bool _8QAM { get; } + public bool _16QAM { get; } + public bool _32QAM { get; } + public bool _64QAM { get; } + public bool _128QAM { get; } + public bool _256QAM { get; } + public bool _512QAM { get; } + public bool _1024QAM { get; } + public bool _2048QAM { get; } + public bool _4096QAM { get; } + public bool _8192QAM { get; } + public bool _16384QAM { get; } + } +} diff --git a/skyscraper8/Docsis/AnnexC/ModemCapabilitiesEncoding.cs b/skyscraper8/Docsis/AnnexC/ModemCapabilitiesEncoding.cs index f09e511..94777e4 100644 --- a/skyscraper8/Docsis/AnnexC/ModemCapabilitiesEncoding.cs +++ b/skyscraper8/Docsis/AnnexC/ModemCapabilitiesEncoding.cs @@ -1,13 +1,23 @@ using System; using System.IO; +using System.Runtime.Intrinsics.Arm; using skyscraper5.Skyscraper; using skyscraper5.Skyscraper.IO; +using skyscraper8.Docsis.AnnexC; +using skyscraper8.Docsis.L2VPN; namespace skyscraper5.Docsis.AnnexC { public class ModemCapabilitiesEncoding : Validatable { - public ModemCapabilitiesEncoding(byte[] buffer) + private readonly bool? ExpandedUnicastSidSpace; + private readonly byte? DpvCapability; + private readonly byte EnergyManagementPreference; + private byte? UpstreamScQamSymbolRateSupport; + private byte? _512MspsUpstreamTransmitScQamChannelSupport; + private byte? _256MspsUpstreamTransmitScQamChannelSupport; + + public ModemCapabilitiesEncoding(byte[] buffer) { MemoryStream ms = new MemoryStream(buffer, true); while (ms.GetAvailableBytes() > 2) @@ -31,6 +41,197 @@ namespace skyscraper5.Docsis.AnnexC break; case 6: PrivacySupport = (PrivacySupportValue)v[0]; + break; + case 7: + DownstreamSaidSupport = (byte?)v[0]; + break; + case 8: + UpstreamServiceFlowSupport = (byte?)v[0]; + break; + case 10: + TransmitPreEqualizerTapsPerModulationInterval = (byte?)v[0]; + break; + case 11: + NumberOfTransmitEqualizerTaps = (byte?)v[0]; + break; + case 12: + DccSupport = (bool?)((v[0] & 0x01) == 1); + break; + case 15: + ExpandedUnicastSidSpace = (bool?)((v[0] & 0x01) == 1); + break; + case 16: + this.RangingHoldOffSupport = new RangingHoldOffSupport(v[0], v[1], v[2], v[3]); + break; + case 17: + //This is guesswork, I don't have "CM-SP-L2VPN-I15-150528" + L2VPN = (bool?)((v[0] & 0x01) == 1); + break; + case 18: + this.ESafeHostCapability = new ESafeHostCapability(v); + break; + case 19: + this.DownstreamUnencryptedTrafficFiltering = (bool?)((v[0] & 0x01) == 1); + break; + case 20: + UpstreamFrequencyRangeSupport = (UpstreamFrequencyRangeSupportEnum)v[0]; + break; + case 21: + UpstreamScQamSymbolRateSupport = v[0]; + break; + case 22: + SelectableActiveCodeMode2Support = v[0] == 1; + break; + case 23: + CodeHoppingMode2Support = (bool?)(v[0] == 1); + break; + case 24: + ScQamMultipleTransmitChannelSupport = (byte?)v[0]; + break; + case 25: + _512MspsUpstreamTransmitScQamChannelSupport = (byte?)v[0]; + break; + case 26: + _256MspsUpstreamTransmitScQamChannelSupport = (byte?)v[0]; + break; + case 27: + TotalSidClusterSupport = (byte?)v[0]; + break; + case 28: + SidClustersPerServiceFlowSupport = (byte?)v[0]; + break; + case 29: + ScQamMultipleReceiveChannelSupport = (byte?)v[0]; + break; + case 30: + TotalDsidSupport = (byte?)v[0]; + break; + case 31: + ResequencingDsidSupport = (byte?)v[0]; + break; + case 32: + MulticastDsidSupport = (byte?)v[0]; + break; + case 33: + MulticastDsidForwarding = (MulticastDsidForwardingEnum?)v[0]; + break; + case 34: + FrameControlTypeForwardingCapability = (bool?)(v[0] == 1); + break; + case 35: + DpvCapability = (byte?)v[0]; + break; + case 36: + UnsolicitedGrantServiceFlowSupport = (byte?)v[0]; + break; + case 37: + MapAndUcdReceiptSupport = (bool?)((v[0] & 0x01) != 1); + break; + case 38: + (v[0], v[1]) = (v[1], v[0]); + UpstreamDropClassifierSupport = BitConverter.ToUInt16(v, 0); + break; + case 39: + Ipv6Support = (bool?)(v[0] == 1); + break; + case 40: + ExtendedUpstreamTransmitPowerCapability = (byte?)v[0]; + break; + case 44: + //Additions and Modifications for Chinese Specification + //I don't have this document. + break; + case 46: + CmStatusAck = (bool?)(v[0] == 1); + break; + case 47: + EnergyManagementPreference = v[3]; + break; + case 48: + (v[0], v[1]) = (v[1], v[0]); + ExtendedPacketLengthSupportCapability = BitConverter.ToUInt16(v, 0); + break; + case 49: + OfdmMultipleReceiveChannelSupport = (byte?)v[0]; + break; + case 50: + OfdmaMultipleTransmitChannelSupport = (byte?)v[0]; + break; + case 51: + DownstreamOfdmProfileSupport = (byte?)v[0]; + break; + case 52: + this.DownstreamOfdmChannelSubcarrierQamModulationSupport = new ChannelSubcarrierQamModulationSupport(v[0], v[1]); + break; + case 53: + this.UpstreamOfdmaChannelSubcarrierQamModulationSupport = new ChannelSubcarrierQamModulationSupport(v[0], v[1]); + break; + case 54: + if (v[0] == 0x01) + DownstreamFrequencyRangeStarting = 108; + else if (v[0] == 0x02) + DownstreamFrequencyRangeStarting = 258; + break; + case 55: + if (v[0] == 0x01) + DownstreamFrequencyRangeUpTo = 1218; + else if (v[0] == 0x02) + DownstreamFrequencyRangeUpTo = 1794; + else if (v[0] == 0x04) + DownstreamFrequencyRangeUpTo = 1002; + break; + case 56: + if (v[0] == 0) + UpstreamFrequencyRangeUpTo = 42; + else if (v[0] == 1) + UpstreamFrequencyRangeUpTo = 65; + else if (v[0] == 2) + UpstreamFrequencyRangeUpTo = 85; + else if (v[0] == 3) + UpstreamFrequencyRangeUpTo = 117; + else if (v[0] == 4) + UpstreamFrequencyRangeUpTo = 204; + break; + case 57: + DocsisTimeProtocolMode = (DtpMode?)v[0]; + break; + case 58: + DocsisTimeProtocolPerformanceSupport = (DtpPerformanceSupport?)v[0]; + break; + case 59: + (v[0], v[1]) = (v[1], v[0]); + Pmax = BitConverter.ToUInt16(v, 0); + break; + case 60: + if (v[0] == 0x01) + DownstreamFrequencyRangeStarting = 108; + else if (v[0] == 0x02) + DownstreamFrequencyRangeStarting = 258; + else if (v[0] == 0x003) + DownstreamFullDuplex = true; + break; + case 61: + if (v[0] == 0x01) + DownstreamFrequencyRangeUpTo = 1218; + else if (v[0] == 0x02) + DownstreamFrequencyRangeUpTo = 1794; + else if (v[0] == 0x04) + DownstreamFrequencyRangeUpTo = 1002; + break; + case 62: + if (v[0] == 0) + UpstreamFrequencyRangeUpTo = 42; + else if (v[0] == 1) + UpstreamFrequencyRangeUpTo = 65; + else if (v[0] == 2) + UpstreamFrequencyRangeUpTo = 85; + else if (v[0] == 3) + UpstreamFrequencyRangeUpTo = 117; + else if (v[0] == 4) + UpstreamFrequencyRangeUpTo = 204; + break; + case 76: + LowLatencySupport = (byte?)v[0]; break; default: //CM-SP-MULPIv4.0-I01-190815.pdf, page 688 @@ -62,11 +263,188 @@ namespace skyscraper5.Docsis.AnnexC public bool? FragmentationSupport { get; } public bool? PayloadHeaderSuppressionSupport { get; } public PrivacySupportValue? PrivacySupport { get; } + public byte? DownstreamSaidSupport { get; } + public byte? UpstreamServiceFlowSupport { get; } + public byte? TransmitPreEqualizerTapsPerModulationInterval { get; } + public byte? NumberOfTransmitEqualizerTaps { get; } + public bool? DccSupport { get; } + internal RangingHoldOffSupport RangingHoldOffSupport { get; } + public bool? L2VPN { get; } + public ESafeHostCapability ESafeHostCapability { get; } + public bool? DownstreamUnencryptedTrafficFiltering { get; } + public UpstreamFrequencyRangeSupportEnum? UpstreamFrequencyRangeSupport { get; } public enum PrivacySupportValue : byte { BpiSupport = 0, BpiPlusSupport = 1 } + + public enum UpstreamFrequencyRangeSupportEnum : byte + { + Standard = 0, + Upstream = 1, + Extended = 2 + } + + public bool _160kspsSymbolRateSupport + { + get + { + if (!UpstreamScQamSymbolRateSupport.HasValue) + return true; + return (UpstreamScQamSymbolRateSupport & 0x01) != 0; + } + } + + public bool _320kspsSymbolRateSupport + { + get + { + if (!UpstreamScQamSymbolRateSupport.HasValue) + return true; + return (UpstreamScQamSymbolRateSupport & 0x02) != 0; + } + } + + public bool _640kspsSymbolRateSupport + { + get + { + if (!UpstreamScQamSymbolRateSupport.HasValue) + return true; + return (UpstreamScQamSymbolRateSupport & 0x04) != 0; + } + } + + public bool _1280kspsSymbolRateSupport + { + get + { + if (!UpstreamScQamSymbolRateSupport.HasValue) + return true; + return (UpstreamScQamSymbolRateSupport & 0x08) != 0; + } + } + + public bool _2560kspsSymbolRateSupport + { + get + { + if (!UpstreamScQamSymbolRateSupport.HasValue) + return true; + return (UpstreamScQamSymbolRateSupport & 0x10) != 0; + } + } + + public bool _5120kspsSymbolRateSupport + { + get + { + if (!UpstreamScQamSymbolRateSupport.HasValue) + return true; + return (UpstreamScQamSymbolRateSupport & 0x20) != 0; + } + } + + public bool? SelectableActiveCodeMode2Support { get; } + public bool? CodeHoppingMode2Support { get; } + public byte? ScQamMultipleTransmitChannelSupport { get; } + public byte? TotalSidClusterSupport { get; } + public byte? SidClustersPerServiceFlowSupport { get; } + public byte? ScQamMultipleReceiveChannelSupport { get; } + public byte? TotalDsidSupport { get; } + public byte? ResequencingDsidSupport { get; private set; } + public byte? MulticastDsidSupport { get; } + public MulticastDsidForwardingEnum? MulticastDsidForwarding { get; } + public bool? FrameControlTypeForwardingCapability { get; } + + public enum MulticastDsidForwardingEnum : byte + { + NoSupport, + SupportExplicit, + SupportPromiscious + } + + public bool? DpvPerPathSuppported + { + get + { + if (DpvCapability == null) + return null; + return (DpvCapability & 0x01) != 0; + } + } + + public bool? DpvPerPacketSuppported + { + get + { + if (DpvCapability == null) + return null; + return (DpvCapability & 0x02) != 0; + } + } + + public byte? UnsolicitedGrantServiceFlowSupport { get; } + public bool? MapAndUcdReceiptSupport { get; } + public ushort UpstreamDropClassifierSupport { get; } + public bool? Ipv6Support { get; } + public byte? ExtendedUpstreamTransmitPowerCapability { get; } + public bool? CmStatusAck { get; } + + public bool? EnergyManagement1x1Feature + { + get + { + if (EnergyManagementPreference == null) + return null; + return (EnergyManagementPreference & 0x01) != 0; + } + } + + public bool? DocsisLightSleepMode + { + get + { + if (EnergyManagementPreference == null) + return null; + return (EnergyManagementPreference & 0x02) != 0; + } + } + + public ushort ExtendedPacketLengthSupportCapability { get; } + public byte? OfdmMultipleReceiveChannelSupport { get; } + public byte? OfdmaMultipleTransmitChannelSupport { get; } + public byte? DownstreamOfdmProfileSupport { get; } + public ChannelSubcarrierQamModulationSupport DownstreamOfdmChannelSubcarrierQamModulationSupport { get; } + public ChannelSubcarrierQamModulationSupport UpstreamOfdmaChannelSubcarrierQamModulationSupport { get; } + public int DownstreamFrequencyRangeStarting { get; } + public int DownstreamFrequencyRangeUpTo { get; } + public int UpstreamFrequencyRangeUpTo { get; } + public DtpMode? DocsisTimeProtocolMode { get; } + public DtpPerformanceSupport? DocsisTimeProtocolPerformanceSupport { get; } + public ushort Pmax { get; } + public bool DownstreamFullDuplex { get; } + public byte? LowLatencySupport { get; } + + public enum DtpMode : byte + { + NotSupported = 0, + SlaveOnly = 1, + MasterOnly = 2, + MasterOrSlave = 3 + } + + public enum DtpPerformanceSupport : byte + { + NotSupported = 0, + Level1 = 1, + Level2 = 2, + Level3 = 3, + Level4 = 4, + Level5 = 5, + NoSpecifiedPerformance = 6, + } } } diff --git a/skyscraper8/Docsis/AnnexC/RangingHoldOffSupport.cs b/skyscraper8/Docsis/AnnexC/RangingHoldOffSupport.cs new file mode 100644 index 0000000..ed361d3 --- /dev/null +++ b/skyscraper8/Docsis/AnnexC/RangingHoldOffSupport.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace skyscraper8.Docsis.AnnexC +{ + internal class RangingHoldOffSupport + { + public RangingHoldOffSupport(byte a, byte b, byte c, byte d) + { + CmRangingClassIdExtension = a; + CmRangingClassIdExtension <<= 8; + CmRangingClassIdExtension += b; + + Cm = ((d & 0x01) != 0); + ERouter = ((d & 0x02) != 0); + EMtaOrEDva = ((d & 0x04) != 0); + DsgEStb = ((d & 0x08) != 0); + } + + public ushort CmRangingClassIdExtension { get; private set; } + public bool Cm { get; } + public bool ERouter { get; } + public bool EMtaOrEDva { get; } + public bool DsgEStb { get; } + } +} diff --git a/skyscraper8/Docsis/L2VPN/ESafeHostCapability.cs b/skyscraper8/Docsis/L2VPN/ESafeHostCapability.cs new file mode 100644 index 0000000..22b0e25 --- /dev/null +++ b/skyscraper8/Docsis/L2VPN/ESafeHostCapability.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading.Tasks; + +namespace skyscraper8.Docsis.L2VPN +{ + public class ESafeHostCapability + { + public ESafeHostCapability(byte[] buffer) + { + ESafeIfIndex = (ESafeIfIndex)buffer[0]; + + byte[] macBuffer = new byte[6]; + Array.Copy(buffer, 1, macBuffer, 0, 6); + ESafeMacAddress = new PhysicalAddress(macBuffer); + } + + public ESafeIfIndex ESafeIfIndex { get; private set; } + public PhysicalAddress ESafeMacAddress { get; private set; } + } + + public enum ESafeIfIndex : byte + { + ERouter = 1, + EMta = 16, + EStbIp = 17, + ETea = 19 + } +}