Implemented most relevant features of the ModemCapabilitiesEncoding

This commit is contained in:
feyris-tan 2025-05-19 20:35:42 +02:00
parent 76386bad33
commit 0d0268509d
4 changed files with 482 additions and 1 deletions

View File

@ -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; }
}
}

View File

@ -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,
}
}
}

View File

@ -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; }
}
}

View File

@ -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
}
}