KLALB V3.6.0 写了一半

This commit is contained in:
Administrator
2026-02-27 08:32:03 +08:00
parent 816e672843
commit 620afef715
164 changed files with 8381 additions and 13495 deletions
+4 -7
View File
@@ -1,16 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/graalvm-jdk-23.0.1+11.1">
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/graalvm-jdk-25.0.1+8.1">
<attributes>
<attribute name="module" value="true"/>
<attribute name="add-exports" value="java.base/jdk.internal.misc=ALL-UNNAMED:java.base/jdk.internal.foreign=ALL-UNNAMED"/>
<attribute name="add-opens" value="java.base/jdk.internal.misc=ALL-UNNAMED:java.base/jdk.internal.foreign=ALL-UNNAMED"/>
</attributes>
<accessrules>
<accessrule kind="accessible" pattern="**"/>
<accessrule kind="accessible" pattern="jdk/internal/misc/*"/>
</accessrules>
</classpathentry>
<classpathentry kind="lib" path="lib/gson-2.1.jar"/>
<classpathentry kind="lib" path="lib/javassist.jar" sourcepath="C:/Users/ADMINI~1/AppData/Local/Temp/1/.org.sf.feeling.decompiler1686963856070/source/javassist-3.29.2-GA-sources.jar"/>
@@ -28,7 +23,9 @@
<classpathentry kind="lib" path="lib/disruptor-4.0.0.jar" sourcepath="lib/disruptor-4.0.0-sources.jar"/>
<classpathentry kind="lib" path="lib/disruptor-4.0.0-javadoc.jar"/>
<classpathentry kind="lib" path="lib/disruptor-4.0.0-sources.jar"/>
<classpathentry kind="lib" path="lib/JavaTUN.jar"/>
<classpathentry kind="lib" path="lib/KNElib1.0.jar"/>
<classpathentry kind="lib" path="lib/KNEOptimize.jar"/>
<classpathentry kind="lib" path="lib/JavaTUN0.3.jar"/>
<classpathentry kind="lib" path="lib/uuid-creator-6.1.1.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-2420
View File
File diff suppressed because it is too large Load Diff
View File
-2180
View File
File diff suppressed because it is too large Load Diff
View File
+22 -2
View File
@@ -1,7 +1,7 @@
[
{
"language": "ZH_CN",
"nogui": false,
"nogui": true,
"VirtualAddress": "2486:1:0:0:0:0:0:8888",
"VirtualASN": 2142606939373348329,
"DNS": [
@@ -15,7 +15,8 @@
],
"ConnectLineTable": [
"home-ipv6.sliveridc1.cn:4565",
"home-ltipv6.sliveridc1.cn:4565"
"home-ltipv6.sliveridc1.cn:4565",
"cn-gd-gz.sliveridc1.cn:4565"
],
"ntpServerTable": [
"{UDP}ntp1.aliyun.com:123",
@@ -36,6 +37,15 @@
"{UDP}ntp.ntsc.ac.cn:123",
"{UDP}us.ntp.org.cn:123"
],
"denyLineTableQuery": false,
"denyLineTableBroadcast": false,
"congestionAlgorithm": "BBR",
"delayUpperBound": 1.506,
"delayLowerBound": 1.25,
"nagleDelayTime": 1000000,
"linkNagleDelayTime": 1000000,
"linkConnectionsCount": 1,
"TUNName": "KLALB_SRv6",
"NetworkInterfaceExcepts": [],
"Type": "KLALBController"
},
@@ -77,6 +87,16 @@
},
"Type": "SocketBridge"
},
{
"Listen": "{KLALB_Stream}[::0]:25565",
"Bridge": {
"DEFAULT": "SocketBridge"
},
"Connect": {
"DEFAULT": "127.0.0.1:25566"
},
"Type": "SocketBridge"
},
{
"Listen": "0.0.0.0:25561",
"Bridge": {
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

+17 -1
View File
@@ -76,4 +76,20 @@ ntpservers=NTP server addresses
nodeinfo=Node information
basicinfo=Basic info
overview=Overview
timerange=Time range
timerange=Time range
error=Error
securitysettings=Security settings
delayupperbound=Delay upper bound
delaylowerbound=Delay lower bound
denyaddrquery=Deny address query
denyaddrbroadcast=Deny address broadcast
random=Random
transmitnagledelaytime=Transmit nagle delay time
linknagledelaytime=Link nagle delay time
linkconnectionscount=Link connections count
tunname=Virtual network device name
dashboard=Dashboard
backplanedelay=Backplane delay
backplanepps=Backplane PPS
uisettings=UI settings
nogui=No GUI mode
+17 -1
View File
@@ -76,4 +76,20 @@ ntpservers=NTP授时服务器地址
nodeinfo=节点信息
basicinfo=基本信息
overview=概览
timerange=时间范围
timerange=时间范围
error=错误
securitysettings=安全设置
delayupperbound=网络时延上限
delaylowerbound=网络时延下限
denyaddrquery=禁用IP地址查询
denyaddrbroadcast=禁用IP地址广播
random=随机
transmitnagledelaytime=传输粘包等待时间
linknagledelaytime=链路粘包等待时间
linkconnectionscount=链路连接数
tunname=虚拟网卡名称
dashboard=仪表盘
backplanedelay=背板处理延迟
backplanepps=背板包转发率
uisettings=UI设置
nogui=无GUI模式
+25 -16
View File
@@ -17,24 +17,26 @@ public class HighAccuracyClock {
private final long initialCPUNanoTime;
private final Long128 initialSystemNanoTime;
private volatile AtomicLong baseCPUNanoTime=new AtomicLong();
private volatile long baseCPUNanoTime;
private volatile Long128 baseSystemNanoTime;
private volatile long frequency=1000000000;//1000015000
private volatile long frequency2=frequency*0xffffffffL/1000000000L;
private ReentrantLock lock=new ReentrantLock();
private static final Long128 NANOS_PER_MILLIS = Long128.valueOf(TimeUnit.MILLISECONDS.toNanos(1));
private static final Long128 NANOS_PER_SECONDS = Long128.valueOf(TimeUnit.SECONDS.toNanos(1));
public static final HighAccuracyClock SYSTEM_CLOCK = new HighAccuracyClock();
public HighAccuracyClock() {
this.initialSystemNanoTime =Long128.valueOf( System.currentTimeMillis() ).multiply(NANOS_PER_MILLIS);
this.initialCPUNanoTime = System.nanoTime();
this.baseSystemNanoTime=initialSystemNanoTime;
this.baseCPUNanoTime.set(initialCPUNanoTime);
this.baseCPUNanoTime=initialCPUNanoTime;
}
public long getFrequency() {
@@ -45,9 +47,11 @@ public class HighAccuracyClock {
lock.lock();
try {
long curr=System.nanoTime();
long nanoela=curr-baseCPUNanoTime.getAndSet(curr);
long nanoela=curr-baseCPUNanoTime;
baseCPUNanoTime=curr;
baseSystemNanoTime=baseSystemNanoTime.add( Long128.valueOf(nanoela).multiply(this.frequency).divide(NANOS_PER_SECONDS));
this.frequency = frequency;
this.frequency2=frequency*0xffffffffL/1000000000L;
}finally {
lock.unlock();
}
@@ -59,6 +63,7 @@ public class HighAccuracyClock {
try {
compact();
this.frequency = frequency+fdelta;
this.frequency2=frequency*0xffffffffL/1000000000L;
}finally {
lock.unlock();
}
@@ -69,7 +74,8 @@ public class HighAccuracyClock {
lock.lock();
try {
long curr=System.nanoTime();
long nanoela=curr-baseCPUNanoTime.getAndSet(curr);
long nanoela=curr-baseCPUNanoTime;
baseCPUNanoTime=curr;
baseSystemNanoTime=baseSystemNanoTime.add(Long128.valueOf(nanoela).multiply(this.frequency).divide(NANOS_PER_SECONDS));
}finally {
lock.unlock();
@@ -80,12 +86,8 @@ public class HighAccuracyClock {
* 获取从1970-01-01开始的当前时间(纳秒精度)
*/
public Long128 getCurrentTimeNanos() {
Long128 mul=Long128.valueOf(System.nanoTime()-baseCPUNanoTime.get()).multiply(frequency);
if(mul.getHigh()!=0) {
compact();
mul=Long128.valueOf(System.nanoTime()-baseCPUNanoTime.get()).multiply(frequency);
}
return mul.divide(NANOS_PER_SECONDS).add(baseSystemNanoTime);
Long128 mul=Long128.valueOf(System.nanoTime()-baseCPUNanoTime).multiply(frequency2);
return mul.shiftRight(32).add(baseSystemNanoTime);
}
/**
@@ -98,14 +100,14 @@ public class HighAccuracyClock {
/**
* 获取 NTPv4 128 位时间戳
*/
public BigInteger getCurrentTimeNTP128() {
public Long128 getCurrentTimeNTP128() {
return NTPTimestamps.nanosToNtp128BitTimestamp(getCurrentTimeNanos());
}
/**
* 获取 NTPv4 64 位时间戳
*/
public BigInteger getCurrentTimeNTP64() {
public Long128 getCurrentTimeNTP64() {
return NTPTimestamps.ntp128To64(getCurrentTimeNTP128());
}
@@ -125,7 +127,7 @@ public class HighAccuracyClock {
public void syncToTime(Long128 targetNanos) {
lock.lock();
try {
baseCPUNanoTime.set( System.nanoTime());
baseCPUNanoTime= System.nanoTime();
baseSystemNanoTime=targetNanos;
}finally {
lock.unlock();
@@ -152,7 +154,7 @@ public class HighAccuracyClock {
}
lock.lock();
try {
baseCPUNanoTime.set( System.nanoTime());
baseCPUNanoTime=System.nanoTime();
baseSystemNanoTime=referenceClock.getCurrentTimeNanos();
}finally {
lock.unlock();
@@ -163,7 +165,7 @@ public class HighAccuracyClock {
* 基于NTP时间戳同步
* @param ntp128Timestamp NTP 128位时间戳
*/
public void syncToNTPTime(BigInteger ntp128Timestamp) {
public void syncToNTPTime(Long128 ntp128Timestamp) {
Long128 targetNanos = NTPTimestamps.ntp128BitToNanosTimestamp(ntp128Timestamp);
syncToTime(targetNanos);
}
@@ -226,6 +228,11 @@ public class HighAccuracyClock {
Long128 nanos = getCurrentTimeNanos();
return NTPTimestamps.nanosSince1970ToString(nanos);
}
public String toString2() {
Long128 nanos = getCurrentTimeNanos();
return NTPTimestamps.nanosSince1970ToString2(nanos);
}
public long getInitialCPUNanoTime() {
return initialCPUNanoTime;
@@ -244,6 +251,8 @@ public class HighAccuracyClock {
Thread.sleep(1000);
}
}
}
+60 -168
View File
@@ -1,6 +1,5 @@
package org.kne.cloud.clock;
import java.math.BigInteger;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
@@ -12,29 +11,30 @@ import org.kne.math.Long128;
public class NTPTimestamps {
// 常量定义
public static final BigInteger NANOS_PER_SECOND = BigInteger.valueOf(1_000_000_000L);
public static final BigInteger NANOS_PER_MILLIS = BigInteger.valueOf(1_000_000L);
public static final Long128 NANOS_PER_SECOND = Long128.valueOf(1_000_000_000L);
public static final Long128 NANOS_PER_MILLIS = Long128.valueOf(1_000_000L);
// NTP 纪元 (1900) 和 Unix 纪元 (1970) 之间的纳秒差
public static final BigInteger NTP_EPOCH_OFFSET_NS = BigInteger.valueOf(2208988800L)
public static final Long128 NTP_EPOCH_OFFSET_NS = Long128.valueOf(2208988800L)
.multiply(NANOS_PER_SECOND);
// 2^64 值,用于单位转换
public static final BigInteger TWO_POW_64 = BigInteger.ONE.shiftLeft(64);
public static final Long128 TWO_POW_64 = Long128.ONE.shiftLeft(64);
// 2^32 值,用于 64 位时间戳处理
public static final BigInteger TWO_POW_32 = BigInteger.ONE.shiftLeft(32);
public static final Long128 TWO_POW_32 = Long128.ONE.shiftLeft(32);
// 掩码常量
public static final BigInteger MASK_32_BIT = new BigInteger("FFFFFFFF", 16);
public static final BigInteger MASK_64_BIT = new BigInteger("FFFFFFFFFFFFFFFF", 16);
public static final Long128 MASK_32_BIT = new Long128(0xFFFFFFFF);
public static final Long128 MASK_64_BIT = new Long128(0xFFFFFFFFFFFFFFFFL);
// ================== 核心转换方法 ==================
// 2^32 秒,约 136.192 年,一个 NTP 纪元的长度
public static final BigInteger SECONDS_PER_ERA = BigInteger.valueOf(0x100000000L);
public static final Long128 SECONDS_PER_ERA = Long128.valueOf(0x100000000L);
private static final Long128 TWO_POW_N64_PER_NANOS = Long128.valueOf("1208925819614629");
public static BigInteger inferNtp64To128(long remote64Bit,BigInteger local128Bit ) {
return inferNtp64To128(toUnsignedBigInteger(remote64Bit),local128Bit);
public static Long128 inferNtp64To128(long remote64Bit,Long128 local128Bit ) {
return inferNtp64To128(toUnsignedLong128(remote64Bit),local128Bit);
}
@@ -45,26 +45,26 @@ public class NTPTimestamps {
* @param local128Bit 本地已知的 128 位 NTP 时间戳
* @return 推断出的完整 128 位 NTP 时间戳
*/
public static BigInteger inferNtp64To128(BigInteger remote64Bit,BigInteger local128Bit ) {
public static Long128 inferNtp64To128(Long128 remote64Bit,Long128 local128Bit ) {
// 1. 从本地 128 位时间戳中提取纪元号和 64 位时间戳部分
BigInteger localEra = NTPTimestamps.getEraNumber(local128Bit);
BigInteger local64Bit = NTPTimestamps.getNtp64Timestamp(local128Bit);
Long128 localEra = NTPTimestamps.getEraNumber(local128Bit);
Long128 local64Bit = NTPTimestamps.getNtp64Timestamp(local128Bit);
// 3. 计算本地和远程 64 位时间戳的差异
BigInteger difference = remote64Bit.subtract(local64Bit);
Long128 difference = remote64Bit.subtract(local64Bit);
// 4. 判断纪元关系并推断远程时间戳的纪元
BigInteger remoteEra;
Long128 remoteEra;
// 如果差异很大(超过半个纪元),可能需要调整纪元
BigInteger halfEra = BigInteger.valueOf(Long.MAX_VALUE);
Long128 halfEra = Long128.valueOf(Long.MAX_VALUE);
if (difference.compareTo(halfEra) > 0) {
// 远程时间戳比本地小很多,可能属于上一个纪元
remoteEra = localEra.subtract(BigInteger.ONE);
remoteEra = localEra.subtract(Long128.ONE);
} else if (difference.compareTo(halfEra.negate()) < 0) {
// 远程时间戳比本地大很多,可能属于下一个纪元
remoteEra = localEra.add(BigInteger.ONE);
remoteEra = localEra.add(Long128.ONE);
} else {
// 差异不大,属于同一个纪元
remoteEra = localEra;
@@ -77,35 +77,36 @@ public class NTPTimestamps {
* 将从1970年开始的纳秒数转换为 NTPv4 128 位时间戳
* 128位时间戳表示从1900年1月1日起经过的 2⁻⁶⁴ 秒的数量
*/
public static BigInteger nanosToNtp128BitTimestamp(Long128 nanosSince1970) {
public static Long128 nanosToNtp128BitTimestamp(Long128 nanosSince1970) {
// 1. 计算从 1900 年开始的总纳秒数
BigInteger totalNanosFrom1900 = nanosSince1970.toBigInteger().add(NTP_EPOCH_OFFSET_NS);
Long128 totalNanosFrom1900 = nanosSince1970.add(NTP_EPOCH_OFFSET_NS);
// 2. 将纳秒转换为 2⁻⁶⁴ 秒单位
return totalNanosFrom1900.multiply(TWO_POW_64).divide(NANOS_PER_SECOND);
// return totalNanosFrom1900.multiply(TWO_POW_64).divide(NANOS_PER_SECOND);
return totalNanosFrom1900.multiply(TWO_POW_N64_PER_NANOS).shiftRight(16);
}
/**
* 从 NTPv4 128 位时间戳转换回从1970年开始的纳秒数
*/
public static Long128 ntp128BitToNanosTimestamp(BigInteger ntp128Timestamp) {
public static Long128 ntp128BitToNanosTimestamp(Long128 ntp128Timestamp) {
// 1. 将 2⁻⁶⁴ 秒单位转换回纳秒
BigInteger totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
Long128 totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
// 2. 计算从 1970 年开始的总纳秒数
return Long128.valueOf( totalNanosFrom1900.subtract(NTP_EPOCH_OFFSET_NS));
return totalNanosFrom1900.subtract(NTP_EPOCH_OFFSET_NS);
}
public static BigInteger nanosToNtp128BitTimeInterval(BigInteger nanos) {
public static Long128 nanosToNtp128BitTimeInterval(Long128 nanos) {
// 2. 将纳秒转换为 2⁻⁶⁴ 秒单位
return nanos.multiply(TWO_POW_64).divide(NANOS_PER_SECOND);
}
public static BigInteger ntp128BitToNanosInterval(BigInteger ntp128Timestamp) {
public static Long128 ntp128BitToNanosInterval(Long128 ntp128Timestamp) {
// 1. 将 2⁻⁶⁴ 秒单位转换回纳秒
BigInteger totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
Long128 totalNanosFrom1900 = ntp128Timestamp.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
return totalNanosFrom1900;
}
@@ -117,7 +118,7 @@ public class NTPTimestamps {
* 将 NTP 128 位时间戳转换为 NTP 64 位时间戳
* 64位时间戳就是128位时间戳的中间64位
*/
public static BigInteger ntp128To64(BigInteger ntp128Timestamp) {
public static Long128 ntp128To64(Long128 ntp128Timestamp) {
return ntp128Timestamp.shiftRight(32).and(MASK_64_BIT);
}
@@ -125,14 +126,14 @@ public class NTPTimestamps {
* 将 NTP 64 位时间戳转换为 NTP 128 位时间戳
* 64位时间戳放在128位时间戳的中间64位,高32位Era和低32位分数为0
*/
public static BigInteger ntp64To128(BigInteger ntp64Timestamp) {
public static Long128 ntp64To128(Long128 ntp64Timestamp) {
return ntp64Timestamp.and(MASK_64_BIT).shiftLeft(32);
}
/**
* 将 NTP 64 位时间戳转换为 NTP 128 位时间戳(指定Era Number
*/
public static BigInteger ntp64To128(BigInteger ntp64Timestamp, BigInteger eraNumber) {
public static Long128 ntp64To128(Long128 ntp64Timestamp, Long128 eraNumber) {
return eraNumber.and(MASK_32_BIT).shiftLeft(96)
.or(ntp64Timestamp.and(MASK_64_BIT).shiftLeft(32));
}
@@ -140,48 +141,48 @@ public class NTPTimestamps {
/**
* 从 NTP 128 位时间戳中提取 Era Number(高32位)
*/
public static BigInteger getEraNumber(BigInteger ntp128Timestamp) {
public static Long128 getEraNumber(Long128 ntp128Timestamp) {
return ntp128Timestamp.shiftRight(96).and(MASK_32_BIT);
}
/**
* 从 NTP 128 位时间戳中提取 64 位时间戳(中间64位)
*/
public static BigInteger getNtp64Timestamp(BigInteger ntp128Timestamp) {
public static Long128 getNtp64Timestamp(Long128 ntp128Timestamp) {
return ntp128Timestamp.shiftRight(32).and(MASK_64_BIT);
}
/**
* 从 NTP 128 位时间戳中提取分数部分(低32位)
*/
public static BigInteger getFraction(BigInteger ntp128Timestamp) {
public static Long128 getFraction(Long128 ntp128Timestamp) {
return ntp128Timestamp.and(MASK_32_BIT);
}
// ================== 工具方法 ==================
/**
* 从毫秒和纳秒偏移构造 BigInteger 纳秒
* 从毫秒和纳秒偏移构造 Long128 纳秒
*/
public static Long128 toNanosSince1970(long unixTimeMillis, long nanosOffset) {
return Long128.valueOf(unixTimeMillis)
.multiply(Long128.valueOf( NANOS_PER_MILLIS))
.multiply( NANOS_PER_MILLIS)
.add(Long128.valueOf(nanosOffset));
}
/**
* 从 BigInteger 纳秒提取毫秒和纳秒偏移
* 从 Long128 纳秒提取毫秒和纳秒偏移
*/
public static long[] toMillisAndNanos(Long128 nanosSince1970) {
Long128[] millisAndNanos = nanosSince1970.divideAndRemainder(Long128.valueOf( NANOS_PER_MILLIS));
Long128[] millisAndNanos = nanosSince1970.divideAndRemainder( NANOS_PER_MILLIS);
return new long[]{millisAndNanos[0].longValue(), millisAndNanos[1].longValue()};
}
/**
* 计算两个 128 位时间戳之间的时间差(纳秒)
*/
public static BigInteger calculateTimeDifference(BigInteger timestamp1, BigInteger timestamp2) {
BigInteger diff = timestamp2.subtract(timestamp1);
public static Long128 calculateTimeDifference(Long128 timestamp1, Long128 timestamp2) {
Long128 diff = timestamp2.subtract(timestamp1);
return diff.multiply(NANOS_PER_SECOND).divide(TWO_POW_64);
}
@@ -190,137 +191,20 @@ public class NTPTimestamps {
/**
* 将 64 位 NTP 时间戳分解为秒数和分数
*/
public static BigInteger[] parseNtp64Timestamp(BigInteger ntp64Timestamp) {
BigInteger seconds = ntp64Timestamp.shiftRight(32).and(MASK_32_BIT);
BigInteger fraction = ntp64Timestamp.and(MASK_32_BIT);
return new BigInteger[]{seconds, fraction};
public static Long128[] parseNtp64Timestamp(Long128 ntp64Timestamp) {
Long128 seconds = ntp64Timestamp.shiftRight(32).and(MASK_32_BIT);
Long128 fraction = ntp64Timestamp.and(MASK_32_BIT);
return new Long128[]{seconds, fraction};
}
/**
* 从秒数和分数构建 64 位 NTP 时间戳
*/
public static BigInteger buildNtp64Timestamp(BigInteger seconds, BigInteger fraction) {
public static Long128 buildNtp64Timestamp(Long128 seconds, Long128 fraction) {
return seconds.and(MASK_32_BIT).shiftLeft(32).or(fraction.and(MASK_32_BIT));
}
// ================== 测试代码 ==================
public static void main(String[] args) {
System.out.println("=== NTPv4 128位/64位时间戳转换测试 ===");
// 测试当前时间
testCurrentTime();
// 测试 128位 ↔ 64位 转换
test128To64Conversion();
// 测试 Era Number 处理
testEraNumberHandling();
// 测试边界值
testBoundaryValues();
}
private static void testCurrentTime() {
System.out.println("\n=== 当前时间测试 ===");
Long128 nanosSince1970 = toNanosSince1970(System.currentTimeMillis(), 123456);
BigInteger ntp128 = nanosToNtp128BitTimestamp(nanosSince1970);
BigInteger ntp64 = ntp128To64(ntp128);
System.out.println("从1970年开始的纳秒数: " + nanosSince1970);
System.out.println("NTP 128-bit: 0x" + ntp128.toString(16).toUpperCase());
System.out.println("NTP 64-bit: 0x" + ntp64.toString(16).toUpperCase());
// 反向转换验证
BigInteger recovered128 = ntp64To128(ntp64);
Long128 recoveredNanos = ntp128BitToNanosTimestamp(recovered128);
System.out.println("恢复的纳秒数: " + recoveredNanos);
System.out.println("转换正确: " + (nanosSince1970.equals(recoveredNanos) ? "" : ""));
}
private static void test128To64Conversion() {
System.out.println("\n=== 128位 ↔ 64位 转换测试 ===");
// 创建一个测试用的 128 位时间戳
BigInteger test128 = new BigInteger("EC652B7E912F00B81234567890ABCDEF", 16);
BigInteger ntp64 = ntp128To64(test128);
BigInteger recovered128 = ntp64To128(ntp64);
System.out.println("原始128位: 0x" + test128.toString(16).toUpperCase());
System.out.println("转换64位: 0x" + ntp64.toString(16).toUpperCase());
System.out.println("恢复128位: 0x" + recovered128.toString(16).toUpperCase());
// 验证中间64位相同
BigInteger original64Part = getNtp64Timestamp(test128);
System.out.println("转换正确: " + (original64Part.equals(ntp64) ? "" : ""));
}
private static void testEraNumberHandling() {
System.out.println("\n=== Era Number 处理测试 ===");
BigInteger ntp64 = new BigInteger("EC652B7E912F00B8", 16);
BigInteger eraNumber = new BigInteger("1", 16); // Era 1
BigInteger ntp128WithEra = ntp64To128(ntp64, eraNumber);
BigInteger extractedEra = getEraNumber(ntp128WithEra);
BigInteger extracted64 = getNtp64Timestamp(ntp128WithEra);
System.out.println("设置 Era: 0x" + eraNumber.toString(16).toUpperCase());
System.out.println("提取 Era: 0x" + extractedEra.toString(16).toUpperCase());
System.out.println("提取 64位: 0x" + extracted64.toString(16).toUpperCase());
System.out.println("128位值: 0x" + ntp128WithEra.toString(16).toUpperCase());
System.out.println("Era 正确: " + (eraNumber.equals(extractedEra) ? "" : ""));
System.out.println("64位正确: " + (ntp64.equals(extracted64) ? "" : ""));
}
private static void testBoundaryValues() {
System.out.println("\n=== 边界值测试 ===");
// 测试最大值
BigInteger max64 = MASK_64_BIT; // 0xFFFFFFFFFFFFFFFF
BigInteger max128 = ntp64To128(max64);
BigInteger recovered64 = ntp128To64(max128);
System.out.println("最大64位: 0x" + max64.toString(16).toUpperCase());
System.out.println("转换128位: 0x" + max128.toString(16).toUpperCase());
System.out.println("恢复64位: 0x" + recovered64.toString(16).toUpperCase());
System.out.println("最大值转换正确: " + (max64.equals(recovered64) ? "" : ""));
// 测试 Era Number 边界
BigInteger maxEra = MASK_32_BIT; // 0xFFFFFFFF
BigInteger test64 = new BigInteger("1234567890ABCDEF", 16);
BigInteger ntp128MaxEra = ntp64To128(test64, maxEra);
BigInteger extractedMaxEra = getEraNumber(ntp128MaxEra);
System.out.println("最大Era转换正确: " + (maxEra.equals(extractedMaxEra) ? "" : ""));
}
/**
* 生成时间序列测试
*/
public static void testTimeSeries() {
System.out.println("\n=== 时间序列测试 ===");
Long128 startNanos = toNanosSince1970(System.currentTimeMillis(), 0);
BigInteger start128 = nanosToNtp128BitTimestamp(startNanos);
for (int i = 0; i < 5; i++) {
Long128 offsetNanos = Long128.valueOf(i).multiply(Long128.valueOf( NANOS_PER_SECOND).divide(Long128.valueOf(10)));
Long128 currentNanos = startNanos.add(offsetNanos);
BigInteger current128 = nanosToNtp128BitTimestamp(currentNanos);
BigInteger current64 = ntp128To64(current128);
long[] time = toMillisAndNanos(currentNanos);
System.out.printf("时间: %d ms + %d ns -> 64位: %s -> 128位: %s%n",
time[0], time[1],
current64.toString(16).toUpperCase(),
current128.toString(16).toUpperCase());
}
}
// 日期时间格式化器
private static final DateTimeFormatter DEFAULT_FORMATTER =
@@ -338,11 +222,19 @@ public class NTPTimestamps {
DEFAULT_FORMATTER.format(dateTime),
nanosPart.longValue());
}
public static String nanosSince1970ToString2(Long128 nanos) {
Long128 millis = nanos.divide(Long128.valueOf(1_000_000));
Instant instant = Instant.ofEpochMilli(millis.longValue());
LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return DEFAULT_FORMATTER.format(dateTime);
}
/**
* 将 128 位时间戳转换为可读字符串
*/
public static String ntp128ToString(BigInteger ntp128Timestamp) {
public static String ntp128ToString(Long128 ntp128Timestamp) {
Long128 nanosSince1970 = ntp128BitToNanosTimestamp(ntp128Timestamp);
return nanosSince1970ToString(nanosSince1970);
}
@@ -350,17 +242,17 @@ public class NTPTimestamps {
/**
* 将 64 位时间戳转换为可读字符串
*/
public static String ntp64ToString(BigInteger ntp64Timestamp) {
public static String ntp64ToString(Long128 ntp64Timestamp) {
Long128 nanosSince1970 = ntp128BitToNanosTimestamp(ntp64To128( ntp64Timestamp));
return nanosSince1970ToString(nanosSince1970);
}
public static BigInteger toUnsignedBigInteger(long unsignedLong) {
public static Long128 toUnsignedLong128(long unsignedLong) {
if (unsignedLong >= 0) {
return BigInteger.valueOf(unsignedLong);
return Long128.valueOf(unsignedLong);
} else {
// 对于负数,通过添加 2^64 来转换为无符号表示
return BigInteger.valueOf(unsignedLong & 0x7FFFFFFFFFFFFFFFL)
return Long128.valueOf(unsignedLong & 0x7FFFFFFFFFFFFFFFL)
.setBit(63);
}
}
@@ -0,0 +1,19 @@
package org.kne.cloud.clock;
public class WatchDogTimer {
private volatile long feedtime=System.nanoTime();
private long timeout;
public WatchDogTimer(long timeout) {
super();
this.timeout = timeout;
}
public void feed() {
feedtime=System.nanoTime();
}
public boolean isBarking() {
return(System.nanoTime()-feedtime)>timeout;
}
}
@@ -0,0 +1,51 @@
package org.kne.cloud.klalb.uitool;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.font.TextAttribute;
import java.util.Map;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import javax.swing.SwingConstants;
import org.kne.cloud.network.klalb.ui.UIEnv;
public class SliderSettingItem extends SettingItem {
protected JSlider slider;
protected JLabel labelx;
public JLabel getLabelx() {
return labelx;
}
public JSlider getSlider() {
return slider;
}
public SliderSettingItem(String text,int w,int h) {
this(text,UIEnv.getFont().deriveFont((float) 15.0),w,h);
}
/**
* @wbp.parser.constructor
*/
public SliderSettingItem(String text, Font deriveFont,int w,int h) {
super(text,deriveFont,w,h);
BorderLayout borderLayout = (BorderLayout) getPanel().getLayout();
slider = new JSlider();
getPanel().add(slider, BorderLayout.CENTER);
slider.setBorder(null);
slider.setOpaque(false);
slider.setBackground(new Color(0,0,0,0));
label.setForeground(Color.GRAY);
labelx = new JLabel();
getPanel().add(labelx, BorderLayout.EAST);
labelx.setFont(labelx.getFont());
labelx.setBorder(null);
labelx.setOpaque(false);
labelx.setBackground(new Color(0,0,0,0));
labelx.setPreferredSize(new Dimension(40, h));
}
}
@@ -41,9 +41,9 @@ public class TextButtonSettingItem extends SettingItem {
button = new JButton();
getPanel().add(button, BorderLayout.EAST);
button.setFont(button.getFont().deriveFont(Map.of(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON)));
button.setBorder(null);
button.setOpaque(false);
button.setFont(button.getFont());
//button.setBorder(null);
//button.setOpaque(false);
button.setBackground(new Color(0,0,0,0));
}
}
@@ -1,177 +0,0 @@
package org.kne.cloud.network;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySegment.Scope;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
public class BufferedArena implements Arena{
private static long blockSize=10*1024L*1024L;
private volatile PreAlloc buffer;
private static ReferenceQueue<MemorySegment> refq=new ReferenceQueue<>();
private static MemorySegmentPool msp=new MemorySegmentPool(1000, blockSize,true);
public static long getBlockSize() {
return blockSize;
}
public static void setBlockSize(long blockSizex) {
blockSize = blockSizex;
}
private ReentrantLock lock=new ReentrantLock();
private class PreAlloc{
private MemorySegment segment;
private AtomicLong pos=new AtomicLong(0);
private AtomicLong refs=new AtomicLong(0);
public MemorySegment getSegment() {
return segment;
}
public AtomicLong getPos() {
return pos;
}
public PreAlloc(MemorySegment segment) {
super();
this.segment = segment;
}
public long byteSize() {
return segment.byteSize();
}
public AtomicLong getRefs() {
return refs;
}
}
private void allocateNew(long blockSize2) {
lock.lock();
try {
//buffer=Arena.ofAuto().allocate(blockSize);
MemorySegment raw=msp.borrow();
buffer=new PreAlloc(raw);
}finally {
lock.unlock();
}
}
static {
Thread t= new Thread(()->{
while(true) {
try {
Reference<? extends MemorySegment> ref;
ref = refq.remove();
if(ref!=null) {
ref.clear();
}
} catch (InterruptedException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY-1);
t.start();
}
public BufferedArena() {
super();
allocateNew(blockSize);
}
@Override
public MemorySegment allocate(long byteSize, long byteAlignment) {
if(byteSize>blockSize)
throw new IndexOutOfBoundsException("byteSize can't large than buffer block");
long pos;
PreAlloc bufferx;
do{
bufferx=this.buffer;
pos=bufferx.getPos().getAndAdd(byteSize);
if(pos+byteSize>bufferx.byteSize()) {
allocateNew(blockSize);
}else {
break;
}
}while(true);
bufferx.getRefs().incrementAndGet();
MemorySegment sliced=bufferx.getSegment().asSlice(pos, byteSize);
new MemorySegmentPhantomReference(sliced, refq, bufferx, msp);
return sliced;
}
@Override
public Scope scope() {
return Arena.ofAuto().scope();
}
@Override
public void close() {
Arena.ofAuto().close();
}
public static BufferedArena ofBuffered() {
return new BufferedArena();
}
private class MemorySegmentPhantomReference extends PhantomReference<MemorySegment>{
private static AtomicReference<MemorySegmentPhantomReference> first=new AtomicReference<>(null);
private AtomicReference<MemorySegmentPhantomReference> next=new AtomicReference<>(null);
private AtomicReference<MemorySegmentPhantomReference> prev=new AtomicReference<>(null);
private PreAlloc father;
private MemorySegmentPool pool;
public MemorySegmentPhantomReference(MemorySegment referent, ReferenceQueue<? super MemorySegment> q,PreAlloc bufferx,MemorySegmentPool pool) {
super(referent, q);
this.father=bufferx;
this.pool=pool;
insert();
}
private void insert() {
MemorySegmentPhantomReference refn= first.getAndSet(this);
if(refn!=null) {
next.set(refn);
refn.prev.set(this);
}
}
private void remove() {
MemorySegmentPhantomReference prevn= prev.getAndSet(null);
MemorySegmentPhantomReference nextn=next.getAndSet(null);
if(prevn!=null)
prevn.next.set(nextn);
if(nextn!=null)
nextn.prev.set(prevn);
}
@Override
public void clear() {
if(father.getRefs().decrementAndGet()<=0) {
if(buffer!=father)
pool.back(father.getSegment());
}
remove();
super.clear();
}
}
}
@@ -18,39 +18,25 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import org.kne.debug.TimeDebugger;
import org.kne.membandboost.MembandBoost;
import jdk.internal.misc.Unsafe;
public class ByteBufferAllocator {
static Thread t;
static {
t=new Thread(()->{
while(true) {
System.gc();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
});
t.setDaemon(true);
t.setPriority(Thread.MAX_PRIORITY-1);
t.start();
}
public ByteBufferAllocator(boolean isDirect) {
}
public ByteBuffer allocate(int capacity) {
//if(capacity<1024)
return allocateHeap(capacity);
//return allocateNative(capacity);
// return allocateNative(capacity);
}
//private Arena ar=BufferedArena.ofBuffered();
private Arena ara=Arena.ofAuto();
//private Arena ara=Arena.ofAuto();
public ByteBuffer allocateNative(int capacity) {
//return ((jdk.internal.foreign.ArenaImpl)Arena.ofAuto()).allocateNoInit(capacity,1).asByteBuffer();
//return ((jdk.internal.foreign.ArenaImpl)ara).allocateNoInit(capacity,1).asByteBuffer();
ByteBuffer buf=Arena.ofAuto().allocate(capacity).asByteBuffer();
if(buf.capacity()!=capacity)
@@ -74,64 +60,25 @@ public class ByteBufferAllocator {
e.printStackTrace();
}
}
public static byte[] allocateArray(int capacity) {
if(usf!=null&&meth!=null) {
try {
public static byte[] allocateUninitializedArray(int capacity) {
if(usf!=null) {
return (byte[]) usf.allocateUninitializedArray(byte.class, capacity);
} catch (Exception e) {
return new byte[capacity];
}
}else {
return new byte[capacity];
}
}
public static ByteBuffer allocateHeap(int capacity) {
return ByteBuffer.wrap((byte[])allocateArray(capacity)) ;
/*if(capacity<=2048) {
return MembandBoost.allocateUninitializedHeapBufferBlocked(capacity);
}else {*/
return MembandBoost.allocateUninitializedHeapBuffer(capacity);
//}
}
public static ByteBuffer allocateHeap0(int capacity) {
return ByteBuffer.wrap((byte[])allocateUninitializedArray(capacity)) ;
}
private static class ByteBufferPhantomReference extends PhantomReference<ByteBuffer>{
private static AtomicReference<ByteBufferPhantomReference> first=new AtomicReference<>(null);
private AtomicReference<ByteBufferPhantomReference> next=new AtomicReference<>(null);
private AtomicReference<ByteBufferPhantomReference> prev=new AtomicReference<>(null);
private ByteBuffer father;
private ByteBufferPool pool;
public ByteBufferPhantomReference(ByteBuffer referent, ReferenceQueue<? super ByteBuffer> q,ByteBuffer father,ByteBufferPool pool) {
super(referent, q);
this.father=father;
this.pool=pool;
insert();
}
private void insert() {
ByteBufferPhantomReference refn= first.getAndSet(this);
if(refn!=null) {
next.set(refn);
refn.prev.set(this);
}
}
private void remove() {
ByteBufferPhantomReference prevn= prev.getAndSet(null);
ByteBufferPhantomReference nextn=next.getAndSet(null);
if(prevn!=null)
prevn.next.set(nextn);
if(nextn!=null)
nextn.prev.set(prevn);
}
@Override
public void clear() {
//System.out.println("clear");
pool.back(father);
remove();
super.clear();
}
}
}
+4 -2
View File
@@ -83,8 +83,10 @@ public class ChannelBridge extends Task{
public void runAtNewThread() {
runAtNewThread("StreamBridge thread");
}
public void runAtNewThread(String name) {
ThreadTool.makeVThreadIfSupport(name, this).start();
public Thread runAtNewThread(String name) {
Thread t=ThreadTool.makeVThreadIfSupport(name, this);
t.start();
return t;
}
}
@@ -196,7 +196,7 @@ public class DatagramServerSocket implements java.io.Closeable{
return sds;
}
try {
Thread.sleep(1);
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -0,0 +1,98 @@
package org.kne.cloud.network;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySegment.Scope;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
public class DirectBufferedArena implements Arena{
private static long blockSize=1024*1024L;
private volatile PreAlloc buffer;
public static long getBlockSize() {
return blockSize;
}
public static void setBlockSize(long blockSizex) {
blockSize = blockSizex;
}
private class PreAlloc{
private MemorySegment segment;
private AtomicLong pos=new AtomicLong(0);
private AtomicLong refs=new AtomicLong(0);
public MemorySegment getSegment() {
return segment;
}
public AtomicLong getPos() {
return pos;
}
public PreAlloc(MemorySegment segment) {
super();
this.segment = segment;
}
public long byteSize() {
return segment.byteSize();
}
public AtomicLong getRefs() {
return refs;
}
}
private void allocateNew(long blockSize2) {
MemorySegment raw=MemorySegment.ofArray(ByteBufferAllocator.allocateUninitializedArray((int) blockSize2));
buffer=new PreAlloc(raw);
}
public DirectBufferedArena() {
super();
allocateNew(blockSize);
}
@Override
public MemorySegment allocate(long byteSize, long byteAlignment) {
if(byteSize>blockSize)
throw new IndexOutOfBoundsException("byteSize can't large than buffer block");
long pos;
PreAlloc bufferx;
do{
bufferx=this.buffer;
pos=bufferx.getPos().getAndAdd(byteSize);
if(pos+byteSize>bufferx.byteSize()) {
allocateNew(blockSize);
}else {
break;
}
}while(true);
bufferx.getRefs().incrementAndGet();
MemorySegment sliced=bufferx.getSegment().asSlice(pos, byteSize);
return sliced;
}
@Override
public Scope scope() {
return null;
}
@Override
public void close() {
}
public static DirectBufferedArena ofBuffered() {
return new DirectBufferedArena();
}
}
@@ -0,0 +1,69 @@
package org.kne.cloud.network;
import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.MemorySegment.Scope;
import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;
public class HeapBufferedArena implements Arena{
private static long blockSize=32768L;
private MemorySegment segment;
private long pos=0;
public static void setBlockSize(long blockSizex) {
blockSize = blockSizex;
}
private void allocateNew(long blockSize2) {
segment=MemorySegment.ofArray(ByteBufferAllocator.allocateUninitializedArray((int) blockSize2));
pos=0;
}
public HeapBufferedArena() {
super();
allocateNew(blockSize);
}
@Override
public MemorySegment allocate(long byteSize, long byteAlignment) {
if(byteSize>blockSize)
return MemorySegment.ofArray(ByteBufferAllocator.allocateUninitializedArray((int) byteSize));
do{
long newpos=pos+byteSize;
if(newpos>blockSize) {
allocateNew(blockSize);
}else {
MemorySegment ms=segment.asSlice(pos, byteSize);
pos=newpos;
return ms;
}
}while(true);
}
@Override
public Scope scope() {
return null;
}
@Override
public void close() {
}
public static HeapBufferedArena ofBuffered() {
return new HeapBufferedArena();
}
}
@@ -5,6 +5,7 @@ import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
@@ -20,9 +21,12 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.function.Consumer;
public class IPMulticastDiscovery extends Thread implements Closeable, AutoCloseable {
private static final boolean debug=false;
private MulticastSocket soc;
private NetworkInterface ninterface;
private volatile boolean closed = false;
@@ -30,6 +34,7 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose
private InetSocketAddress bind;
private int type;
private List<MultipurposeSocketAddress> msas;
private UUID selfUUID;
private volatile Consumer<MultipurposeSocketAddress> con;
private long timeInterval;
@@ -63,13 +68,14 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose
}
public IPMulticastDiscovery(InetSocketAddress bind, InetSocketAddress group, NetworkInterface ninterface,
List<MultipurposeSocketAddress> msas,long timeInterval) throws IOException {
List<MultipurposeSocketAddress> msas,UUID node,long timeInterval) throws IOException {
soc = new MulticastSocket(bind);
soc.joinGroup(group, ninterface);
this.bind = bind;
this.group = group;
this.ninterface = ninterface;
this.msas = msas;
this.selfUUID=node;
this.timeInterval=timeInterval;
}
@@ -100,16 +106,19 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose
}
}
if (bf) {
continue;
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dops = new DataOutputStream(baos);
dops.writeInt(multipurposeSocketAddress.getPort());
dops.writeUTF(multipurposeSocketAddress.getType());
dops.writeLong(selfUUID.getMostSignificantBits());
dops.writeLong(selfUUID.getLeastSignificantBits());
dops.close();
byte[] b = baos.toByteArray();
DatagramPacket dp = new DatagramPacket(b, b.length, group);
soc.send(dp);
if(debug)
System.out.println("发送广播:"+multipurposeSocketAddress+" "+group+" "+selfUUID);
}
}
} catch (NoRouteToHostException|UnknownHostException e) {
}
@@ -136,6 +145,7 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose
try {
loop:while (!closed) {
try {
byte[] b = new byte[65535];
DatagramPacket dp = new DatagramPacket(b, b.length);
soc.receive(dp);
@@ -143,12 +153,21 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose
DataInputStream dis = new DataInputStream(bis);
int port = dis.readInt();
String type = dis.readUTF();
long h=dis.readLong();
long l=dis.readLong();
UUID uid=new UUID(h, l);
dis.close();
MultipurposeSocketAddress mpsa = new MultipurposeSocketAddress(type, dp.getAddress().getHostAddress(),
port);
try {
if(debug) {
if(uid.equals(selfUUID)) {
System.out.println("丢弃广播:"+mpsa+" "+dp.getSocketAddress()+" "+uid);
continue;
}else {
System.out.println("接收广播:"+mpsa+" "+dp.getSocketAddress()+" "+uid);
}
}
InetAddress mpsai=mpsa.getInetAddress();
//System.out.println(mpsa);
Enumeration<InetAddress> ei = ninterface.getInetAddresses();
while (ei.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) ei.nextElement();
@@ -162,9 +181,14 @@ public class IPMulticastDiscovery extends Thread implements Closeable, AutoClose
}
}catch(UnknownHostException e) {
}catch(EOFException e) {
}
}
} catch (IOException e) {
} catch(SocketException e) {
if(!isClosed())
e.printStackTrace();
}catch (IOException e) {
System.out.println(bind + " " + group + " " + ninterface);
e.printStackTrace();
} finally {
@@ -0,0 +1,326 @@
package org.kne.cloud.network;
import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.kne.cloud.network.ipv6.IPv6Address;
/**
* 高性能IPv6套接字地址实现,替代Java原生的InetSocketAddress
* 大幅减少GC压力和提高网络栈性能
*/
public final class IPv6SocketAddress {
private static final long serialVersionUID = 1L;
private final IPv6Address address;
private final int port;
// 常用常量
public static final IPv6SocketAddress ANY = new IPv6SocketAddress(IPv6Address.UNSPECIFIED, 0);
// 构造方法
public IPv6SocketAddress(IPv6Address address, int port ) {
if (address == null) {
throw new IllegalArgumentException("Address cannot be null");
}
if (port < 0 || port > 65535) {
throw new IllegalArgumentException("Port out of range: " + port);
}
this.address = address;
this.port = port;
}
/**
* 从IPv6地址和端口创建
*/
public static IPv6SocketAddress valueOf(IPv6Address address, int port) {
return new IPv6SocketAddress(address, port);
}
/**
* 从两个long和端口创建(最高性能)
*/
public static IPv6SocketAddress valueOf(long high, long low, int port) {
return new IPv6SocketAddress(IPv6Address.valueOf(high, low), port);
}
/**
* 从byte[16]和端口创建
*/
public static IPv6SocketAddress valueOf(byte[] addressBytes, int port) {
return new IPv6SocketAddress(IPv6Address.valueOf(addressBytes), port);
}
/**
* 从ByteBuffer创建(零拷贝友好)
*/
public static IPv6SocketAddress valueOf(ByteBuffer buffer) {
if (buffer.remaining() < 18) { // 16字节地址 + 2字节端口
throw new IllegalArgumentException("Buffer must have at least 18 bytes remaining");
}
long high = buffer.getLong();
long low = buffer.getLong();
int port = buffer.getShort() & 0xFFFF;
return valueOf(high, low, port);
}
/**
* 从ByteBuffer指定位置创建
*/
public static IPv6SocketAddress valueOf(int offset, ByteBuffer buffer) {
if (buffer.remaining() < offset + 18) {
throw new IllegalArgumentException("Buffer too small");
}
long high = buffer.getLong(offset);
long low = buffer.getLong(offset + 8);
int port = buffer.getShort(offset + 16) & 0xFFFF;
return valueOf(high, low, port);
}
/**
* 从Java InetSocketAddress转换
*/
public static IPv6SocketAddress valueOf(InetSocketAddress inetSocketAddress) {
if (inetSocketAddress == null) {
throw new IllegalArgumentException("InetSocketAddress cannot be null");
}
IPv6Address addr = IPv6Address.valueOf(inetSocketAddress.getAddress());
int port = inetSocketAddress.getPort();
return new IPv6SocketAddress(addr, port);
}
/**
* 从字符串解析(格式: [ipv6]:port 或 ipv6:port
*/
public static IPv6SocketAddress valueOf(String socketAddress) {
if (socketAddress == null || socketAddress.isEmpty()) {
throw new IllegalArgumentException("Invalid socket address string");
}
try {
// 处理[ipv6]:port格式
if (socketAddress.startsWith("[")) {
int closeBracket = socketAddress.indexOf(']');
if (closeBracket == -1) {
throw new IllegalArgumentException("Invalid IPv6 socket address format");
}
String ipPart = socketAddress.substring(1, closeBracket);
String portPart = socketAddress.substring(closeBracket + 1);
if (!portPart.startsWith(":")) {
throw new IllegalArgumentException("Invalid IPv6 socket address format");
}
IPv6Address address = IPv6Address.valueOf(ipPart);
int port = Integer.parseInt(portPart.substring(1));
return valueOf(address, port);
} else {
// 处理ipv6:port格式(简单情况)
int lastColon = socketAddress.lastIndexOf(':');
if (lastColon == -1) {
throw new IllegalArgumentException("Invalid IPv6 socket address format");
}
String ipPart = socketAddress.substring(0, lastColon);
String portPart = socketAddress.substring(lastColon + 1);
IPv6Address address = IPv6Address.valueOf(ipPart);
int port = Integer.parseInt(portPart);
return valueOf(address, port);
}
} catch (Exception e) {
throw new IllegalArgumentException("Invalid IPv6 socket address: " + socketAddress, e);
}
}
/**
* 创建未解析的地址(带hostname)
* @throws UnknownHostException
*/
public static IPv6SocketAddress createUnresolved(String hostname, int port) throws UnknownHostException {
if (hostname == null || hostname.isEmpty()) {
throw new IllegalArgumentException("Hostname cannot be null or empty");
}
if (port < 0 || port > 65535) {
throw new IllegalArgumentException("Port out of range: " + port);
}
return new IPv6SocketAddress(IPv6Address.valueOf ( hostname), port);
}
// 核心getter方法
public IPv6Address getAddress() {
return address;
}
public int getPort() {
return port;
}
/**
* 转换为byte数组(18字节:16字节地址 + 2字节端口)
*/
public byte[] toByteArray() {
byte[] bytes = new byte[18];
toByteArray(bytes, 0);
return bytes;
}
/**
* 写入到现有byte数组
*/
public void toByteArray(byte[] dest, int offset) {
if (dest.length - offset < 18) {
throw new IllegalArgumentException("Destination array too small");
}
address.toByteArray(dest, offset);
dest[offset + 16] = (byte) (port >> 8);
dest[offset + 17] = (byte) port;
}
/**
* 写入到ByteBuffer(高性能网络操作)
*/
public void writeTo(ByteBuffer buffer) {
address.writeTo(buffer);
buffer.putShort((short) port);
}
/**
* 写入到ByteBuffer指定位置
*/
public void writeTo(int offset, ByteBuffer buffer) {
address.writeTo(offset, buffer);
buffer.putShort(offset + 16, (short) port);
}
/**
* 转换为Java InetSocketAddress(兼容性方法)
*/
public InetSocketAddress toInetSocketAddress() {
Inet6Address inet6Addr = address.toInet6Address();
return new InetSocketAddress(inet6Addr, port);
}
// 实用方法
/**
* 检查是否为通配符地址(0.0.0.0:0)
*/
public boolean isWildcardAddress() {
return address.equals(IPv6Address.UNSPECIFIED) && port == 0;
}
/**
* 检查是否为环回地址
*/
public boolean isLoopbackAddress() {
return address.isLoopbackAddress();
}
/**
* 检查是否为多播地址
*/
public boolean isMulticastAddress() {
return address.isMulticastAddress();
}
/**
* 检查是否为链路本地地址
*/
public boolean isLinkLocalAddress() {
return address.isLinkLocalAddress();
}
/**
* 检查是否为站点本地地址
*/
public boolean isSiteLocalAddress() {
return address.isSiteLocalAddress();
}
/**
* 获取多播地址的scope
*/
public int getMulticastScope() {
return address.getMulticastScope();
}
// 路由相关的实用方法
/**
* 检查地址是否在指定网络内
*/
public boolean isInNetwork(IPv6Address network, int prefixLength) {
return address.isInNetwork(network, prefixLength);
}
/**
* 应用网络掩码
*/
public IPv6SocketAddress maskWith(IPv6Address mask) {
return valueOf(address.maskWith(mask), port);
}
// 比较和哈希
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + port;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IPv6SocketAddress other = (IPv6SocketAddress) obj;
if (address == null) {
if (other.address != null)
return false;
} else if (!address.equals(other.address))
return false;
if (port != other.port)
return false;
return true;
}
@Override
public String toString() {
// 对于IPv6地址,使用方括号括起来
return "[" + address.toString() + "]:" + port;
}
/**
* 转换为压缩形式的字符串
*/
public String toCompressedString() {
return "[" + address.toCompressedString() + "]:" + port;
}
}
@@ -63,7 +63,7 @@ public class MemorySegmentPool {
}
if(b==null) {
ByteBufferAllocator.t.interrupt();
//ByteBufferAllocator.t.interrupt();
if(direct) {
b=((jdk.internal.foreign.ArenaImpl)Arena.ofAuto()).allocateNoInit(length,1);
System.out.println(length);
@@ -189,7 +189,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port),timeout);
}catch(Exception e) {
s.close();
System.gc();
throw e;
}
return s;
@@ -205,7 +204,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
s.close();
System.gc();
throw e;
}
return s;
@@ -220,7 +218,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
s.close();
System.gc();
throw e;
}
return s;
@@ -235,7 +232,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port),timeout);
}catch(Exception e) {
s.close();
System.gc();
throw e;
}
return s;
@@ -261,7 +257,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
s.close();
System.gc();
throw e;
}finally {
if(tt!=null)
@@ -280,7 +275,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
s.close();
System.gc();
throw e;
}
return s;
@@ -295,7 +289,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
s.close();
System.gc();
throw e;
}
return s;
@@ -312,7 +305,6 @@ public class MultipurposeSocketAddress implements Serializable{
s.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
s.close();
System.gc();
throw e;
}finally {
if(tt!=null)
@@ -379,7 +371,6 @@ public class MultipurposeSocketAddress implements Serializable{
dgd.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
dgd.close();
System.gc();
throw e;
}
return dgd;
@@ -394,14 +385,12 @@ public class MultipurposeSocketAddress implements Serializable{
dgd.connect(new InetSocketAddress(host, port));
}catch(Exception e) {
dgd.close();
System.gc();
throw e;
}
return dgd;
}
public DatagramSocket listenDatagramSocket() throws UnknownHostException, IOException {
DatagramSocketFactory dgs=socketTypeRegister.get(type).getDatagramSocketFactory();
System.out.println(dgs);
if(dgs==null) {
throw new UnsupportedOperationException("DatagramSocket Unsupported");
}
@@ -410,7 +399,6 @@ public class MultipurposeSocketAddress implements Serializable{
dgd.bind(new InetSocketAddress(host, port));
}catch(Exception e) {
dgd.close();
System.gc();
throw e;
}
return dgd;
+1 -35
View File
@@ -10,7 +10,7 @@ import java.util.concurrent.locks.ReentrantLock;
import org.kne.cloud.network.klalb.KLALBPacket;
import org.kne.debug.TimeDebugger;
public abstract class NetworkPacket implements Comparable<NetworkPacket>{
public abstract class NetworkPacket{
private static final boolean debugPassport=false;
public static final ByteBufferAllocator bufferAllocator=new ByteBufferAllocator(true);
@@ -52,41 +52,7 @@ public abstract class NetworkPacket implements Comparable<NetworkPacket>{
public abstract long getTotalLength();
public long getPriority() {
return priority;
}
public void setPriority(long priority) {
this.priority = priority;
}
public long getSendseq() {
return sendseq;
}
private long priority;
private long sendseq;
private static final AtomicLong seqgen=new AtomicLong();
@Override
public int compareTo(NetworkPacket o) {
if(priority>o.priority) {
return 1;
}else if(priority<o.priority){
return -1;
}else {
if(sendseq>o.sendseq) {
return 1;
}else if(sendseq<o.sendseq){
return -1;
}else {
return 0;
}
}
}
public void genseq() {
this.sendseq=seqgen.getAndIncrement();
}
public abstract void writeToChannel(WritableByteChannel dto) throws IOException ;
public abstract void readFromChannel(ReadableByteChannel din,long length) throws IOException;
+8 -25
View File
@@ -3,6 +3,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.util.concurrent.locks.LockSupport;
import org.kne.cloud.network.klalb.CannotAssociateException;
import org.kne.cloud.network.klalb.KLALBVirtualSocket;
@@ -31,32 +32,14 @@ public class SocketBridge extends Task{
@Override
protected void runTask() {
try {
if(a instanceof KLALBVirtualSocket) {
try {
((KLALBVirtualSocket) a).associateSocket(b);
}catch(CannotAssociateException e) {
bridgeAB.runAtNewThread("SocketBridge A->B thread");
bridgeBA.runAtNewThread("SocketBridge B->A thread");
bridgeAB.waitfortask();
bridgeBA.waitfortask();
}
}else if(b instanceof KLALBVirtualSocket){
try {
((KLALBVirtualSocket) b).associateSocket(a);
}catch(CannotAssociateException e) {
bridgeAB.runAtNewThread("SocketBridge A->B thread");
bridgeBA.runAtNewThread("SocketBridge B->A thread");
bridgeAB.waitfortask();
bridgeBA.waitfortask();
}
}else {
bridgeAB.runAtNewThread("SocketBridge A->B thread");
bridgeBA.runAtNewThread("SocketBridge B->A thread");
bridgeAB.waitfortask();
bridgeBA.waitfortask();
}} catch (Exception e) {
Thread ta=bridgeAB.runAtNewThread("SocketBridge A->B thread");
Thread tb=bridgeBA.runAtNewThread("SocketBridge B->A thread");
while((ta.isAlive()||tb.isAlive())&&(!a.isClosed())&&(!b.isClosed())) {
LockSupport.parkNanos(1000000L);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
//new Exception().printStackTrace();
@@ -4,6 +4,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.*;
import java.nio.channels.SocketChannel;
import java.util.concurrent.locks.LockSupport;
import org.kne.cloud.network.klalb.CannotAssociateException;
import org.kne.cloud.network.klalb.KLALBVirtualSocket;
@@ -33,33 +34,13 @@ public class SocketChannelBridge extends Task{
@Override
protected void runTask() {
try {
if(a instanceof KLALBVirtualSocketChannel) {
try {
((KLALBVirtualSocketChannel) a).associateSocketChannel(b);
}catch(CannotAssociateException e) {
bridgeAB.runAtNewThread("SocketBridge A->B thread");
bridgeBA.runAtNewThread("SocketBridge B->A thread");
bridgeAB.waitfortask();
bridgeBA.waitfortask();
}
}else if(b instanceof KLALBVirtualSocketChannel){
try {
((KLALBVirtualSocketChannel) b).associateSocketChannel(a);
}catch(CannotAssociateException e) {
bridgeAB.runAtNewThread("SocketBridge A->B thread");
bridgeBA.runAtNewThread("SocketBridge B->A thread");
bridgeAB.waitfortask();
bridgeBA.waitfortask();
}
}else {
bridgeAB.runAtNewThread("SocketBridge A->B thread");
bridgeBA.runAtNewThread("SocketBridge B->A thread");
bridgeAB.waitfortask();
bridgeBA.waitfortask();
}
Thread ta=bridgeAB.runAtNewThread("SocketBridge A->B thread");
Thread tb=bridgeBA.runAtNewThread("SocketBridge B->A thread");
while((ta.isAlive()||tb.isAlive())&&a.isOpen()&&b.isOpen()) {
LockSupport.parkNanos(1000000L);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
+4 -2
View File
@@ -84,8 +84,10 @@ public class StreamBridge extends Task{
public void runAtNewThread() {
runAtNewThread("StreamBridge thread");
}
public void runAtNewThread(String name) {
ThreadTool.makeVThreadIfSupport(name, this).start();
public Thread runAtNewThread(String name) {
Thread t=ThreadTool.makeVThreadIfSupport(name, this);
t.start();
return t;
}
}
+6 -2
View File
@@ -65,7 +65,10 @@ public class ThreadTool {
return rt;
}
public static Thread makeVDaemonThread(String name, Runnable r) {
try { //return new Thread(r, name);
if(false)
return new Thread(r, name);
try {
Class<?> c=Class.forName("java.lang.Thread");
Method m= c.getDeclaredMethod("ofVirtual", null);
Object o=m.invoke(null, null);
@@ -87,7 +90,8 @@ public class ThreadTool {
}
}
public static Thread makeVThread(String name, Runnable r) {
if(false)
return new Thread(r, name);
try { //return new Thread(r, name);
Class<?> c=Class.forName("java.lang.Thread");
Method m= c.getDeclaredMethod("ofVirtual", null);
@@ -1,26 +1,120 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.lang.ref.Cleaner;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import org.kne.cloud.network.ThreadTool;
import org.kne.concurrent.SpinLock;
import org.kne.opencl64.Releaser;
/**
* 网络消息批量发送器用于减少小包数量降低网络性能开销
* @param <T> 消息类型
*/
public class MessageBatcher<T> implements Runnable{
public class ArrayListMessageBatcher<T> implements MessageBatcher<T>{
private static final Cleaner clr=Cleaner.create();
private ArrayListMessageBatcher0<T> impl;
private ArrayListMessageBatcherReleaser<T> releaser;
public ArrayListMessageBatcher(int batchSize, long maxDelay) {
impl=new ArrayListMessageBatcher0<T>(batchSize, maxDelay);
releaser=new ArrayListMessageBatcherReleaser<T>(impl);
clr.register(this, releaser);
}
@Override
public int getBatchSize() {
return impl.getBatchSize();
}
@Override
public long getMaxDelay() {
return impl.getMaxDelay();
}
@Override
public void setConsumer(Consumer<List<T>> consumer) {
impl.setConsumer(consumer);
}
@Override
public void putMessage(T message) {
impl.putMessage(message);
}
@Override
public void putMessages(List<T> messages) {
impl.putMessages(messages);
}
@Override
public void flush() {
impl.flush();
}
@Override
public int getQueueSize() {
return impl.getQueueSize();
}
@Override
public boolean isClosed() {
return impl.isClosed();
}
@Override
public void close() {
impl.close();
}
public static void main(String[] args) throws InterruptedException {
for(;;){
ArrayListMessageBatcher<Integer>mes=new ArrayListMessageBatcher<>(10, 1000000L);
System.gc();
}
/*ArrayListMessageBatcher<Integer>mes=new ArrayListMessageBatcher<>(10, 1000000L);
mes.setConsumer((x)->{System.out.println(x);});
int n=0;
for(;;){
mes.putMessage(n++);
mes.putMessage(n++);
mes.putMessage(n++);
mes.putMessage(n++);
Thread.sleep(1);
}*/
}
}
class ArrayListMessageBatcherReleaser<T> extends Releaser<ArrayListMessageBatcher0<T>>{
public ArrayListMessageBatcherReleaser(ArrayListMessageBatcher0<T> resource) {
super(resource);
}
@Override
protected void release(ArrayListMessageBatcher0<T> resource) {
resource.close();
//System.out.println("release!");
}
}
class ArrayListMessageBatcher0<T> implements Runnable,MessageBatcher<T>{
private ArrayList<T> messageList;
private ReentrantLock lock=new ReentrantLock();
private Lock lock=new SpinLock();
private final int batchSize;
private final long maxDelay;
private Consumer<List<T>> consumer;
private final Thread batchThread;
private final AtomicBoolean running;
private final AtomicBoolean closed;
private long firstTime;
/**
@@ -28,13 +122,13 @@ public class MessageBatcher<T> implements Runnable{
* @param batchSize 批量大小当消息达到此数量时触发发送
* @param maxDelayMillis 最大延迟时间(毫秒)即使消息数量不足也会触发发送
*/
public MessageBatcher(int batchSize, long maxDelay) {
public ArrayListMessageBatcher0(int batchSize, long maxDelay) {
this.batchSize = batchSize;
this.maxDelay = maxDelay;
this.running = new AtomicBoolean(true);
this.closed = new AtomicBoolean(false);
// 创建并启动批量处理线程
this.batchThread = new Thread(this);
this.batchThread = ThreadTool.makeVDaemonThread("ArrayListMessageBatcher Thread", this );
this.batchThread.setDaemon(true);
this.batchThread.start();
}
@@ -99,7 +193,7 @@ public class MessageBatcher<T> implements Runnable{
* 停止批量处理器
*/
public void close() {
running.set(false);
closed.set(true);
LockSupport.unpark(batchThread);
// 确保所有消息都被发送
flush();
@@ -109,7 +203,7 @@ public class MessageBatcher<T> implements Runnable{
* 批量处理消息的核心方法
*/
public void run() {
while(running.get()) {
while(!closed.get()) {
lock.lock();
try {
check(false);
@@ -175,16 +269,12 @@ public class MessageBatcher<T> implements Runnable{
return 0;
return cmessageList.size();
}
public static void main(String[] args) throws InterruptedException {
MessageBatcher<Integer>mes=new MessageBatcher<>(10, 1000000L);
mes.setConsumer((x)->{System.out.println(x);});
int n=0;
for(;;){
mes.putMessage(n++);
mes.putMessage(n++);
mes.putMessage(n++);
mes.putMessage(n++);
Thread.sleep(1);
}
@Override
public boolean isClosed() {
return closed.get();
}
}
@@ -1,21 +1,21 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class LARCCongressAlgorithm implements CongressAlgorithm {
public class BBRCongestionAlgorithm implements CongestionAlgorithm ,DetnetCongestionAlgorithm{
private static final long BURST_TIME = 1000000L;
private static final long BIAS = 1000000L;
private static long MIN_SPEED = 64 * 1024L;
private static final long BURST_TIME = 10000000L;
private static final long BIAS = 500000L;
private static long MIN_SPEED = 512 * 1024L;
private static long MIN_WINDOW = 16384;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 10000000L;
private long MIN_RTTVAR = 5000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
@@ -29,10 +29,10 @@ public class LARCCongressAlgorithm implements CongressAlgorithm {
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
private long congressSpeed=MIN_SPEED;
private double MAX_GAIN=1.1;//2.8853900817779
private double MIN_GAIN=0.95;
private double windowGain=1.5;
private double speedGain=4;//MAX_GAIN
private double MIN_GAIN=1.05;
private double MAX_GAIN=1.20;//2.8853900817779
private double windowGain=MIN_GAIN;
private double speedGain=MAX_GAIN;//1.20 MAX_GAIN
@Override
public void reset() {
window = MIN_WINDOW;
@@ -98,7 +98,7 @@ public class LARCCongressAlgorithm implements CongressAlgorithm {
congressSpeed = bandwidth;
//congressSpeed = (congressSpeed + bandwidth) / 2;
} else {
congressSpeed = (congressSpeed * 199 + bandwidth) / 200;
congressSpeed = (congressSpeed * 49 + bandwidth) / 50;
}
speed=(long) (congressSpeed * speedGain)+MIN_SPEED ;
window= ((long) (congressSpeed*windowGain )*(RTTMin+BIAS)/1000000000L)+MIN_WINDOW;
@@ -135,4 +135,16 @@ public class LARCCongressAlgorithm implements CongressAlgorithm {
//System.out.println(bandwidth+" "+congressSpeed+" "+window);
}
@Override
public void setUpperDelayBound(double upper) {
MAX_GAIN=upper;
speedGain=MAX_GAIN;
}
@Override
public void setLowerDelayBound(double lower) {
MIN_GAIN=lower;
windowGain=MIN_GAIN;
}
}
@@ -1,10 +1,10 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class BBRVegasCongressAlgorithm implements CongressAlgorithm {
public class BBRVegasCongressAlgorithm implements CongestionAlgorithm {
private static final long BURST_TIME = 2000000L;
private static final long BIAS = 2000000L;
@@ -1,9 +1,9 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public interface CongressAlgorithm {
public interface CongestionAlgorithm {
public void reset();
public void setWindowControlConsumer(Consumer<Long>windowControlConsumer);
public void setSpeedControlConsumer(BiConsumer<Long,Long>speedControlConsumer);
@@ -1,131 +1,161 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class BBRCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 2000000L;
private static final long BIAS = 2000000L;
private static long MIN_SPEED = 128 * 1024L;
private static long MIN_WINDOW = 16384;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 50000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L;
private volatile long RTTTotal = 0;
private volatile long RTTCount = 0;
private volatile long RTO = 1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
private long congressSpeed=MIN_SPEED;
private double MAX_GAIN=1.02;//2.8853900817779
private double MIN_GAIN=0.9;
private double windowGain=MAX_GAIN;
private double speedGain=MAX_GAIN;
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
windowGain=MAX_GAIN;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
private long RTTstartTime = System.nanoTime();
private long bandwidth;
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
RTTMin = (RTTMin * 99999 + latencyns) / 100000;
}
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
RTTTotal += latencyns;
RTTCount++;
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTAvg2) {
if(RTTCount>0) {
RTTAvg2=(RTTAvg2+RTTTotal/RTTCount)/2;
RTTTotal=0;
RTTCount=0;
}
RTTstartTime=curr;
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
//congressSpeed = (congressSpeed + bandwidth) / 2;
} else {
congressSpeed = (congressSpeed * 199 + bandwidth) / 200;
}
speed=MIN_SPEED+(long) (congressSpeed * speedGain) ;
window= (Math.max(MIN_SPEED,(long) (congressSpeed*windowGain ))*(RTTMin+1000000L)/1000000000L)+MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
}
@Override
public void setCurrentBandwidth(long bandwidth) {
this.bandwidth=bandwidth;
//System.out.println(gain);
//System.out.println(bandwidth+" "+congressSpeed+" "+window);
}
}
package org.kne.cloud.network.congestion;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class DCTCP2CongestionAlgorithm implements CongestionAlgorithm {
private static final long BURST_TIME = 1000000L;
private static final long BIAS = 2000000L;
private static long MIN_SPEED = 64 * 1024L;
private static long MIN_WINDOW = 32768;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 400000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private double ECNAvg2 = 0L;
private double alpha=0;
private volatile AtomicLong ECNSize = new AtomicLong(0);
private volatile AtomicLong TotalSize = new AtomicLong(0);
private volatile long RTO = 1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long windowUsed=MIN_WINDOW;
private volatile long congressWindowSize=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private long congressSpeed=MIN_SPEED;
private long RTTstartTime = System.nanoTime();
private long bandwidth=MIN_SPEED;
private double MAX_GAIN=1.5;//2.8853900817779
private double MIN_GAIN=1.2;
private double gain=MAX_GAIN;
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
gain=MAX_GAIN;
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
RTTMin = (RTTMin * 99999 + latencyns) / 100000;
}
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
if(ecn) {
ECNSize.addAndGet(packetSize);
}
TotalSize.addAndGet(packetSize);
long curr=System.nanoTime();
if(curr-RTTstartTime>(RTTAvg+BIAS)) {
RTTstartTime=curr;
long totalSize=TotalSize.getAndSet(0);
long ecnSize=ECNSize.getAndSet(0);
if(totalSize!=0) {
ECNAvg2=ecnSize/(double)totalSize;
alpha=(alpha*15+ECNAvg2)/16;
}
if(ECNAvg2>0.5) {
gain=MIN_GAIN;
if(congressWindowSize>MIN_WINDOW) {
congressWindowSize-=200;
updateWindowSize();
}
}else if(ECNAvg2>0.1){
if(windowUsed*3L>=congressWindowSize) {
congressWindowSize+=200;
updateWindowSize();
}
}else {
if(windowUsed*3L>=congressWindowSize) {
congressWindowSize+=8000;
updateWindowSize();
}
}
//System.out.println(ECNAvg2);
//System.out.println(speed+" "+window);
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
} else {
congressSpeed = (congressSpeed * 99 + bandwidth) / 100;
}
speed=Math.max(MIN_SPEED,(long) (congressSpeed * gain)) ;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
}
private void updateWindowSize() {
window=Math.max( congressWindowSize,MIN_WINDOW);
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
this.windowUsed=used;
}
@Override
public void setCurrentBandwidth(long bandwidth) {
this.bandwidth=bandwidth;
}
}
@@ -1,4 +1,4 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@@ -6,28 +6,25 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class ECNCongressAlgorithm implements CongressAlgorithm {
public class DCTCPCongestionAlgorithm implements CongestionAlgorithm {
private static final long BURST_TIME = 2000000L;
private static final long BURST_TIME = 1000000L;
private static final long BIAS = 2000000L;
private static long MIN_SPEED = 64 * 1024L;
private static long MIN_WINDOW = 16384;
private static long MIN_WINDOW = 32768;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 50000000L;
private long MIN_RTTVAR = 400000000L;
private volatile long RTTMin = 1000000000L;
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L;
private double ECNAvg2 = 0L;
private double alpha=0;
private volatile AtomicLong RTTTotal = new AtomicLong(0);
private volatile AtomicLong ECNSize = new AtomicLong(0);
private volatile AtomicLong TotalSize = new AtomicLong(0);
private volatile AtomicLong RTTCount = new AtomicLong(0);
private volatile long RTO = 1000000000L;
@@ -39,11 +36,10 @@ public class ECNCongressAlgorithm implements CongressAlgorithm {
private long RTTstartTime = System.nanoTime();
private long bandwidth=MIN_SPEED;
private double MAX_GAIN=1.2;//2.8853900817779
private double MAX_GAIN=2.8853900817779;//2.8853900817779
private double MIN_GAIN=1.2;
private double gain=MAX_GAIN;
private ReentrantLock lock=new ReentrantLock();
@Override
public void reset() {
window = MIN_WINDOW;
@@ -77,51 +73,48 @@ public class ECNCongressAlgorithm implements CongressAlgorithm {
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);// RTTVar*4
RTTTotal .addAndGet( latencyns);
if(ecn) {
ECNSize.addAndGet(packetSize);
}
TotalSize.addAndGet(packetSize);
RTTCount.incrementAndGet();
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTAvg2) {
if(curr-RTTstartTime>(RTTAvg+BIAS)) {
RTTstartTime=curr;
lock.lock();
try {
if(RTTCount.get()>0) {
long count=RTTCount.getAndSet(0);
RTTAvg2=RTTTotal.getAndSet(0)/count;
ECNAvg2=ECNSize.getAndSet(0)/(double)TotalSize.getAndSet(0);
alpha=(alpha*15+ECNAvg2)/16;
//System.out.println(alpha);
long totalSize=TotalSize.getAndSet(0);
long ecnSize=ECNSize.getAndSet(0);
if(totalSize!=0) {
ECNAvg2=ecnSize/(double)totalSize;
alpha=(alpha*15+ECNAvg2)/16;
}
if(ECNAvg2>0.5) {
if(ECNAvg2>0.6) {
gain=MIN_GAIN;
if(congressWindowSize>MIN_WINDOW) {
congressWindowSize=Math.max(MIN_WINDOW,(long) (congressWindowSize*(1-alpha/5)));
congressWindowSize=Math.max(MIN_WINDOW,(long) (congressWindowSize*(1-alpha/10)));
updateWindowSize();
}
}else if(ECNAvg2>0.05){
}else if(ECNAvg2>0.2){
if(windowUsed*3L>=congressWindowSize) {
congressWindowSize+=100;
congressWindowSize+=200;
updateWindowSize();
}
}else {
if(windowUsed*3L>=congressWindowSize) {
congressWindowSize+=4000;
congressWindowSize+=8000;
updateWindowSize();
}
}
//System.out.println(ECNAvg2);
//System.out.println(speed+" "+window);
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
} else {
@@ -132,11 +125,9 @@ public class ECNCongressAlgorithm implements CongressAlgorithm {
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}finally {
lock.unlock();
}
}
//System.out.println(speed+" "+window);
}
@@ -0,0 +1,6 @@
package org.kne.cloud.network.congestion;
public interface DetnetCongestionAlgorithm extends CongestionAlgorithm {
public void setUpperDelayBound(double upper);
public void setLowerDelayBound(double lower);
}
@@ -1,9 +1,9 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class EmptyCongressAlgorithm implements CongressAlgorithm{
public class EmptyCongestionAlgorithm implements CongestionAlgorithm{
private long timeout;
@@ -53,7 +53,7 @@ public class EmptyCongressAlgorithm implements CongressAlgorithm{
}
public EmptyCongressAlgorithm(long timeout) {
public EmptyCongestionAlgorithm(long timeout) {
super();
this.timeout = timeout;
}
@@ -0,0 +1,72 @@
package org.kne.cloud.network.congestion;
import java.util.List;
import java.util.function.Consumer;
/**
* 消息批处理器接口
* 提供批量消息处理功能,支持按数量和时间触发批量发送
*/
public interface MessageBatcher<T> {
// ==================== 配置相关方法 ====================
/**
* 获取批处理大小
* @return 批处理大小
*/
int getBatchSize();
/**
* 获取最大延迟时间
* @return 最大延迟时间(纳秒)
*/
long getMaxDelay();
/**
* 设置消息消费者回调函数
* @param consumer 消费者回调
*/
void setConsumer(Consumer<List<T>> consumer);
// ==================== 消息操作方法 ====================
/**
* 添加消息到批处理器
* @param message 消息对象
*/
void putMessage(T message);
/**
* 批量添加消息
* @param messages 消息列表
*/
void putMessages(List<T> messages);
/**
* 立即刷新并发送所有待处理消息
*/
void flush();
// ==================== 状态查询方法 ====================
/**
* 获取当前队列中的消息数量
* @return 队列大小
*/
int getQueueSize();
// ==================== 生命周期管理方法 ====================
/**
* 检查批处理器是否停止
* @return 是否停止
*/
boolean isClosed();
/**
* 停止批处理器
*/
void close();
}
@@ -1,4 +1,4 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
@@ -1,4 +1,4 @@
package org.kne.cloud.network.congress;
package org.kne.cloud.network.congestion;
import java.util.Iterator;
import java.util.Objects;
@@ -0,0 +1,221 @@
package org.kne.cloud.network.congestion;
import java.io.Closeable;
import java.io.IOException;
import java.net.SocketException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ThreadTool;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.klalb.SendItem;
public class SendPacketSlidingWindow<K, V extends NetworkPacket> implements Closeable, AutoCloseable {
private Map<K, SendItem<V>> sendMap = new ConcurrentHashMap<>(1024, 0.2f);
private AtomicLong sendmapWindowUsed=new AtomicLong(0);
//private LongAdder sendmapWindowUsed = new LongAdder();
private int headerCalibrate = 0;
public void setHeaderCalibrate(int headerCalibrate) {
this.headerCalibrate = headerCalibrate;
}
private CongestionAlgorithm algorithm;
private Consumer<V> resendConsumer;
private Consumer<V> closingConsumer;
private volatile boolean closed = false;
private ResendChecker checker = new ResendChecker();
private AtomicLong windowSize = new AtomicLong();
private Lock lock;
private Condition condition;
private boolean removeAtResend;
public SendPacketSlidingWindow(CongestionAlgorithm algorithm, long windowSize) {
this(algorithm, windowSize, 0, true);
}
public SendPacketSlidingWindow(CongestionAlgorithm algorithm, long windowSize, int headerCalibrate) {
this(algorithm, windowSize, headerCalibrate, true);
}
public SendPacketSlidingWindow(CongestionAlgorithm algorithm, long windowSize, int headerCalibrate,
boolean removeAtResend) {
this.headerCalibrate = headerCalibrate;
this.removeAtResend = removeAtResend;
this.algorithm = algorithm;
this.windowSize.set(windowSize);
Thread t = ThreadTool.makeVThread("重路由计时器线程", checker);
t.start();
}
public long getWindowSize() {
return windowSize.get();
}
public void setWindowSize(long windowSize) {
this.windowSize.set(windowSize);
}
public Consumer<V> getResendConsumer() {
return resendConsumer;
}
public void setResendConsumer(Consumer<V> resendConsumer) {
this.resendConsumer = resendConsumer;
}
public Consumer<V> getClosingConsumer() {
return closingConsumer;
}
public void setClosingConsumer(Consumer<V> closingConsumer) {
this.closingConsumer = closingConsumer;
}
public long getSendmapWindowUsed() {
return sendmapWindowUsed.get();
}
public int getHeaderCalibrate() {
return headerCalibrate;
}
public CongestionAlgorithm getAlgorithm() {
return algorithm;
}
public boolean isCongress(IPv6Packet iPv6Packet, double scale) {
boolean congress = sendmapWindowUsed.get() > windowSize.get() * scale;
return congress;
}
public void put(K sequence, V packet) {
SendItem<V> newitem = new SendItem<V>(packet);
SendItem<V> old = sendMap.put(sequence, newitem);
long dx=0;
if (old != null) {
dx=-(old.getPacketLength() + headerCalibrate);
}
long newWindow =sendmapWindowUsed.addAndGet(newitem.getPacketLength() + headerCalibrate+dx);
algorithm.setCurrentWindowUsed(newWindow);
}
public V ack(K sequence) {
return ack(sequence,false);
}
public V ack(K sequence,boolean ecn) {
SendItem<V> ipv6;
if ((ipv6 = sendMap.remove(sequence)) != null) {
long newWindow =sendmapWindowUsed.addAndGet(-(ipv6.getPacketLength() + headerCalibrate));
algorithm.setCurrentWindowUsed(newWindow);
long RTTC = System.nanoTime() - ipv6.getSendtime();
algorithm.putAck(ipv6.getPacketLength(), RTTC, ecn);
// System.out.println("remove:"+aseq.getSequence()+" "+sendMap.size());
Lock lockx = lock;
if (lockx != null) {
lockx.lock();
try {
Condition cds = condition;
if (cds != null) {
cds.signalAll();
}
} finally {
lockx.unlock();
}
}
return ipv6.getPacket();
} else {
// System.out.println("miss:"+aseq.getSequence()+" "+sendMap.size());
return null;
}
}
private class ResendChecker implements Runnable {
@Override
public void run() {
while (!closed) {
Collection<SendItem<V>> vals = sendMap.values();
for (Iterator<SendItem<V>> iterator = vals.iterator(); iterator.hasNext();) {
SendItem<V> sitm = (SendItem<V>) iterator.next();
long current = System.nanoTime();
if (current - sitm.getSendtime() > algorithm.getRTO()) {
if (removeAtResend) {
iterator.remove();
long newWindow = sendmapWindowUsed.addAndGet((int) -(sitm.getPacketLength() + headerCalibrate));
algorithm.setCurrentWindowUsed(newWindow);
} else {
sitm.setSendtime(current);
}
V pktr = sitm.getPacket();
if (resendConsumer != null)
resendConsumer.accept(pktr);
}
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 清理资源
if (closingConsumer != null) {
for (SendItem<V> item : sendMap.values()) {
closingConsumer.accept(item.getPacket());
}
}
sendMap.clear();
sendmapWindowUsed.set(0);
}
}
public boolean isClosed() {
return closed;
}
@Override
public void close() {
closed = true;
}
public void setCongressCondition(Lock lock2, Condition condition2) {
this.lock = lock2;
this.condition = condition2;
}
public Map<K, SendItem<V>> getSendmap() {
return sendMap;
}
public int getWindowPacketCount() {
return sendMap.size();
}
public boolean isEmpty() {
return sendMap.isEmpty();
}
@Override
public String toString() {
return "SendPacketSlidingWindow [sendmapWindowUsed=" + sendmapWindowUsed + ", windowSize=" + windowSize + "]";
}
}
@@ -0,0 +1,218 @@
package org.kne.cloud.network.congestion;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCongestionAlgorithm {
// 可配置的时延膨胀比上下限 - Vegas2.0核心参数
private double delayUpperBound = 1.20; // RTT上限为基础RTT的1.2倍
private double delayLowerBound = 1.15; // RTT下限为基础RTT的1.05倍
private static final long BURST_TIME = 2000000L;
private static final long BIAS = 500000L;
private static long MIN_SPEED = 256 * 1024L;
private static long MIN_WINDOW = 16384;
// 新增:窗口调整参数(可基于当前窗口大小动态调整)
private static final double WINDOW_ADJUST_FACTOR = 0.01; // 1%的窗口调整幅度
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate = new AtomicBoolean(true);
private long MIN_RTTVAR = 30000000L;
private volatile long RTTMin = 1000000000L; // BaseRTT
private volatile long RTTVar = 1000000000L;
private volatile long RTTAvg = 1000000000L;
private volatile long RTTAvg2 = 1000000000L; // 当前平滑RTT
private volatile long RTTTotal = 0;
private volatile long RTTCount = 0;
private volatile long RTO = 1000000000L;
private volatile long window = MIN_WINDOW;
private volatile long window2 = MIN_WINDOW;
private volatile long speed = MIN_SPEED;
private volatile long maxwindow = 99999999999L;
private long congressSpeed=MIN_SPEED;
public Vegas2CongestionAlgorithm() {
reset();
}
@Override
public void reset() {
window = MIN_WINDOW;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
speed = MIN_SPEED;
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer = windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer = speedControlConsumer;
}
private long RTTstartTime = System.nanoTime();
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
// 处理ECN信号 - 将其视为强烈的拥塞信号
if (ecn) {
// 当收到ECN时,更激进地减少窗口
window2 = Math.max(0, window2 * 3 / 4);
if (windowControlConsumer != null) {
windowControlConsumer.accept(window2);
}
}
// 更新最小RTTBaseRTT
if (latencyns <= RTTMin) {
RTTMin = latencyns;
} else {
// 缓慢适应:当网络路径真正变化时,BaseRTT应能缓慢更新
// 这里使用极慢的衰减因子,只有在持续观测到更低RTT时才快速更新
RTTMin = (RTTMin * 9999 + latencyns) / 10000;
}
// 更新平滑RTT估计
if (firstUpdate.compareAndSet(true, false)) {
RTTAvg = latencyns;
RTTVar = latencyns / 2;
RTTAvg2 = latencyns;
} else {
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - latencyns)) / 4;
RTTAvg = (RTTAvg * 7 + latencyns) / 8;
}
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);
RTTTotal += latencyns;
RTTCount++;
long curr = System.nanoTime();
// 每个RTT周期调整一次窗口(使用当前估计的RTT)
if (curr - RTTstartTime > Math.max(BIAS, RTTMin)) {
if (RTTCount > 0) {
long currentRTT = RTTTotal / RTTCount;
RTTAvg2 = (RTTAvg2 * 3 + currentRTT) / 4; // 平滑当前RTT
RTTTotal = 0;
RTTCount = 0;
}
// ================== Vegas2.0核心逻辑 ==================
// 1. 计算时延膨胀比
double delayRatio = (double) RTTAvg2 / (double) Math.max(BIAS, RTTMin);
// 2. 基于比值的窗口调整(取代原来的基于差值的调整)
long adjustStep = Math.max(512, (long)(window2 * WINDOW_ADJUST_FACTOR));
if (delayRatio > delayUpperBound) {
// 时延过高:减小窗口,减少幅度与超标程度成正比
double exceedRatio = delayRatio / delayUpperBound;
window2 -= (long)(adjustStep * exceedRatio);
} else if (delayRatio < delayLowerBound) {
// 时延过低:增大窗口,增加幅度与低于目标程度成正比
double belowRatio = delayLowerBound / delayRatio;
window2 += (long)(adjustStep * belowRatio);
} else {
// 在理想区间内:微调以维持稳定
// 计算目标RTT = BaseRTT × 目标膨胀比
long targetRTT = (long)(Math.max(BIAS, RTTMin) * (delayLowerBound + delayUpperBound) / 2.0);
if (RTTAvg2 > targetRTT) {
// 略高于目标:小幅减少
window2 = Math.max(0, window2 - 256);
} else if (RTTAvg2 < targetRTT) {
// 略低于目标:小幅增加
window2 = Math.min(maxwindow, window2 + 256);
}
// 非常接近目标:保持窗口不变
}
// ===================================================
// 窗口边界检查
if (window2 >= maxwindow) {
window2 = maxwindow;
}
if (window2 < 0) {
window2 = 0;
}
RTTstartTime = curr;
if (bandwidth >= congressSpeed) {
congressSpeed = bandwidth;
//congressSpeed = (congressSpeed + bandwidth) / 2;
} else {
congressSpeed = (congressSpeed * 49 + bandwidth) / 50;
}
// 速度计算:基于当前窗口和RTT,考虑一个安全边界
// 使用目标膨胀比而非固定1.2倍,确保与窗口控制逻辑一致
window=window2+MIN_WINDOW;
speed=(long) (congressSpeed * delayUpperBound)+MIN_SPEED ;
if (windowControlConsumer != null) {
windowControlConsumer.accept(window);
}
if (speedControlConsumer != null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
this.maxwindow = used * 16 + 65536;
}
private long bandwidth;
@Override
public void setCurrentBandwidth(long bandwidth) {
// 可选:基于已知带宽信息调整参数
this.bandwidth=bandwidth;
}
// 新增方法:获取当前状态信息(用于监控和调试)
public double getCurrentDelayRatio() {
return (double) RTTAvg2 / (double) Math.max(BIAS, RTTMin);
}
public long getBaseRTT() {
return RTTMin;
}
public long getCurrentRTT() {
return RTTAvg2;
}
@Override
public void setUpperDelayBound(double upper) {
delayUpperBound=upper;
}
@Override
public void setLowerDelayBound(double lower) {
delayLowerBound=lower;
}
}
@@ -1,203 +0,0 @@
package org.kne.cloud.network.congress;
import java.io.Closeable;
import java.io.IOException;
import java.net.SocketException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.klalb.SendItem;
public class SendPacketSlidingWindow <K,V extends NetworkPacket> implements Closeable,AutoCloseable{
private Map<K,SendItem<V>> sendMap= new ConcurrentHashMap<>(1024,0.2f);
//private AtomicInteger sendmapWindowUsed=new AtomicInteger(0);
private LongAdder sendmapWindowUsed=new LongAdder();
private int headerCalibrate=0;
public void setHeaderCalibrate(int headerCalibrate) {
this.headerCalibrate = headerCalibrate;
}
private CongressAlgorithm algorithm;
private Consumer<V> resendConsumer;
private Consumer<V> closingConsumer;
private volatile boolean closed=false;
private ResendChecker checker=new ResendChecker();
private AtomicLong windowSize = new AtomicLong();
private Lock lock;
private Condition condition;
public SendPacketSlidingWindow(CongressAlgorithm algorithm, long windowSize) {
super();
this.algorithm = algorithm;
this.windowSize .set( windowSize);
Thread t=new Thread(checker);
t.start();
}
public SendPacketSlidingWindow(CongressAlgorithm algorithm, long windowSize,int headerCalibrate) {
this(algorithm,windowSize);
this.headerCalibrate=headerCalibrate;
}
public long getWindowSize() {
return windowSize.get();
}
public void setWindowSize(long windowSize) {
this.windowSize.set(windowSize);
}
public Consumer<V> getResendConsumer() {
return resendConsumer;
}
public void setResendConsumer(Consumer<V> resendConsumer) {
this.resendConsumer = resendConsumer;
}
public Consumer<V> getClosingConsumer() {
return closingConsumer;
}
public void setClosingConsumer(Consumer<V> closingConsumer) {
this.closingConsumer = closingConsumer;
}
public long getSendmapWindowUsed() {
return sendmapWindowUsed.sum();
}
public int getHeaderCalibrate() {
return headerCalibrate;
}
public CongressAlgorithm getAlgorithm() {
return algorithm;
}
public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
boolean congress=sendmapWindowUsed.sum()>windowSize.get()*scale;
return congress;
}
public void put(K sequence,V packet) throws SocketException {
if(closed) {
throw new SocketException("sliding window closed!");
}
SendItem<V> newitem=new SendItem<V>( packet);
SendItem<V> old= sendMap.put(sequence,newitem);
if(old!=null) {
sendmapWindowUsed.add( -(old.getPacketLength()+headerCalibrate));
}
sendmapWindowUsed.add( (newitem.getPacketLength()+headerCalibrate));
long newWindow=sendmapWindowUsed.sum();
algorithm.setCurrentWindowUsed(newWindow);
}
public V ack(K sequence) {
SendItem<V> ipv6;
if((ipv6=sendMap.remove(sequence))!=null) {
sendmapWindowUsed.add( -(ipv6.getPacketLength()+headerCalibrate));
long newWindow= sendmapWindowUsed.sum();
algorithm.setCurrentWindowUsed(newWindow);
long RTTC=System.nanoTime()-ipv6.getSendtime();
algorithm.putAck(ipv6.getPacketLength(), RTTC, false);
//System.out.println("remove:"+aseq.getSequence()+" "+sendMap.size());
Lock lockx=lock;
if(lockx!=null) {
lockx.lock();
try {
Condition cds=condition;
if(cds!=null) {
cds.signalAll();
}
}finally {
lockx.unlock();
}
}
return ipv6.getPacket();
}else {
// System.out.println("miss:"+aseq.getSequence()+" "+sendMap.size());
return null;
}
}
private class ResendChecker implements Runnable{
@Override
public void run() {
while(!closed) {
Collection<SendItem<V>>vals= sendMap.values();
for (Iterator<SendItem<V>> iterator = vals.iterator(); iterator.hasNext();) {
SendItem<V> sitm = (SendItem<V>) iterator.next();
if(System.nanoTime() -sitm.getSendtime()>algorithm.getRTO()) {
iterator.remove();
sendmapWindowUsed.add((int) -(sitm.getPacketLength()+headerCalibrate));
long newWindow=sendmapWindowUsed.sum();
algorithm.setCurrentWindowUsed(newWindow);
//if(!kplink.isStream())
V pktr=sitm.getPacket();
pktr.setPriority(pktr.getPriority()-1);
if(resendConsumer!=null)
resendConsumer.accept(pktr);
//System.out.println("reroute");
}
}
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 清理资源
if (closingConsumer != null) {
for (SendItem<V> item : sendMap.values()) {
closingConsumer.accept(item.getPacket());
}
}
sendMap.clear();
sendmapWindowUsed.reset();
}
}
public boolean isClosed() {
return closed;
}
@Override
public void close() {
closed=true;
}
public void setCongressCondition(Lock lock2, Condition condition2) {
this.lock=lock2;
this.condition=condition2;
}
public Map<K, SendItem<V>> getSendmap() {
return sendMap;
}
}
@@ -1,132 +0,0 @@
package org.kne.cloud.network.congress;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
public class VegasCongressAlgorithm implements CongressAlgorithm {
private static final long BURST_TIME = 1000000L;
private static final long BIAS = 1000000L;
private static long MIN_SPEED=256*1024L;
private static long MIN_WINDOW=4096L;
private Consumer<Long> windowControlConsumer;
private BiConsumer<Long, Long> speedControlConsumer;
private AtomicBoolean firstUpdate=new AtomicBoolean(true);
private long MIN_RTTVAR=30000000L;
private volatile long RTTMin=1000000000L;
private volatile long RTTVar=1000000000L;
private volatile long RTTAvg=1000000000L;
private volatile long RTTAvg2=1000000000L;
private volatile long RTTTotal=0;
private volatile long RTTCount=0;
private volatile long RTO=1000000000L;
private volatile long window=MIN_WINDOW;
private volatile long speed=MIN_SPEED;
private volatile long maxwindow=99999999999L;
@Override
public void reset() {
window=MIN_WINDOW;
if(windowControlConsumer!=null) {
windowControlConsumer.accept(window);
}
speed=MIN_SPEED;
if(speedControlConsumer!=null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
}
@Override
public void setWindowControlConsumer(Consumer<Long> windowControlConsumer) {
this.windowControlConsumer=windowControlConsumer;
}
@Override
public void setSpeedControlConsumer(BiConsumer<Long, Long> speedControlConsumer) {
this.speedControlConsumer=speedControlConsumer;
}
private long RTTstartTime=System.nanoTime();
@Override
public synchronized void putAck(long packetSize, long latencyns, boolean ecn) {
if(latencyns<=RTTMin) {
RTTMin=latencyns;
}else {
RTTMin= (RTTMin*9999+latencyns)/10000;
}
if(firstUpdate.compareAndSet(true, false)) {
RTTAvg=latencyns;
RTTVar=latencyns/2;
RTTAvg2=latencyns;
}else {
RTTVar=(RTTVar*3+Math.abs(RTTAvg-latencyns))/4;
RTTAvg= (RTTAvg*7+latencyns)/8;
}
RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4
RTTTotal+=latencyns;
RTTCount++;
long curr=System.nanoTime();
if(curr-RTTstartTime>RTTMin) {
if(RTTCount>0) {
RTTAvg2=(RTTAvg2+RTTTotal/RTTCount)/2;
RTTTotal=0;
RTTCount=0;
}
double excepted=window/(double)(Math.max( BIAS,RTTMin));
double actual=window/(double)(RTTAvg2);
double diff=(excepted-actual)*(Math.max( BIAS,RTTMin));
//System.out.println("diff:"+diff);
if(diff>65536*3) {
window-=512;
}
if(diff<65536*2) {
window+=512;
}
if(window>=maxwindow){
window=maxwindow;
//System.out.println("window:"+window);
}
if(window<MIN_WINDOW) {
window=MIN_WINDOW;
//System.out.println("window:"+window);
}
RTTstartTime=curr;
if(windowControlConsumer!=null) {
windowControlConsumer.accept(window);
}
speed=Math.max(MIN_SPEED, (long) (window/(double)(RTTAvg2)*1000000000.0*1.2));
if(speedControlConsumer!=null) {
speedControlConsumer.accept(speed, BURST_TIME);
}
//System.out.println(speed+" "+window);
}
}
@Override
public void putLoss(long packetSize, long lossns, int losscounter) {
// TODO 自动生成的方法存根
}
@Override
public long getRTO() {
return RTO;
}
@Override
public void setCurrentWindowUsed(long used) {
this.maxwindow=used*16+65536;
}
@Override
public void setCurrentBandwidth(long bandwidth) {
// TODO 自动生成的方法存根
}
}
@@ -6,13 +6,27 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.kne.cloud.network.klalb.KLALBRemoteLine;
import org.kne.cloud.network.srv6.SRv6Router;
public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
private CopyOnWriteArraySet<IPv6LinkStateListener> listeners = new CopyOnWriteArraySet<>();
private SRv6Router srv6Router;
public SRv6Router getSrv6Router() {
return srv6Router;
}
public void setSRv6Router(SRv6Router srv6Router) {
this.srv6Router = srv6Router;
}
@Override
public void addIPv6LinkStateListener(IPv6LinkStateListener listener) {
listeners.add(listener);
@@ -40,4 +54,14 @@ public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
v.onAddressUpdate(this);
});
}
public BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> getReceiveConsumer() {
return receiveConsumer;
}
private BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> receiveConsumer;
@Override
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> receiveConsumer) {
this.receiveConsumer = receiveConsumer;
}
}
@@ -0,0 +1,16 @@
package org.kne.cloud.network.ipv6;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.Consumer;
public interface ControlledIPv6NetworkLink extends IPv6NetworkLink {
public boolean isCongress(IPv6Packet iPv6Packet,double scale);
public default boolean isCongress(IPv6Packet iPv6Packet) {
return isCongress(iPv6Packet, 1.0);
}
void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer);
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet);
public void setCongressCondition(Lock lock,Condition condition);
}
@@ -6,19 +6,19 @@ import java.net.InetAddress;
import java.util.Objects;
public class FlowSession implements Serializable{
private Inet6Address srcAddr;
private Inet6Address dstAddr;
private IPv6Address srcAddr;
private IPv6Address dstAddr;
private int flowLabel;
public FlowSession(Inet6Address srcAddr, Inet6Address dstAddr, int flowLabel) {
public FlowSession(IPv6Address srcAddr, IPv6Address dstAddr, int flowLabel) {
super();
this.srcAddr = srcAddr;
this.dstAddr = dstAddr;
this.flowLabel = flowLabel;
}
public Inet6Address getSrcAddr() {
public IPv6Address getSrcAddr() {
return srcAddr;
}
public Inet6Address getDstAddr() {
public IPv6Address getDstAddr() {
return dstAddr;
}
public int getFlowLabel() {
@@ -30,7 +30,12 @@ public class FlowSession implements Serializable{
}
@Override
public int hashCode() {
return Objects.hash(dstAddr, flowLabel, srcAddr);
final int prime = 31;
int result = 1;
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
result = prime * result + flowLabel;
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
@@ -41,8 +46,19 @@ public class FlowSession implements Serializable{
if (getClass() != obj.getClass())
return false;
FlowSession other = (FlowSession) obj;
return Objects.equals(dstAddr, other.dstAddr) && flowLabel == other.flowLabel
&& Objects.equals(srcAddr, other.srcAddr);
if (dstAddr == null) {
if (other.dstAddr != null)
return false;
} else if (!dstAddr.equals(other.dstAddr))
return false;
if (flowLabel != other.flowLabel)
return false;
if (srcAddr == null) {
if (other.srcAddr != null)
return false;
} else if (!srcAddr.equals(other.srcAddr))
return false;
return true;
}
}
@@ -1,5 +1,6 @@
package org.kne.cloud.network.ipv6;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
@@ -22,21 +23,38 @@ public class ICMPv6Packet extends IPv6Payload {
public static final int TYPE_PARAMETER_PROBLEM = 4;
public static final int TYPE_ECHO_REQUEST = 128;
public static final int TYPE_ECHO_REPLY = 129;
public static final int TYPE_POSTCARD = 253;
private ByteBuffer header = NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
private ByteBuffer header;
private ByteBuffer data;
public void setData(ByteBuffer data) {
this.data = data;
}
public ICMPv6Packet() {
private boolean isDefault;
protected ICMPv6Packet(ByteBuffer header,boolean isDefault) {
super(ICMPv6_PROTOCOL_NUMBER, false);
this.header=header;
this.isDefault=isDefault;
}
public ICMPv6Packet(int type, int code) {
this(type,code,true);
}
protected ICMPv6Packet(int type, int code,boolean isDefault) {
super(ICMPv6_PROTOCOL_NUMBER, false);
header = NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
getHeader().put((byte) type);
getHeader().put((byte) code);
// 校验和字段初始为0,后续计算
getHeader().putChar((char) 0);
this.isDefault=isDefault;
if(isDefault) {
data = NetworkPacket.bufferAllocator.allocate(65535);
}
}
@Override
@@ -50,7 +68,7 @@ public class ICMPv6Packet extends IPv6Payload {
public void writeToChannel(WritableByteChannel dto) throws IOException {
// 写入头部和数据
dto.write(getHeader().slice(0, ICMPv6_HEADER_LENGTH));
if (data != null && data.limit() > 0) {
if ( isDefault) {
dto.write(data.slice(0, data.limit()));
}
}
@@ -58,9 +76,9 @@ public class ICMPv6Packet extends IPv6Payload {
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
// 读取ICMPv6头部
getHeader().clear().limit(ICMPv6_HEADER_LENGTH);
getHeader().limit(ICMPv6_HEADER_LENGTH);
KNEChannels.readFully(din, getHeader());
getHeader().flip();
// 读取数据部分(总长度减去头部长度)
long dataLength = length - ICMPv6_HEADER_LENGTH;
@@ -68,18 +86,16 @@ public class ICMPv6Packet extends IPv6Payload {
throw new IOException("Invalid ICMPv6 packet: total length < header length");
}
if (dataLength > 0) {
if (isDefault) {
data = NetworkPacket.bufferAllocator.allocate((int) dataLength);
KNEChannels.readFully(din, data);
data.flip();
} else {
data = null;
}
}
}
@Override
protected boolean needEndPosition() {
return false;
return true;
}
/**
@@ -167,17 +183,10 @@ public class ICMPv6Packet extends IPv6Payload {
// 临时将校验和字段设为0
setChecksum(0);
long sum = 0;
// IPv6伪首部
byte[] srcAddr = new byte[16], dstAddr = new byte[16];
getParent().getRawSourceAddress(srcAddr);
getParent().getRawDestinationAddress(dstAddr);
for (int i = 0; i < 16; i += 2) {
sum += ((srcAddr[i] & 0xFF) << 8) | (srcAddr[i + 1] & 0xFF);
sum += ((dstAddr[i] & 0xFF) << 8) | (dstAddr[i + 1] & 0xFF);
}
long sum = getParent().calculateAddressChecksum();
// ICMPv6报文长度
int totalLength = (int) getTotalLength();
@@ -281,4 +290,26 @@ public class ICMPv6Packet extends IPv6Payload {
public ByteBuffer getHeader() {
return header;
}
public static ICMPv6Packet readICMPv6PacketFromChannel(ReadableByteChannel din, int payloadlength) throws EOFException, IOException {
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
bb.position(0);
bb.limit(ICMPv6_HEADER_LENGTH);
KNEChannels.readFully(din, bb);
int type=bb.get(0)&0xff;
switch(type) {
case ICMPv6TimeExceededPacket.TYPE_TIME_EXCEEDED:
ICMPv6TimeExceededPacket timeExceed=new ICMPv6TimeExceededPacket(bb);
timeExceed.readFromChannel(din, payloadlength);
return timeExceed;
case ICMPv6PostcardPacket.TYPE_POSTCARD:
ICMPv6PostcardPacket postcards=new ICMPv6PostcardPacket(bb);
postcards.readFromChannel(din, payloadlength);
return postcards;
default:
ICMPv6Packet icmp=new ICMPv6Packet(bb, true);
icmp.readFromChannel(din, payloadlength);
return icmp;
}
}
}
@@ -0,0 +1,62 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.List;
import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
public class ICMPv6PostcardPacket extends ICMPv6Packet {
private List<PostcardEntry> postcards=new ArrayList<>();
protected ICMPv6PostcardPacket(ByteBuffer header) {
super(header, false);
}
public ICMPv6PostcardPacket(int code) {
super(ICMPv6Packet.TYPE_POSTCARD, code, false);
}
public ICMPv6PostcardPacket() {
this(0);
}
public List<PostcardEntry> getPostcards() {
return postcards;
}
@Override
public long getTotalLength() {
return ICMPv6Packet.ICMPv6_HEADER_LENGTH+postcards.size()*PostcardEntry.POSTCARD_ENTRY_SIZE;
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
super.writeToChannel(dto);
for(PostcardEntry postcard:postcards) {
postcard.writeToChannel(dto);
}
}
@Override
public String toString() {
return "ICMPv6PostcardPacket [postcards=" + postcards + ", getTotalLength()=" + getTotalLength() + "]";
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
postcards.clear();
int count= (int) ((length-ICMPv6Packet.ICMPv6_HEADER_LENGTH)/PostcardEntry.POSTCARD_ENTRY_SIZE);
for(int i=0;i<count;i++) {
PostcardEntry pe=new PostcardEntry();
pe.readFromChannel(din);
postcards.add(pe);
}
}
}
@@ -7,7 +7,6 @@ import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
public class ICMPv6TimeExceededPacket extends ICMPv6Packet {
private static final int UNUSED_FIELD_LENGTH = 4; // 未使用字段长度
// 代码值常量
public static final int CODE_HOP_LIMIT_EXCEEDED = 0; // 跳数限制超时
@@ -18,7 +17,11 @@ public class ICMPv6TimeExceededPacket extends ICMPv6Packet {
setUnused(0);
}
/**
public ICMPv6TimeExceededPacket(ByteBuffer bb) {
super(bb, true);
}
/**
* 获取未使用字段(通常为0)
*/
public int getUnused() {
@@ -0,0 +1,400 @@
package org.kne.cloud.network.ipv6;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.klalb.KLALBUtils;
/**
* 高性能IPv6地址实现,使用两个long代替byte[16]
* 大幅减少GC压力和提高路由表查找性能
*/
public final class IPv6Address implements Comparable<IPv6Address> {
private final long high;
private final long low;
// 常用常量地址
public static final IPv6Address LOOPBACK = new IPv6Address(0, 1);
public static final IPv6Address UNSPECIFIED = new IPv6Address(0, 0);
public static final IPv6Address LOCALHOST = LOOPBACK;
// IPv4映射的IPv6地址前缀
private static final long IPV4_MAPPED_HIGH = 0x0000_0000_0000_0000L;
private static final long IPV4_MAPPED_LOW_PREFIX = 0x0000_0000_FFFF_0000L;
// 构造方法
public IPv6Address(long high, long low) {
this.high = high;
this.low = low;
}
public IPv6Address(Inet6Address address) {
this(address.getAddress());
}
public IPv6Address(byte[] bytes) {
if (bytes.length != 16) {
throw new IllegalArgumentException("IPv6 address must be 16 bytes");
}
this. high = ((long)(bytes[0] & 0xFF) << 56) |
((long)(bytes[1] & 0xFF) << 48) |
((long)(bytes[2] & 0xFF) << 40) |
((long)(bytes[3] & 0xFF) << 32) |
((long)(bytes[4] & 0xFF) << 24) |
((long)(bytes[5] & 0xFF) << 16) |
((long)(bytes[6] & 0xFF) << 8) |
((long)(bytes[7] & 0xFF));
this.low = ((long)(bytes[8] & 0xFF) << 56) |
((long)(bytes[9] & 0xFF) << 48) |
((long)(bytes[10] & 0xFF) << 40) |
((long)(bytes[11] & 0xFF) << 32) |
((long)(bytes[12] & 0xFF) << 24) |
((long)(bytes[13] & 0xFF) << 16) |
((long)(bytes[14] & 0xFF) << 8) |
((long)(bytes[15] & 0xFF));
}
/**
* 从两个long创建IPv6地址
*/
public static IPv6Address valueOf(long high, long low) {
return new IPv6Address(high, low);
}
/**
* 从byte[16]创建IPv6地址(高性能版本)
*/
public static IPv6Address valueOf(byte[] bytes) {
return new IPv6Address(bytes);
}
/**
* 从ByteBuffer创建IPv6地址(零拷贝友好)
*/
public static IPv6Address valueOf(ByteBuffer buffer) {
if (buffer.remaining() < 16) {
throw new IllegalArgumentException("Buffer must have at least 16 bytes remaining");
}
long high = buffer.getLong();
long low = buffer.getLong();
return valueOf(high, low);
}
public static IPv6Address valueOf(int offset, ByteBuffer buffer) {
long high = buffer.getLong(offset);
long low = buffer.getLong(offset+8);
return valueOf(high, low);
}
/**
* 从字符串解析IPv6地址(高性能版本)
* @throws UnknownHostException
*/
public static IPv6Address valueOf(String ipString) throws UnknownHostException {
if (ipString == null || ipString.isEmpty()) {
throw new IllegalArgumentException("Invalid IPv6 address string");
}
return new IPv6Address((Inet6Address)Inet6Address.getByName(ipString));
}
/**
* 从Java InetAddress转换
*/
public static IPv6Address valueOf(InetAddress inetAddress) {
if (inetAddress == null) {
throw new IllegalArgumentException("InetAddress cannot be null");
}
byte[] bytes = inetAddress.getAddress();
if (bytes.length == 4) {
// IPv4地址,转换为IPv4映射的IPv6地址
return valueOf(IPV4_MAPPED_HIGH,
IPV4_MAPPED_LOW_PREFIX |
(((long)(bytes[0] & 0xFF) << 24) |
((bytes[1] & 0xFF) << 16) |
((bytes[2] & 0xFF) << 8) |
(bytes[3] & 0xFF)));
}
return valueOf(bytes);
}
// 核心getter方法
public long getHigh() {
return high;
}
public long getLow() {
return low;
}
/**
* 转换为byte[16](需要时使用)
*/
public byte[] toByteArray() {
byte[] bytes = new byte[16];
toByteArray(bytes, 0);
return bytes;
}
/**
* 写入到现有byte数组(避免创建新对象)
*/
public void toByteArray(byte[] dest, int offset) {
if (dest.length - offset < 16) {
throw new IllegalArgumentException("Destination array too small");
}
dest[offset] = (byte) (high >> 56);
dest[offset + 1] = (byte) (high >> 48);
dest[offset + 2] = (byte) (high >> 40);
dest[offset + 3] = (byte) (high >> 32);
dest[offset + 4] = (byte) (high >> 24);
dest[offset + 5] = (byte) (high >> 16);
dest[offset + 6] = (byte) (high >> 8);
dest[offset + 7] = (byte) high;
dest[offset + 8] = (byte) (low >> 56);
dest[offset + 9] = (byte) (low >> 48);
dest[offset + 10] = (byte) (low >> 40);
dest[offset + 11] = (byte) (low >> 32);
dest[offset + 12] = (byte) (low >> 24);
dest[offset + 13] = (byte) (low >> 16);
dest[offset + 14] = (byte) (low >> 8);
dest[offset + 15] = (byte) low;
}
/**
* 写入到ByteBuffer(高性能网络操作)
*/
public void writeTo(ByteBuffer buffer) {
buffer.putLong(high);
buffer.putLong(low);
}
public void writeTo(int offset, ByteBuffer buffer) {
buffer.putLong(offset,high);
buffer.putLong(offset+8,low);
}
/**
* 转换为标准IPv6字符串表示
*/
@Override
public String toString() {
try {
return Inet6Address.getByAddress(toByteArray()).getHostAddress();
} catch (UnknownHostException e) {
return "Internal Error";
}
}
/**
* 转换为压缩形式的字符串(::格式)
*/
public String toCompressedString() {
return KLALBUtils.parseAbbrIPv6(toString());
}
/**
* 检查是否为IPv4映射地址
*/
public boolean isIPv4MappedAddress() {
return high == IPV4_MAPPED_HIGH &&
(low & 0x0000_0000_FFFF_0000L) == IPV4_MAPPED_LOW_PREFIX;
}
/**
* 如果这是IPv4映射地址,提取IPv4部分
*/
public byte[] getIPv4Bytes() {
if (!isIPv4MappedAddress()) {
throw new IllegalStateException("Not an IPv4 mapped address");
}
byte[] ipv4 = new byte[4];
ipv4[0] = (byte) (low >> 24);
ipv4[1] = (byte) (low >> 16);
ipv4[2] = (byte) (low >> 8);
ipv4[3] = (byte) low;
return ipv4;
}
/**
* 检查是否为多播地址
*/
public boolean isMulticastAddress() {
return (high & 0xFF00_0000_0000_0000L) == 0xFF00_0000_0000_0000L;
}
/**
* 检查是否为链路本地地址
*/
public boolean isLinkLocalAddress() {
return (high & 0xFFC0_0000_0000_0000L) == 0xFE80_0000_0000_0000L;
}
/**
* 检查是否为站点本地地址(已弃用,但为了兼容性保留)
*/
public boolean isSiteLocalAddress() {
return (high & 0xFFC0_0000_0000_0000L) == 0xFEC0_0000_0000_0000L;
}
/**
* 检查是否为唯一本地地址 (ULA)
*/
public boolean isUniqueLocalAddress() {
return (high & 0xFE00_0000_0000_0000L) == 0xFC00_0000_0000_0000L;
}
/**
* 检查是否为环回地址
*/
public boolean isLoopbackAddress() {
return this.equals(LOOPBACK);
}
/**
* 检查是否为未指定地址
*/
public boolean isUnspecifiedAddress() {
return this.equals(UNSPECIFIED);
}
/**
* 获取多播地址的scope
*/
public int getMulticastScope() {
if (!isMulticastAddress()) {
return -1;
}
return (int) ((low >> 48) & 0x0F);
}
// 路由表相关的实用方法
/**
* 创建掩码(用于CIDR表示法)
*/
public static IPv6Address createMask(int prefixLength) {
if (prefixLength < 0 || prefixLength > 128) {
throw new IllegalArgumentException("Prefix length must be between 0 and 128");
}
long maskHigh, maskLow;
if (prefixLength == 128) {
maskHigh = -1L; // 0xFFFFFFFF_FFFFFFFF
maskLow = -1L;
} else if (prefixLength > 64) {
maskHigh = -1L;
maskLow = (-1L) << (64 - (prefixLength - 64));
} else if (prefixLength == 64) {
maskHigh = -1L;
maskLow = 0;
} else {
maskHigh = (-1L) << (64 - prefixLength);
maskLow = 0;
}
return valueOf(maskHigh, maskLow);
}
/**
* 应用掩码(用于网络地址计算)
*/
public IPv6Address maskWith(IPv6Address mask) {
return valueOf(high & mask.high, low & mask.low);
}
/**
* 检查地址是否在指定网络内
*/
public boolean isInNetwork(IPv6Address network, IPv6Address mask) {
IPv6Address maskedThis = this.maskWith(mask);
IPv6Address maskedNetwork = network.maskWith(mask);
return maskedThis.equals(maskedNetwork);
}
/**
* 检查地址是否在指定CIDR网络内
*/
public boolean isInNetwork(IPv6Address network, int prefixLength) {
IPv6Address mask = createMask(prefixLength);
return isInNetwork(network, mask);
}
// 比较和哈希
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
IPv6Address other = (IPv6Address) obj;
return high == other.high && low == other.low;
}
@Override
public int hashCode() {
// 优化的哈希计算,考虑long的分布
return (int) (high ^ (high >>> 32) ^ low ^ (low >>> 32));
}
@Override
public int compareTo(IPv6Address other) {
int highCompare = Long.compareUnsigned(high, other.high);
if (highCompare != 0) return highCompare;
return Long.compareUnsigned(low, other.low);
}
public static void main(String[] args) throws UnknownHostException {
// 创建IPv6地址
IPv6Address addr1 = IPv6Address.valueOf("2001:db8::1");
IPv6Address addr2 = IPv6Address.valueOf(0x20010DB800000000L, 0x0000000000000001L);
// 高性能路由表查找
IPv6Address target = IPv6Address.valueOf("2001:db8:1234::5678");
IPv6Address network = IPv6Address.valueOf("2001:db8:1234::");
int prefixLength = 64;
if (target.isInNetwork(network, prefixLength)) {
System.out.println("地址在目标网络内");
}
// 转换为字节数组(需要时)
byte[] bytes = addr1.toByteArray();
// 直接写入ByteBuffer(零拷贝)
ByteBuffer buffer = ByteBuffer.allocateDirect(16);
addr1.writeTo(buffer);
}
public Inet6Address toInet6Address() {
try {
return (Inet6Address) Inet6Address.getByAddress(toByteArray());
} catch (UnknownHostException e) {
return null;
}
}
public boolean isAnyLocalAddress() {
return high==0&&low==0;
}
}
@@ -0,0 +1,73 @@
package org.kne.cloud.network.ipv6;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
public class IPv6AddressGroup implements Comparable<IPv6AddressGroup>{
public IPv6AddressGroup(IPv6Address address) {
this(address, 128);
}
@Override
public String toString() {
return address+"/"+prefixLength;
}
@Override
public int hashCode() {
return Objects.hash(address, prefixLength);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IPv6AddressGroup other = (IPv6AddressGroup) obj;
return Objects.equals(address, other.address) && prefixLength == other.prefixLength;
}
public IPv6AddressGroup(IPv6Address address, int prefixLength) {
super();
this.address = address;
this.prefixLength = prefixLength;
}
public IPv6AddressGroup(DataInputStream in) throws IOException {
readFromStream(in);
}
private IPv6Address address;
private int prefixLength=128;
public IPv6Address getAddress() {
return address;
}
public int getPrefixLength() {
return prefixLength;
}
@Override
public int compareTo(IPv6AddressGroup o) {
return -Integer.compare(prefixLength, o.prefixLength);
}
public void writeToStream(DataOutputStream out) throws IOException {
out.writeLong(address.getHigh());
out.writeLong(address.getLow());
out.write(prefixLength);
}
public void readFromStream(DataInputStream in) throws IOException {
long high=in.readLong();
long low=in.readLong();
address=new IPv6Address(high,low);
prefixLength=in.read();
}
public boolean checkMatch(IPv6Address address2) {
return address2.equals(address.maskWith(IPv6Address.createMask(prefixLength)));
}
}
@@ -13,6 +13,8 @@ public class IPv6HopByHopTLV extends TLV {
public static final int PADN = 1;
public static final int JUMBO_PAYLOAD = 0xC2;
public static final int ROUTER_ALERT = 0x05;
public static final int KLALB_OAM = 0x3E;
public static final int KLALB_PASSPORT = 0x1E;
public IPv6HopByHopTLV(ByteBuffer header) {
this(header, true);
@@ -62,6 +64,16 @@ public class IPv6HopByHopTLV extends TLV {
htlv = new JumboPayloadHopByHopTLV(bbf, true);
htlv.readFromChannel(din, 0);
return htlv;
case KLALB_OAM:
// KLALB OAM
htlv = new KLALBOAMHopByHopTLV(bbf);
htlv.readFromChannel(din, 0);
return htlv;
case KLALB_PASSPORT:
// KLALB Passport
htlv = new KLALBPassportHopByHopTLV(bbf);
htlv.readFromChannel(din, 0);
return htlv;
default:
// 未知类型: 假设有数据部分
htlv = new IPv6HopByHopTLV(bbf, true);
@@ -5,29 +5,29 @@ import java.net.Inet6Address;
import java.util.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.klalb.KLALBPacket;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
import org.kne.cloud.network.srv6.SRv6Router;
public interface IPv6NetworkLink {
public SRv6Router getSrv6Router() ;
public void setSRv6Router(SRv6Router srv6Router) ;
public boolean isLoopBack();
public List<Inet6AddressGroup> getAddressGroups();
public List<IPv6AddressGroup> getAddressGroups();
public List<Neighbor> getNeighborsInfo();
public List<RouteItem> getRouteItems();
public void sendPacket(IPv6Packet pack, Inet6Address inet6Address) throws IOException;
public boolean isCongress(IPv6Packet iPv6Packet,double scale);
public default boolean isCongress(IPv6Packet iPv6Packet) {
return isCongress(iPv6Packet, 1.0);
}
public void sendPacket(IPv6Packet pack, IPv6Address inet6Address) throws IOException;
public String getName();
public boolean isUp();
public void setReceiveConsumer(Consumer<IPv6Packet>con);
void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer);
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet);
public void setCongressCondition(Lock lock,Condition condition);
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> srhReceive);
public void addIPv6LinkStateListener(IPv6LinkStateListener listener);
public void removeIPv6LinkStateListener(IPv6LinkStateListener listener);
}
+156 -85
View File
@@ -12,6 +12,7 @@ import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -35,6 +36,8 @@ import org.pcap4j.packet.namednumber.IpNumber;
*/
public class IPv6Packet extends NetworkPacket {
private static final boolean debug=false;
// ==================== IPv6扩展头类型 ====================
/** 逐跳选项头 - RFC 8200 */
@@ -238,17 +241,6 @@ public class IPv6Packet extends NetworkPacket {
this.previousLink = previousLink;
}
// 流序列标记,用于标识数据包在流中的顺序
private long flowSeqMark = -1;
public long getFlowSeqMark() {
return flowSeqMark;
}
public void setFlowSeqMark(long flowSeqMark) {
this.flowSeqMark = flowSeqMark;
}
// TTL是否已减少的标志
private boolean TTLdecreased = false;
@@ -261,14 +253,19 @@ public class IPv6Packet extends NetworkPacket {
}
// IPv6头部数据缓冲区
private volatile ByteBuffer IPv6header;
private ByteBuffer IPv6header;
private IPv6HopByHopHeader hopByHopHeader;
private IPv6RoutingHeader routingHeader;
// IPv6扩展头部列表
private volatile List<IPv6ExtHeader> headers = new ArrayList<>();
private List<IPv6ExtHeader> headers = new ArrayList<>();
// IPv6负载数据
private IPv6Payload payload;
// IPv6头部固定长度
public static final int IPv6_HEADER_LENGTH = 40;
@@ -289,7 +286,6 @@ public class IPv6Packet extends NetworkPacket {
*/
public IPv6Packet() {
IPv6header = NetworkPacket.bufferAllocator.allocate(IPv6_HEADER_LENGTH);
IPv6header.limit(IPv6_HEADER_LENGTH);
}
/**
@@ -354,7 +350,7 @@ public class IPv6Packet extends NetworkPacket {
*/
public void markCE() {
IPv6header.put(1, (byte) (IPv6header.get(1) | 0b00110000));
// new Exception().printStackTrace();
// new Exception().printStackTrace();
}
/**
@@ -434,7 +430,7 @@ public class IPv6Packet extends NetworkPacket {
* 获取原始源地址字节数组
* @param sourceAddress 用于存储源地址的字节数组
*/
public void getRawSourceAddress(byte[] sourceAddress) {
public void getRawSourceAddressArray(byte[] sourceAddress) {
IPv6header.get(SOURCE_ADDRESS_OFFSET, sourceAddress, 0, sourceAddress.length);
}
@@ -442,21 +438,15 @@ public class IPv6Packet extends NetworkPacket {
* 设置原始源地址字节数组
* @param sourceAddress 源地址字节数组
*/
public void setRawSourceAddress(byte[] sourceAddress) {
public void setRawSourceAddressArray(byte[] sourceAddress) {
IPv6header.put(SOURCE_ADDRESS_OFFSET, sourceAddress, 0, sourceAddress.length);
}
public IPv6RouteTableKey getSourceRouteTableKey() {
long most=IPv6header.getLong(SOURCE_ADDRESS_OFFSET);
long least=IPv6header.getLong(SOURCE_ADDRESS_OFFSET+8);
return new IPv6RouteTableKey(most, least);
}
/**
* 获取原始目标地址字节数组
* @param destinationAddress 用于存储目标地址的字节数组
*/
public void getRawDestinationAddress(byte[] destinationAddress) {
public void getRawDestinationAddressArray(byte[] destinationAddress) {
IPv6header.get(DESTINATION_ADDRESS_OFFSET, destinationAddress, 0, destinationAddress.length);
}
@@ -465,22 +455,49 @@ public class IPv6Packet extends NetworkPacket {
* 设置原始目标地址字节数组
* @param destinationAddress 目标地址字节数组
*/
public void setRawDestinationAddress(byte[] destinationAddress) {
public void setRawDestinationAddressArray(byte[] destinationAddress) {
IPv6header.put(DESTINATION_ADDRESS_OFFSET, destinationAddress, 0, destinationAddress.length);
}
/**
* 获取原始源地址字节数组
* @param sourceAddress 用于存储源地址的字节数组
* @return
*/
public IPv6Address getSourceAddress() {
return IPv6Address.valueOf(SOURCE_ADDRESS_OFFSET,IPv6header);
}
/**
* 设置原始源地址字节数组
* @param sourceAddress 源地址字节数组
*/
public void setSourceAddress(IPv6Address sourceAddress) {
sourceAddress.writeTo(SOURCE_ADDRESS_OFFSET,IPv6header);
}
public IPv6RouteTableKey getDestinationRouteTableKey() {
long most=IPv6header.getLong(DESTINATION_ADDRESS_OFFSET);
long least=IPv6header.getLong(DESTINATION_ADDRESS_OFFSET+8);
return new IPv6RouteTableKey(most, least);
}
/**
* 获取原始目标地址字节数组
* @param destinationAddress 用于存储目标地址的字节数组
*/
public IPv6Address getDestinationAddress() {
return IPv6Address.valueOf(DESTINATION_ADDRESS_OFFSET,IPv6header);
}
/**
* 设置原始目标地址字节数组
* @param destinationAddress 目标地址字节数组
*/
public void setDestinationAddress(IPv6Address destinationAddress) {
destinationAddress.writeTo(DESTINATION_ADDRESS_OFFSET,IPv6header);
}
/**
* 获取源地址
* @return 源地址
*/
public Inet6Address getSourceAddress() {
public Inet6Address getSourceAddress2() {
byte[] b = new byte[IPV6_ADDRESS_LENGTH];
IPv6header.get(SOURCE_ADDRESS_OFFSET, b, 0, b.length);
try {
@@ -494,7 +511,7 @@ public class IPv6Packet extends NetworkPacket {
* 设置源地址
* @param sourceAddress 源地址
*/
public void setSourceAddress(Inet6Address sourceAddress) {
public void setSourceAddress2(Inet6Address sourceAddress) {
byte[] b = sourceAddress.getAddress();
IPv6header.put(SOURCE_ADDRESS_OFFSET, b, 0, b.length);
}
@@ -503,7 +520,7 @@ public class IPv6Packet extends NetworkPacket {
* 获取目标地址
* @return 目标地址
*/
public Inet6Address getDestinationAddress() {
public Inet6Address getDestinationAddress2() {
byte[] b = new byte[IPV6_ADDRESS_LENGTH];
IPv6header.get(DESTINATION_ADDRESS_OFFSET, b, 0, b.length);
try {
@@ -517,7 +534,7 @@ public class IPv6Packet extends NetworkPacket {
* 设置目标地址
* @param destinationAddress 目标地址
*/
public void setDestinationAddress(Inet6Address destinationAddress) {
public void setDestinationAddress2(Inet6Address destinationAddress) {
byte[] b = destinationAddress.getAddress();
IPv6header.put(DESTINATION_ADDRESS_OFFSET, b, 0, b.length);
}
@@ -539,7 +556,11 @@ public class IPv6Packet extends NetworkPacket {
private int calcPayloadLength() {
int lth = 0;
for (int i = 0; i < headers.size(); i++) {
lth += headers.get(i).getTotalLength();
int extHeaderLength=(int) headers.get(i).getTotalLength();
if(extHeaderLength<=0) {
throw new IllegalArgumentException("extHeaderLength:"+extHeaderLength+"<0");
}
lth += extHeaderLength;
}
lth += payload.getTotalLength();
return lth;
@@ -578,6 +599,9 @@ public class IPv6Packet extends NetworkPacket {
exth.writeToChannel(dto);
}
payload.writeToChannel(dto);
if(debug)
debug("send");
}
/**
@@ -607,6 +631,7 @@ public class IPv6Packet extends NetworkPacket {
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
hopByHopHeader=(IPv6HopByHopHeader) ext;
break;
case DESTINATION_OPTIONS: // 目标选项头部
ext = new IPv6DestinationHeader();
@@ -637,6 +662,7 @@ public class IPv6Packet extends NetworkPacket {
nextheader = ext.getNextHeader();
payloadlength -= ext.getTotalLength();
headers.add(ext);
routingHeader=(IPv6RoutingHeader) ext;
break;
case FRAGMENT: // 分段头部
ext = new IPv6ExtHeader(nextheader);
@@ -666,12 +692,16 @@ public class IPv6Packet extends NetworkPacket {
payloadlength -= ext.getTotalLength();
headers.add(ext);
break;
case ICMPv6:
ICMPv6Packet icmp=ICMPv6Packet.readICMPv6PacketFromChannel(din,payloadlength);
icmp.setParent(this);
this.payload=icmp;
break loop;
case UDP: // UDP协议
UDPPacket up=new UDPPacket();
up.setParent(this);
up.readFromChannel(din,payloadlength);
this.payload=up;
UDPPacket udp=new UDPPacket();
udp.setParent(this);
udp.readFromChannel(din,payloadlength);
this.payload=udp;
break loop;
case KLALBPacket.KLALB_PROTOCOL_NUMBER: // KLALB协议
KLALBPacket kp = KLALBPacket.readKLALBPacketFromChannel(din);
@@ -689,9 +719,24 @@ public class IPv6Packet extends NetworkPacket {
break loop;
}
}
if(debug)
debug("recv");
}
private void debug(String description) {
StringBuilder sb=new StringBuilder();
sb.append(description);
sb.append(" total:");
sb.append(getPayloadLength());
sb.append(" ");
for (IPv6ExtHeader iPv6ExtHeader : headers) {
sb.append(iPv6ExtHeader.getTotalLength());
sb.append(' ');
}
if(payload!=null)
sb.append(payload.getTotalLength());
System.out.println(sb);
}
/**
* 转换为字符串表示
@@ -1062,7 +1107,7 @@ public class IPv6Packet extends NetworkPacket {
*/
public static class IPv6SegmentRoutingHeader extends IPv6RoutingHeader {
private final List<Inet6Address> addresses = new ArrayList<Inet6Address>();
private final List<IPv6Address> addresses = new ArrayList<IPv6Address>();
private final List<IPv6SegmentRoutingTLV> tlvs = new ArrayList<IPv6SegmentRoutingTLV>();
@Override
@@ -1083,7 +1128,7 @@ public class IPv6Packet extends NetworkPacket {
super(EXT_HEADER_ALIGNMENT, bbf);
}
public IPv6SegmentRoutingHeader(List<Inet6Address> segs) {
public IPv6SegmentRoutingHeader(List<IPv6Address> segs) {
this();
this.addresses.addAll(segs);
int ln = addresses.size() - 1;
@@ -1115,7 +1160,7 @@ public class IPv6Packet extends NetworkPacket {
getData().putShort(6, (short) tag);
}
public List<Inet6Address> getAddresses() {
public List<IPv6Address> getAddresses() {
return addresses;
}
@@ -1134,9 +1179,12 @@ public class IPv6Packet extends NetworkPacket {
setLastEntry(addresses.size() - 1);
super.writeToChannel(dto);
for (Inet6Address inet6Address : addresses) {
dto.write(ByteBuffer.wrap(inet6Address.getAddress()));
ByteBuffer addr=NetworkPacket.bufferAllocator.allocateHeap(addresses.size() *IPV6_ADDRESS_LENGTH);
for (IPv6Address inet6Address : addresses) {
inet6Address.writeTo(addr);
}
addr.flip();
dto.write(addr);
for (IPv6SegmentRoutingTLV tlv : tlvs) {
IPv6SegmentRoutingTLV.writeIPv6SegmentRoutingTLVToChannel(dto, tlv);
}
@@ -1200,15 +1248,12 @@ public class IPv6Packet extends NetworkPacket {
}
addresses.clear();
bfr = NetworkPacket.bufferAllocator.allocateHeap(IPV6_ADDRESS_LENGTH);
for (int i = 0; i <= laste; i++) { // 注意:应该是 <= laste
bfr.clear();
KNEChannels.readFully(din, bfr);
bfr.flip();
bfr = NetworkPacket.bufferAllocator.allocateHeap(IPV6_ADDRESS_LENGTH*(laste+1));
KNEChannels.readFully(din, bfr);
bfr.flip();
usdl += bfr.limit();
Inet6Address addr = (Inet6Address) Inet6Address.getByAddress(bfr.array());
addresses.add(addr);
for (int i = 0; i <= laste; i++) { // 注意:应该是 <= laste
addresses.add(IPv6Address.valueOf(bfr));
}
tlvs.clear();
@@ -1290,38 +1335,59 @@ public class IPv6Packet extends NetworkPacket {
* @return IPv6段逐跳头部,如果不存在则返回null
*/
public IPv6HopByHopHeader getHopByHopHeader() {
IPv6HopByHopHeader hoph = null;
List<IPv6ExtHeader> exhs = headers;
for (int j = 0; j < exhs.size(); j++) {
IPv6ExtHeader exh = exhs.get(j);
if (exh instanceof IPv6HopByHopHeader) {
hoph=(IPv6HopByHopHeader) exh;
break;
}
}
return hoph;
return hopByHopHeader;
}
/**
* 获取路由头部
* @return 路由头部,如果不存在则返回null
*/
public IPv6RoutingHeader getRoutingHeader() {
return routingHeader;
}
/**
public void setHopByHopHeader(IPv6HopByHopHeader hopByHopHeader) {
this.hopByHopHeader = hopByHopHeader;
}
public void setRoutingHeader(IPv6RoutingHeader routingHeader) {
this.routingHeader = routingHeader;
}
/**
* 获取SRv6段路由头部
* @return SRv6段路由头部,如果不存在则返回null
*/
public IPv6SegmentRoutingHeader getSRHHeader() {
IPv6SegmentRoutingHeader srhh = null;
List<IPv6ExtHeader> exhs = headers;
for (int j = 0; j < exhs.size(); j++) {
IPv6ExtHeader exh = exhs.get(j);
if (exh instanceof IPv6SegmentRoutingHeader) {
if (((IPv6SegmentRoutingHeader) exh).getRoutingType() == SRV6_ROUTING_TYPE) {
srhh = (IPv6SegmentRoutingHeader) exh;
break;
public IPv6SegmentRoutingHeader getSegmentRoutingHeader() {
IPv6RoutingHeader rh=getRoutingHeader();
if(rh==null)
return null;
IPv6SegmentRoutingHeader srhh=null;
if (rh instanceof IPv6SegmentRoutingHeader) {
if (((IPv6SegmentRoutingHeader) rh).getRoutingType() == SRV6_ROUTING_TYPE) {
srhh = (IPv6SegmentRoutingHeader) rh;
}
}
}
return srhh;
}
public UUID getPacketID() {
IPv6HopByHopHeader hop=getHopByHopHeader();
if(hop==null)
return null;
List<IPv6HopByHopTLV> tlvs= hop.getTlvs();
for(IPv6HopByHopTLV tlv:tlvs) {
if(tlv instanceof KLALBOAMHopByHopTLV)
return ((KLALBOAMHopByHopTLV)tlv).getUUID();
}
return null;
}
@Override
protected boolean needEndPosition() {
return false;
@@ -1334,16 +1400,21 @@ public class IPv6Packet extends NetworkPacket {
return rerouteCounter;
}
// 承诺标志,用于某种状态跟踪
private volatile boolean promise = true;
public long calculateAddressChecksum() {
long sum=0;
ByteBuffer dataCopy = IPv6header.slice(SOURCE_ADDRESS_OFFSET,32);
while (dataCopy.remaining() >= 2) {
sum += dataCopy.getChar();
}
if (dataCopy.remaining() == 1) {
sum += (dataCopy.get() & 0xFF) << 8;
}
return sum;
}
public void setPromise(boolean b) {
promise = b;
}
public boolean isPromise() {
return promise;
}
@@ -1,305 +0,0 @@
package org.kne.cloud.network.ipv6;
import java.net.Inet6Address;
import java.util.Objects;
public class IPv6RouteTableKey {
private long most;
private long least;
public IPv6RouteTableKey(byte[] address) {
long[] l = inet6AddressToLongs(address);
this.most = l[0];
this.least = l[1]; // 修复:应该是 l[1] 而不是 l[0]
}
public IPv6RouteTableKey(long most, long least) {
super();
this.most = most;
this.least = least;
}
public IPv6RouteTableKey(Inet6Address address) {
this(address.getAddress());
}
public IPv6RouteTableKey(Inet6AddressGroup address) {
this(address.getAddress());
applyMask(address.getPrefixLength());
}
public long getMost() {
return most;
}
public long getLeast() {
return least;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (least ^ (least >>> 32));
result = prime * result + (int) (most ^ (most >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IPv6RouteTableKey other = (IPv6RouteTableKey) obj;
if (least != other.least)
return false;
if (most != other.most)
return false;
return true;
}
/**
* 根据前缀长度应用掩码,仅保留网络部分
* @param prefixLength 前缀长度 (0-128)
* @return 应用掩码后的新 IPv6RouteTableKey 对象
*/
public IPv6RouteTableKey mask(int prefixLength) {
if (prefixLength < 0 || prefixLength > 128) {
throw new IllegalArgumentException("前缀长度必须在 0 到 128 之间");
}
if (prefixLength == 0) {
return new IPv6RouteTableKey(0L, 0L); // 默认路由
}
long maskedMost = this.most;
long maskedLeast = this.least;
if (prefixLength <= 64) {
// 仅影响高位
long mask = createMask(prefixLength);
maskedMost &= mask;
maskedLeast = 0L; // 低位全部清零
} else {
// 影响高位和部分低位
int lowPrefixLength = prefixLength - 64;
long lowMask = createMask(lowPrefixLength);
maskedLeast &= lowMask;
// 高位保持不变
}
return new IPv6RouteTableKey(maskedMost, maskedLeast);
}
/**
* 根据前缀长度应用掩码,仅保留网络部分
* @param prefixLength 前缀长度 (0-128)
* @return 应用掩码后的新 IPv6RouteTableKey 对象
*/
public void applyMask(int prefixLength) {
if (prefixLength < 0 || prefixLength > 128) {
throw new IllegalArgumentException("前缀长度必须在 0 到 128 之间");
}
if (prefixLength == 0) {
this.most=0;
this.least=0;
return;
//return new IPv6RouteTableKey(0L, 0L); // 默认路由
}
long maskedMost = this.most;
long maskedLeast = this.least;
if (prefixLength <= 64) {
// 仅影响高位
long mask = createMask(prefixLength);
maskedMost &= mask;
maskedLeast = 0L; // 低位全部清零
} else {
// 影响高位和部分低位
int lowPrefixLength = prefixLength - 64;
long lowMask = createMask(lowPrefixLength);
maskedLeast &= lowMask;
// 高位保持不变
}
this.most=maskedMost;
this.least=maskedLeast;
// return new IPv6RouteTableKey(maskedMost, maskedLeast);
}
/**
* 创建指定长度的掩码
* @param bits 要保留的位数 (0-64)
* @return 掩码值
*/
private long createMask(int bits) {
// 使用查表法,预先计算所有可能的掩码值
return MASK_TABLE[bits];
}
// 预计算的掩码表
private static final long[] MASK_TABLE = new long[65]; // 0-64 共65个值
// 静态初始化块,在类加载时预计算所有掩码值
static {
for (int bits = 0; bits <= 64; bits++) {
if (bits == 0) {
MASK_TABLE[bits] = 0L;
} else if (bits == 64) {
MASK_TABLE[bits] = -1L;
} else {
MASK_TABLE[bits] = (-1L) << (64 - bits);
}
}
}
/**
* 将 byte[] 转换为两个 long 值(高位和低位)
* @param bytes 16字节的IPv6地址
* @return 包含两个long值的数组,第一个是高位,第二个是低位
*/
public static long[] inet6AddressToLongs(byte[] bytes) {
if (bytes.length != 16) {
throw new IllegalArgumentException("IPv6地址必须是16字节");
}
long high = 0;
long low = 0;
// 处理前8字节(高位)
for (int i = 0; i < 8; i++) {
high = (high << 8) | (bytes[i] & 0xFF);
}
// 处理后8字节(低位)
for (int i = 8; i < 16; i++) {
low = (low << 8) | (bytes[i] & 0xFF);
}
return new long[]{high, low};
}
/**
* 将两个long值转换回byte[]
* @param high 高位long值
* @param low 低位long值
* @return 16字节的IPv6地址
*/
public static byte[] longsToInet6Address(long high, long low) {
byte[] bytes = new byte[16];
// 提取高位的8个字节
for (int i = 0; i < 8; i++) {
bytes[i] = (byte) ((high >> (56 - i * 8)) & 0xFF);
}
// 提取低位的8个字节
for (int i = 0; i < 8; i++) {
bytes[8 + i] = (byte) ((low >> (56 - i * 8)) & 0xFF);
}
return bytes;
}
@Override
public String toString() {
return String.format("%016x:%016x", most, least);
}
/**
* 单元测试
*/
public static void main(String[] args) {
for(int i=0;i<65;i++) {
long l=MASK_TABLE[i];
System.out.println(Long.toUnsignedString(l, 16));
}
System.out.println("开始 IPv6RouteTableKey 单元测试...");
// 测试1: 基本转换测试
System.out.println("\n1. 测试基本转换:");
byte[] testAddress = new byte[16];
// 创建测试地址: 2001:0db8:85a3::8a2e:0370:7334
testAddress[0] = 0x20; testAddress[1] = 0x01;
testAddress[2] = 0x0d; testAddress[3] = (byte) 0xb8;
testAddress[4] = (byte) 0x85; testAddress[5] = (byte) 0xa3;
// 中间部分为0
testAddress[12] = (byte) 0x8a; testAddress[13] = 0x2e;
testAddress[14] = 0x03; testAddress[15] = 0x70;
// testAddress[16] = 0x73; testAddress[17] = 0x34; // 注意: 数组只有16个元素
IPv6RouteTableKey key = new IPv6RouteTableKey(testAddress);
System.out.println("原始地址: " + key);
// 测试2: 掩码应用测试
System.out.println("\n2. 测试掩码应用:");
IPv6RouteTableKey masked64 = key.mask(64);
System.out.println("/64 掩码: " + masked64);
IPv6RouteTableKey masked48 = key.mask(48);
System.out.println("/48 掩码: " + masked48);
IPv6RouteTableKey masked128 = key.mask(128);
System.out.println("/128 掩码: " + masked128);
IPv6RouteTableKey masked0 = key.mask(0);
System.out.println("/0 掩码: " + masked0);
// 测试3: 相等性测试
System.out.println("\n3. 测试相等性:");
IPv6RouteTableKey key2 = new IPv6RouteTableKey(testAddress);
System.out.println("相同地址是否相等: " + key.equals(key2));
System.out.println("哈希码是否相同: " + (key.hashCode() == key2.hashCode()));
// 测试4: 转换函数测试
System.out.println("\n4. 测试转换函数:");
long[] longs = inet6AddressToLongs(testAddress);
System.out.println("转换为longs: " + Long.toHexString(longs[0]) + ":" + Long.toHexString(longs[1]));
byte[] reconverted = longsToInet6Address(longs[0], longs[1]);
boolean conversionOk = true;
for (int i = 0; i < 16; i++) {
if (testAddress[i] != reconverted[i]) {
conversionOk = false;
break;
}
}
System.out.println("转换是否可逆: " + conversionOk);
// 测试5: 边界条件测试
System.out.println("\n5. 测试边界条件:");
try {
key.applyMask(-1);
System.out.println("错误: 应该抛出异常");
} catch (IllegalArgumentException e) {
System.out.println("正确: 负前缀长度抛出异常");
}
try {
key.applyMask(129);
System.out.println("错误: 应该抛出异常");
} catch (IllegalArgumentException e) {
System.out.println("正确: 过大前缀长度抛出异常");
}
// 测试6: 全零和全一地址测试
System.out.println("\n6. 测试特殊地址:");
byte[] allZeros = new byte[16];
IPv6RouteTableKey zeroKey = new IPv6RouteTableKey(allZeros);
System.out.println("全零地址: " + zeroKey);
byte[] allOnes = new byte[16];
for (int i = 0; i < 16; i++) allOnes[i] = (byte) 0xFF;
IPv6RouteTableKey onesKey = new IPv6RouteTableKey(allOnes);
System.out.println("全一地址: " + onesKey);
System.out.println("\n所有测试完成!");
}
}
@@ -2,156 +2,147 @@ package org.kne.cloud.network.ipv6;
import java.io.Closeable;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6HopByHopHeader;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.klalb.CONST;
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
import org.kne.cloud.network.srv6.DetNetSRv6TLV;
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
import org.kne.cloud.network.srv6.IpV6RoutingSRHData;
import org.kne.cloud.network.srv6.PacketConsumer;
import org.kne.cloud.network.srv6.PacketReorder;
import org.kne.cloud.network.srv6.SEQSSegmentRoutingTLV;
import org.kne.cloud.network.srv6.SRv6PacketReorder;
import org.kne.cloud.network.srv6.SRv6PacketSeqMarker;
import org.kne.cloud.network.srv6.SRv6Router;
import org.kne.cloud.network.srv6.SRv6StreamSequenceTLV;
import org.kne.cloud.network.srv6.SRv6TLV;
import org.kne.cloud.network.srv6.TCPTransimitAgent;
import org.kne.cloud.network.tun.InetAddressRow;
import org.kne.cloud.network.tun.TUNChannel;
import org.kne.cloud.network.tun.TUNNetworkDevice;
import org.kne.concurrent.DisruptorExecutor;
import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.concurrent.SpinLock;
import org.kne.io.KNEChannels;
public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implements IPv6NetworkLink, Closeable, AutoCloseable {
public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink
implements IPv6NetworkLink, Closeable, AutoCloseable {
public static final String KLALB_DECENTRALIZED_S_RV6_NETWORK = "KLALB Decentralized SRv6 Network";
public static final String KLALB_S_RV6 = "KLALB SRv6";
private TUNNetworkDevice tun;
private Inet6AddressGroup hostAddress;
private IPv6AddressGroup hostAddress;
private Thread tr;
private Lock slok=new SpinLock();
private SRv6PacketSeqMarker seqm=new SRv6PacketSeqMarker();
public IPv6TUNLoopbackNetworkLink(Inet6AddressGroup hostAddress, int mtu,List<InetAddress>dns) throws IOException {
private Lock slok = new SpinLock();
public IPv6TUNLoopbackNetworkLink(String name,IPv6AddressGroup hostAddress, int mtu, List<InetAddress> dns) throws IOException {
if (tun != null)
throw new IllegalStateException("already open!");
try {
tun = TUNNetworkDevice.createDevice(KLALB_S_RV6, KLALB_DECENTRALIZED_S_RV6_NETWORK);
tun.open();
tun.setStatus(true);
this.hostAddress = hostAddress;
if (hostAddress != null)
tun.setIPAddress(hostAddress.getAddress(), hostAddress.getPrefixLength());
if(dns!=null) {
tun.setDNSAddress(dns);
}
try {
tun.setMTU(mtu);
}catch(IOException e) {
e.printStackTrace();
}
Thread tb = new Thread(() -> {
while (true) {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
try {
tun.read(tmp);
tmp.flip();
//System.out.println(tmp);
if (IPv6Packet.getIPVersion(tmp.get(0)) == 6) {
HighPerformanceExecutor.defaultExecutor.execute(() -> {
tun = TUNNetworkDevice.createDevice(name, CONST.KLALB_DECENTRALIZED_S_RV6_NETWORK);
this.hostAddress = hostAddress;
if (hostAddress != null) {
List<InetAddressRow>rows=new ArrayList<>();
rows.add(new InetAddressRow(hostAddress.getAddress().toInet6Address(), hostAddress.getPrefixLength()));
tun.setIPAddress(rows);
}
if (dns != null) {
tun.setDNSAddress(dns);
}
try {
tun.setMTU(mtu);
} catch (IOException e) {
e.printStackTrace();
}
TUNChannel channel= tun.openSession();
Thread tb = new Thread(() -> {
while (true) {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
try {
channel.read(tmp);
tmp.flip();
// System.out.println(tmp);
if (IPv6Packet.getIPVersion(tmp.get(0)) == 6) {
try {
IPv6Packet ipp = new IPv6Packet();
ipp.readFromChannel(KNEChannels.newReadableChannel(tmp), mtu);
//NetworkPacket.databufferpool_65535.back(tmp);
if (con != null) {
monitor.getOutPacketCounterAL().add(1);
monitor.getOutTrafficAL().add(ipp.getTotalLength());
// ipp.setDisposeAfterSend(true);
// ipp.getPayload().setDisposeAfterSend(true);
ipp.setPromise(true);
if(ipp.getPayload().getProtocolNumber()==6) {
seqm.mark(ipp);
}
con.accept(ipp);
// NetworkPacket.databufferpool_65535.back(tmp);
BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> con = super.getReceiveConsumer();
if (con != null) {
if (ipp.getPayload().getProtocolNumber() == 6) {
SRv6Router router = getSrv6Router();
if (router != null) {
router.insertHopByHopHeader(ipp);
}
}
con.accept(IPv6TUNLoopbackNetworkLink.this, () -> {
UUID pid = ipp.getPacketID();
if (pid != null) {
monitor.getUploadBandwidth().recordPacket(pid, (int) ipp.getTotalLength());
}
// ipp.setDisposeAfterSend(true);
// ipp.getPayload().setDisposeAfterSend(true);
return ipp;
});
} else {
//ipp.dispose();
// ipp.dispose();
}
} catch (IOException e) {
e.printStackTrace();
}
});
}else {
//NetworkPacket.databufferpool_65535.back(tmp);
} else {
// NetworkPacket.databufferpool_65535.back(tmp);
}
} catch (Exception e) {
// NetworkPacket.databufferpool_65535.back(tmp);
e.printStackTrace();
}
} catch (Exception e) {
//NetworkPacket.databufferpool_65535.back(tmp);
e.printStackTrace();
}
}
});
tb.setPriority(Thread.MAX_PRIORITY-1);
tb.start();
tr = new Thread(() -> {
while (true) {
ByteBuffer tmp = sendQueue.poll();
if (tmp != null) {
});
tb.setPriority(Thread.MAX_PRIORITY - 1);
tb.start();
tr = new Thread(() -> {
while (true) {
ByteBuffer tmp = sendQueue.poll();
if (tmp != null) {
slok.lock();
try {
tun.write(tmp);
channel.write(tmp);
} catch (IOException e) {
e.printStackTrace();
}finally {
} finally {
slok.unlock();
//NetworkPacket.databufferpool_65535.back(tmp);
}
} else {
for(SRv6PacketReorder spr:reorder.values()) {
try {
spr.runOrdering();
} catch (IOException e) {
e.printStackTrace();
// NetworkPacket.databufferpool_65535.back(tmp);
}
} else {
LockSupport.parkNanos(1000000L);
}
LockSupport.parkNanos(10000000L);
}
}
});
tr.setPriority(Thread.MAX_PRIORITY-1);
tr.start();
}catch(UnsatisfiedLinkError e) {
});
tr.setPriority(Thread.MAX_PRIORITY - 1);
tr.start();
} catch (UnsatisfiedLinkError e) {
throw new IOException(e);
}
onOnlineStateUpdate();
@@ -159,87 +150,64 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
private LinkedBlockingQueue<ByteBuffer> sendQueue = new LinkedBlockingQueue<ByteBuffer>();
private volatile Consumer<IPv6Packet> con;
private SpeedAndTrafficMonitorDataImpl monitor;
private ConcurrentHashMap<FlowSession, SRv6PacketReorder> reorder=new ConcurrentHashMap<>();
@Override
public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException {
if (tun != null) {
public void sendPacket(IPv6Packet pack, IPv6Address next) throws IOException {
if (tun != null) {
try {
// System.out.println("rev");
IPv6SegmentRoutingHeader srh= pack.getSRHHeader();
SEQSSegmentRoutingTLV seqs=null;
if(srh!=null) {
List<IPv6SegmentRoutingTLV> l=srh.getTlvs();
for (int i = 0; i < l.size(); i++) {
IPv6SegmentRoutingTLV tlv=l.get(i);
if(tlv instanceof SEQSSegmentRoutingTLV) {
seqs=(SEQSSegmentRoutingTLV) tlv;
break;
}
}
}
sendPacket0(pack,seqs);
} catch (IOException e) {
//NetworkPacket.databufferpool_65535.back(tmp);
e.printStackTrace();
}
try {
//pack.disposeAll();
} else {
//pack.disposeAll();
IPv6HopByHopHeader hbh = pack.getHopByHopHeader();
KLALBOAMHopByHopTLV oamtlv = null;
if (hbh != null) {
List<IPv6HopByHopTLV> ll = hbh.getTlvs();
for (int i = 0; i < ll.size(); i++) {
IPv6HopByHopTLV tlv = ll.get(i);
if (tlv instanceof KLALBOAMHopByHopTLV) {
oamtlv = (KLALBOAMHopByHopTLV) tlv;
break;
}
}
}
IPv6SegmentRoutingHeader srh = pack.getSegmentRoutingHeader();
DetNetSRv6TLV seqs = null;
if (srh != null) {
List<IPv6SegmentRoutingTLV> l = srh.getTlvs();
for (int i = 0; i < l.size(); i++) {
IPv6SegmentRoutingTLV tlv = l.get(i);
if (tlv instanceof DetNetSRv6TLV) {
seqs = (DetNetSRv6TLV) tlv;
break;
}
}
}
sendPacket0(pack, oamtlv, seqs);
} catch (IOException e) {
e.printStackTrace();
}
} else {
}
}
private void sendPacket0(IPv6Packet pack,SEQSSegmentRoutingTLV seqs) throws IOException {
private void sendPacket0(IPv6Packet pack, KLALBOAMHopByHopTLV oamtlv, DetNetSRv6TLV detNet) throws IOException {
if(seqs!=null&&seqs.isKeepOrder()) {
FlowSession fss=pack.getFlowSession();
SRv6PacketReorder newr= new SRv6PacketReorder(new PacketConsumer() {
@Override
public boolean accept(IPv6Packet packx) throws IOException {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
packx.writeToChannel(KNEChannels.newWritableChannel(tmp));
monitor.getInPacketCounterAL().add(1);
monitor.getInTrafficAL().add(packx.getTotalLength());
tmp.flip();
sendQueue.add(tmp);
LockSupport.unpark(tr);
return true;
}
});
SRv6PacketReorder olr=reorder.putIfAbsent(fss,newr);
if(olr==null) {
olr=newr;
}
olr.put(pack,seqs.getSequence());
}else {
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535);
pack.writeToChannel(KNEChannels.newWritableChannel(tmp));
monitor.getInPacketCounterAL().add(1);
monitor.getInTrafficAL().add(pack.getTotalLength());
tmp.flip();
sendQueue.add(tmp);
LockSupport.unpark(tr);
}
UUID pid = pack.getPacketID();
if (pid != null) {
monitor.getUploadBandwidth().recordPacket(pid, (int) pack.getTotalLength());
}
tmp.flip();
sendQueue.add(tmp);
LockSupport.unpark(tr);
}
private SRv6StreamSequenceTLV getStreamSequenceTLV(IpV6RoutingSRHData srh) {
@@ -261,15 +229,15 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
@Override
public List<Neighbor> getNeighborsInfo() {
List<Neighbor> hs = new ArrayList<>();
//if (hostAddress != null)
//hs.put(hostAddress, null);
// if (hostAddress != null)
// hs.put(hostAddress, null);
return hs;
}
@Override
public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
return sendQueue.size() > 1000*scale;
}
/*
* @Override public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
* return sendQueue.size() > 1000*scale; }
*/
@Override
public String getName() {
@@ -289,11 +257,6 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
onOnlineStateUpdate();
}
@Override
public void setReceiveConsumer(Consumer<IPv6Packet> con) {
this.con = con;
}
public void setMonitor(SpeedAndTrafficMonitorDataImpl monitor) {
this.monitor = monitor;
}
@@ -303,49 +266,31 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
}
@Override
public List< Inet6AddressGroup> getAddressGroups() {
public List<IPv6AddressGroup> getAddressGroups() {
return List.of(hostAddress);
}
@Override
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
}
@Override
public List<RouteItem> getRouteItems() {
List<RouteItem> rlist=new ArrayList<>();
for(Inet6AddressGroup grp:getAddressGroups()) {
rlist.add(new RouteItem(new Inet6AddressGroup(grp.getAddress(), 128),
grp.getAddress(), this, "Direct", 0, 1, null, "D",true));
List<RouteItem> rlist = new ArrayList<>();
for (IPv6AddressGroup grp : getAddressGroups()) {
rlist.add(new RouteItem(new IPv6AddressGroup(grp.getAddress(), 128), grp.getAddress(), this, "Direct", 0, 1,
null, "D", true));
}
for (Iterator<Neighbor> iteratorx = getNeighborsInfo()
.iterator(); iteratorx.hasNext();) {
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(),
this, "Direct", 0, 128, addresses.getMonitor(), "D",false);
rlist.add(ri);
RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(),
this, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D",false);
rlist.add(ris);
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
addresses.getAddress().getAddress(), this, "Direct", 0, 128, addresses.getMonitor(), "D", false);
rlist.add(ri);
RouteItem ris = new RouteItem(addresses.getLocator(), addresses.getLocator().getAddress(), this,
"KLALB SRv6", 13, 128, addresses.getMonitor(), "D", false);
rlist.add(ris);
}
return rlist;
}
@Override
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
return false;
}
@Override
public void setCongressCondition(Lock lock, Condition condition) {
// TODO 自动生成的方法存根
}
}
@@ -1,142 +0,0 @@
package org.kne.cloud.network.ipv6;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
public class Inet6AddressGroup implements Comparable<Inet6AddressGroup>{
private static final byte[][] maskTransf=new byte[129][16];
static {
for (int i = 0; i < 129; i++) {
for(int j=0;j<i;j++) {
maskTransf[i][j/8]=(byte) (((0b10000000)>>>j%8)|maskTransf[i][j/8]);
}
}
/* for (int i = 0; i < maskTransf.length; i++) {
try {
System.out.println(InetAddress.getByAddress(maskTransf[i]));
} catch (UnknownHostException e) {
e.printStackTrace();
}
}*/
}
public Inet6AddressGroup(Inet6Address address) {
this(address, 128);
}
@Override
public String toString() {
return address.getHostAddress()+"/"+prefixLength;
}
@Override
public int hashCode() {
return Objects.hash(address, prefixLength);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Inet6AddressGroup other = (Inet6AddressGroup) obj;
return Objects.equals(address, other.address) && prefixLength == other.prefixLength;
}
public Inet6AddressGroup(Inet6Address address, int prefixLength) {
super();
this.address = address;
this.prefixLength = prefixLength;
}
public Inet6AddressGroup(DataInputStream in) throws IOException {
readFromStream(in);
}
private Inet6Address address;
private int prefixLength=128;
public Inet6Address getAddress() {
return address;
}
public int getPrefixLength() {
return prefixLength;
}
private byte[] cachedRawAddress;
public byte[] getRawAddress() {
if(cachedRawAddress==null) {
return (cachedRawAddress=address.getAddress());
}else {
return cachedRawAddress;
}
}
private byte[] cachedAndm;
private byte[] getAndm(byte[]mask) {
if(cachedAndm==null) {
return (cachedAndm=and0(mask ,getRawAddress()));
}else {
return cachedAndm;
}
}
public boolean checkMatch(Inet6Address ia) {
byte[]mask=maskTransf[prefixLength];
byte[]andm=getAndm(mask);
return andeq0(mask,ia.getAddress(),andm);
}
public boolean checkMatch(byte[] ia) {
byte[]mask=maskTransf[prefixLength];
byte[]andm=getAndm(mask);
return andeq0(mask,ia,andm);
}
private static boolean andeq0(byte[] bs, byte[] address2, byte[] andm) {
for (int i = 0; i < bs.length; i++) {
if(andm[i]!=(byte) (bs[i]&address2[i])) {
return false;
}
}
return true;
}
private static byte[] and0(byte[] bs, byte[] address2) {
byte[]rez=new byte[bs.length];
for (int i = 0; i < rez.length; i++) {
rez[i]=(byte) (bs[i]&address2[i]);
}
return rez;
}
@Override
public int compareTo(Inet6AddressGroup o) {
return -Integer.compare(prefixLength, o.prefixLength);
}
public void writeToStream(DataOutputStream out) throws IOException {
out.write(address.getAddress());
out.write(prefixLength);
}
public void readFromStream(DataInputStream in) throws IOException {
byte[]b=new byte[16];
in.readFully(b);
address=(Inet6Address) Inet6Address.getByAddress(b);
prefixLength=in.read();
}
public Inet6AddressGroup createPrefixOnlyAddressGroup(int newPrefixLength) {
byte[]mask=maskTransf[newPrefixLength];
byte[]andm=getAndm(mask);
try {
return new Inet6AddressGroup((Inet6Address) Inet6Address.getByAddress(andm), newPrefixLength);
} catch (UnknownHostException e) {
return null;
}
}
public Inet6AddressGroup createPrefixOnlyAddressGroup() {
return createPrefixOnlyAddressGroup(prefixLength);
}
public static void main(String[] args) throws UnknownHostException {
Inet6AddressGroup i6ag=new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("1234:1234::1234"),12);
System.out.println(i6ag);
System.out.println(i6ag.createPrefixOnlyAddressGroup());
}
}
@@ -0,0 +1,180 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.UUID;
public class KLALBOAMHopByHopTLV extends IPv6HopByHopTLV {
// 标志位掩码定义 - 移除了DetNet相关标志
public static final int FLAG_RECORD_PASSPORT = 0x01; // 第1位: 记录Passport
public static final int FLAG_POSTCARD_TO_SOURCE = 0x02; // 第2位: 向源地址回传Postcard
public static final int FLAG_POSTCARD_TO_PREV_HOP = 0x04; // 第3位: 向上一跳回传Postcard
// 保留其他位用于未来扩展 (0x08, 0x10, 0x20, 0x40, 0x80)
public KLALBOAMHopByHopTLV(ByteBuffer klalbHeader) {
super(klalbHeader);
}
@Override
public String toString() {
return "KLALBOAMHopByHopTLV [getVersion()=" + getVersion() + ", getFlags()=" + getFlags()
+ ", getInitialHops()=" + getInitialHops() + ", getUUID()=" + getUUID()
+ ", isRecordPassport()=" + isRecordPassport()
+ ", isPostcardToSource()=" + isPostcardToSource()
+ ", isPostcardToPreviousHop()=" + isPostcardToPreviousHop()
+ "]";
}
public KLALBOAMHopByHopTLV(int version, int flags, int initialHops, UUID uuid,long timestamp) {
super(IPv6HopByHopTLV.KLALB_OAM);
setVersion(version);
setFlags(flags);
setInitialHops(initialHops);
getData().put(3, (byte) 0);
getData().put(4, (byte) 0);
getData().put(5, (byte) 0);
setUUID(uuid);
setTimestamp(timestamp);
getData().limit(30);
}
/**
* 新的构造方法,通过boolean参数设置OAM测量相关的标志位
*
* @param version 版本号
* @param initialHops 初始跳数
* @param recordPassport 是否启用记录Passport
* @param postcardToSource 是否启用向源地址回传Postcard
* @param postcardToPreviousHop 是否启用向上一跳回传Postcard
* @param flowuuid 流UUID
* @param sequence 序列号
*/
public KLALBOAMHopByHopTLV(int version, int initialHops, boolean recordPassport, boolean postcardToSource,
boolean postcardToPreviousHop, UUID uuid ,long timestamp) {
super(IPv6HopByHopTLV.KLALB_OAM);
setVersion(version);
setInitialHops(initialHops);
// 根据boolean参数计算flags值
int flags = 0;
if (recordPassport) flags |= FLAG_RECORD_PASSPORT;
if (postcardToSource) flags |= FLAG_POSTCARD_TO_SOURCE;
if (postcardToPreviousHop) flags |= FLAG_POSTCARD_TO_PREV_HOP;
setFlags(flags);
// 设置保留字段为0
getData().put(3, (byte) 0);
getData().put(4, (byte) 0);
getData().put(5, (byte) 0);
setUUID(uuid);
setTimestamp(timestamp);
getData().limit(30);
}
public int getVersion() {
return getData().get(0) & 0xff;
}
public void setVersion(int version) {
getData().put(0, (byte) version);
}
public int getFlags() {
return getData().get(1) & 0xff;
}
public void setFlags(int flags) {
getData().put(1, (byte) flags);
}
public int getInitialHops() {
return getData().get(2) & 0xff;
}
public void setInitialHops(int initialHops) {
getData().put(2, (byte) initialHops);
}
public void setUUID(UUID uuid) {
getData().putLong(6, uuid.getMostSignificantBits());
getData().putLong(14, uuid.getLeastSignificantBits());
}
public UUID getUUID() {
return new UUID(getData().getLong(6), getData().getLong(14));
}
public long getTimestamp() {
return getData().getLong(22);
}
public void setTimestamp(long sequence) {
getData().putLong(22, sequence);
}
// 第1位: 记录Passport
public boolean isRecordPassport() {
return (getFlags() & FLAG_RECORD_PASSPORT) != 0;
}
public void setRecordPassport(boolean enabled) {
int flags = getFlags();
if (enabled) {
flags |= FLAG_RECORD_PASSPORT;
} else {
flags &= ~FLAG_RECORD_PASSPORT;
}
setFlags(flags);
}
// 第2位: 向源地址回传Postcard
public boolean isPostcardToSource() {
return (getFlags() & FLAG_POSTCARD_TO_SOURCE) != 0;
}
public void setPostcardToSource(boolean enabled) {
int flags = getFlags();
if (enabled) {
flags |= FLAG_POSTCARD_TO_SOURCE;
} else {
flags &= ~FLAG_POSTCARD_TO_SOURCE;
}
setFlags(flags);
}
// 第3位: 向上一跳回传Postcard
public boolean isPostcardToPreviousHop() {
return (getFlags() & FLAG_POSTCARD_TO_PREV_HOP) != 0;
}
public void setPostcardToPreviousHop(boolean enabled) {
int flags = getFlags();
if (enabled) {
flags |= FLAG_POSTCARD_TO_PREV_HOP;
} else {
flags &= ~FLAG_POSTCARD_TO_PREV_HOP;
}
setFlags(flags);
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
super.writeToChannel(dto);
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
}
}
@@ -0,0 +1,80 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
public class KLALBPassportHopByHopTLV extends IPv6HopByHopTLV {
public KLALBPassportHopByHopTLV(ByteBuffer buffer) {
super(buffer);
}
/**
* 构造方法 - 创建新的护照时间戳记录
*
* @param packetSize 包长度(2字节)
* @param timestampOffset 时间戳偏移量(4字节),相对于流开始时间
*/
public KLALBPassportHopByHopTLV(int packetSize, int timestampOffset) {
super(IPv6HopByHopTLV.KLALB_PASSPORT); // 护照记录类型
setPacketSize(packetSize);
setTimestampOffset(timestampOffset);
getData().limit(6); // 固定6字节数据
}
@Override
public String toString() {
return "KLALBPassportHopByHopTLV [packetLength=" + getPacketSize() +
", timestampOffset=" + getTimestampOffset() + "]";
}
/**
* 设置包长度(2字节,大端序)
* 范围: 0-65535字节
*/
public void setPacketSize(int packetSize) {
if (packetSize < 0 || packetSize > 65535) {
throw new IllegalArgumentException("Packet length must be between 0 and 65535");
}
getData().put(0, (byte) ((packetSize >> 8) & 0xFF));
getData().put(1, (byte) (packetSize & 0xFF));
}
/**
* 获取包长度(2字节,大端序)
*/
public int getPacketSize() {
return ((getData().get(0) & 0xFF) << 8) | (getData().get(1) & 0xFF);
}
/**
* 设置时间戳偏移量(4字节,有符号整数,大端序)
*/
public void setTimestampOffset(int timestampOffset) {
getData().putInt(2, timestampOffset);
}
/**
* 获取时间戳偏移量(4字节,有符号整数,大端序)
*/
public int getTimestampOffset() {
return getData().getInt(2);
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
super.writeToChannel(dto);
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
super.readFromChannel(din, length);
}
public long getTimestampOffsetLong() {
return ((long)getTimestampOffset())<<4;
}
}
@@ -9,7 +9,9 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.kne.cloud.network.srv6.PacketConsumer;
import org.kne.cloud.network.srv6.SRv6Router;
@@ -32,23 +34,18 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
return protocolNumberRegister;
}
private List<Inet6AddressGroup> addressGroups =new ArrayList<>();
private List<IPv6AddressGroup> addressGroups =new ArrayList<>();
//new Inet6AddressGroup(loopbackAddress, 128) new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("::1"), 128)
public LoopbackIPv6NetworkLink(List<Inet6AddressGroup> addressGroupsx,SRv6Router router) {
public LoopbackIPv6NetworkLink(List<IPv6AddressGroup> addressGroupsx,SRv6Router router) {
this.addressGroups .addAll( addressGroupsx);
}
public Consumer<IPv6Packet> getReceiveConsumer() {
return receiveConsumer;
}
private Consumer<IPv6Packet> receiveConsumer;
private Consumer<IPv6Packet> rerouteConsumer;
private SRv6Router router;
@Override
public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException {
public void sendPacket(IPv6Packet pack, IPv6Address next) throws IOException {
PacketConsumer pcm= protocolNumberRegister.get(pack.getPayload().getProtocolNumber());
if (pcm != null) {
if(!pcm.accept(pack)) {
@@ -74,10 +71,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
return hs;
}
@Override
public boolean isCongress(IPv6Packet iPv6Packet, double scale) {
return false;
}
@Override
public String getName() {
@@ -90,26 +83,18 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
}
@Override
public void setReceiveConsumer(Consumer<IPv6Packet> con) {
this.receiveConsumer = con;
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> con) {
super.setReceiveConsumer(con);
if(fallbackLink!=null) {
fallbackLink.setReceiveConsumer(con);
}
}
@Override
public List<Inet6AddressGroup> getAddressGroups() {
public List<IPv6AddressGroup> getAddressGroups() {
return addressGroups;
}
@Override
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
this.rerouteConsumer=rerouteConsumer;
if(fallbackLink!=null) {
fallbackLink.setRerouteConsumer(rerouteConsumer);
}
}
public Consumer<IPv6Packet> getRerouteConsumer() {
return rerouteConsumer;
}
@@ -117,20 +102,20 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
@Override
public List<RouteItem> getRouteItems() {
List<RouteItem> rlist = new ArrayList<>();
for(Inet6AddressGroup group:addressGroups) {
rlist.add(new RouteItem(new Inet6AddressGroup(group.getAddress(), 128),
for(IPv6AddressGroup group:addressGroups) {
rlist.add(new RouteItem(new IPv6AddressGroup(group.getAddress(), 128),
group.getAddress(), this, "Direct", 0, 0, null, "D", true));
}
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128),
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
addresses.getAddress().getAddress(), this, "Direct", 0, 128, addresses.getMonitor(), "D",
false);
rlist.add(ri);
RouteItem ris = new RouteItem(addresses.getLocator(),
(Inet6Address) addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
addresses.getMonitor(), "D", false);
rlist.add(ris);
@@ -138,10 +123,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
return rlist;
}
@Override
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
return false;
}
public SRv6Router getRouter() {
return router;
@@ -150,13 +131,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
public void setRouter(SRv6Router router) {
this.router = router;
}
@Override
public void setCongressCondition(Lock lock, Condition condition) {
// TODO 自动生成的方法存根
}
};
+6 -7
View File
@@ -5,34 +5,33 @@ import java.net.InetAddress;
import java.util.Objects;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
import org.kne.cloud.network.te.BandwidthDistributer;
public class Neighbor {
private Inet6AddressGroup address;
private Inet6AddressGroup locator;
private IPv6AddressGroup address;
private IPv6AddressGroup locator;
private MonitorData monitor;
private BandwidthDistributer<Inet6Address> bandwidthDistributer;
public MonitorData getMonitor() {
return monitor;
}
public Inet6AddressGroup getAddress() {
public IPv6AddressGroup getAddress() {
return address;
}
public Inet6AddressGroup getLocator() {
public IPv6AddressGroup getLocator() {
return locator;
}
public BandwidthDistributer<Inet6Address> getBandwidthDistributer() {
return bandwidthDistributer;
}
public Neighbor(Inet6AddressGroup address, Inet6AddressGroup locator, MonitorData monitor) {
public Neighbor(IPv6AddressGroup address, IPv6AddressGroup locator, MonitorData monitor) {
super();
this.address = address;
this.locator = locator;
this.monitor = monitor;
}
public Neighbor(Inet6AddressGroup address, Inet6AddressGroup locator, MonitorData monitor2,
public Neighbor(IPv6AddressGroup address, IPv6AddressGroup locator, MonitorData monitor2,
BandwidthDistributer<Inet6Address> bandwidthDistributer) {
this(address,locator,monitor2);
this.bandwidthDistributer=bandwidthDistributer;
@@ -0,0 +1,53 @@
package org.kne.cloud.network.ipv6;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
public class PacketID {
private UUID flowuuid;
private long sequence;
public PacketID(UUID flowuuid, long sequence) {
super();
this.flowuuid = flowuuid;
this.sequence = sequence;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long value = flowuuid.getMostSignificantBits() ^ flowuuid.getLeastSignificantBits();
result = prime * result + (int)(value ^ (value >>> 32));
result = prime * result + (int) (sequence ^ (sequence >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PacketID other = (PacketID) obj;
if (flowuuid == null) {
if (other.flowuuid != null)
return false;
} else if (!flowuuid.equals(other.flowuuid))
return false;
if (sequence != other.sequence)
return false;
return true;
}
@Override
public String toString() {
return "PacketID [flowuuid=" + flowuuid + ", sequence=" + sequence + "]";
}
public UUID getFlowuuid() {
return flowuuid;
}
public long getSequence() {
return sequence;
}
}
@@ -0,0 +1,55 @@
package org.kne.cloud.network.ipv6;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
public class PacketIDGenerator {
private UUID flowuuid;
private AtomicLong sequence;
public PacketIDGenerator() {
flowuuid=UUID.randomUUID();
sequence=new AtomicLong();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((flowuuid == null) ? 0 : flowuuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
PacketIDGenerator other = (PacketIDGenerator) obj;
if (flowuuid == null) {
if (other.flowuuid != null)
return false;
} else if (!flowuuid.equals(other.flowuuid))
return false;
return true;
}
public PacketIDGenerator(UUID flowuuid, AtomicLong sequence) {
super();
this.flowuuid = flowuuid;
this.sequence = sequence;
}
public UUID getFlowuuid() {
return flowuuid;
}
public AtomicLong getSequence() {
return sequence;
}
@Override
public String toString() {
return "PacketIDGenerater [flowuuid=" + flowuuid + ", sequence=" + sequence + "]";
}
public PacketID generate() {
return new PacketID(flowuuid, sequence.getAndIncrement());
}
}
@@ -0,0 +1,193 @@
package org.kne.cloud.network.ipv6;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.UUID;
import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
public class PostcardEntry extends NetworkPacket {
public static final int POSTCARD_ENTRY_SIZE = 48;
private ByteBuffer data = NetworkPacket.bufferAllocator.allocate(POSTCARD_ENTRY_SIZE);
// 字段偏移量常量
private static final int SID_OFFSET = 0; // 16字节
private static final int UUID_OFFSET = 16; // 16字节
private static final int SEQUENCE_OFFSET = 16+16; // 8字节
private static final int TIMESTAMP_BASE_OFFSET = 16+16; // 8字节
private static final int TIMESTAMP_DELTA_OFFSET = 24+16; // 4字节
private static final int PACKET_SIZE_OFFSET = 28+16; // 2字节
private static final int RESERVED_OFFSET = 30+16; // 6字节
public PostcardEntry(IPv6Address sid,UUID uuid,long timestampBase,int timestampDelta,int packetSize) {
setSID(sid);
setPacketUUID(uuid);
setTimestampBase(timestampBase);
setTimestampDelta(timestampDelta);
setPacketSize(packetSize);
data.limit(POSTCARD_ENTRY_SIZE);
}
public void setSID(IPv6Address sid) {
data.putLong(SID_OFFSET, sid.getHigh());
data.putLong(SID_OFFSET+8, sid.getLow());
}
public IPv6Address getSID() {
long high=data.getLong(SID_OFFSET);
long low =data.getLong(SID_OFFSET+8);
return new IPv6Address(high, low);
}
public PostcardEntry() {
// 初始化缓冲区
data.limit(POSTCARD_ENTRY_SIZE);
}
@Override
public long getTotalLength() {
return POSTCARD_ENTRY_SIZE;
}
@Override
public void writeToChannel(WritableByteChannel dto) throws IOException {
data.position(0);
data.limit(POSTCARD_ENTRY_SIZE);
dto.write(data.slice());
}
@Override
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
data.clear();
data.limit(POSTCARD_ENTRY_SIZE);
KNEChannels.readFully(din, data);
data.flip();
}
@Override
protected boolean needEndPosition() {
return false;
}
/**
* 设置包UUID16字节)
*/
public void setPacketUUID(UUID uuid) {
data.putLong(UUID_OFFSET, uuid.getMostSignificantBits());
data.putLong(UUID_OFFSET + 8, uuid.getLeastSignificantBits());
}
/**
* 获取包UUID16字节)
*/
public UUID getPacketUUID() {
long mostSigBits = data.getLong(UUID_OFFSET);
long leastSigBits = data.getLong(UUID_OFFSET + 8);
return new UUID(mostSigBits, leastSigBits);
}
/**
* 设置序列号(8字节)
*/
public void setSequence(long sequence) {
data.putLong(SEQUENCE_OFFSET, sequence);
}
/**
* 获取序列号(8字节)
*/
public long getSequence() {
return data.getLong(SEQUENCE_OFFSET);
}
/**
* 设置时间戳(8字节)
*/
public void setTimestampBase(long timestamp) {
data.putLong(TIMESTAMP_BASE_OFFSET, timestamp);
}
/**
* 获取时间戳(8字节)
*/
public long getTimestampBase() {
return data.getLong(TIMESTAMP_BASE_OFFSET);
}
public int getTimestampDelta() {
return data.getInt(TIMESTAMP_DELTA_OFFSET);
}
public void setTimestampDelta(int delta) {
data.putInt(TIMESTAMP_DELTA_OFFSET, delta);
}
/**
* 设置包大小(2字节,无符号)
*/
public void setPacketSize(int packetSize) {
if (packetSize < 0 || packetSize > 65535) {
throw new IllegalArgumentException("Packet size must be between 0 and 65535");
}
data.putShort(PACKET_SIZE_OFFSET, (short) packetSize);
}
/**
* 获取包大小(2字节,无符号)
*/
public int getPacketSize() {
return data.getShort(PACKET_SIZE_OFFSET) & 0xFFFF;
}
/**
* 设置保留字段(2字节)
*/
public void setReserved(int reserved) {
data.putChar(RESERVED_OFFSET ,(char) reserved);
}
/**
* 获取保留字段(2字节)
*/
public int getReserved() {
return data.getChar(RESERVED_OFFSET);
}
/**
* 清空保留字段(设置为0)
*/
public void clearReserved() {
setReserved(0);
}
@Override
public String toString() {
UUID uuid = getPacketUUID();
return String.format("PostcardEntry[uuid=%s, seq=%d, time=%d, delta=%d, size=%d]",
uuid.toString(),
getSequence(),
getTimestampBase(),
getTimestampDelta(),
getPacketSize());
}
public double getTimestampDeltaLong() {
return ((long)getTimestampDelta())<<4;
}
}
+13 -25
View File
@@ -6,14 +6,13 @@ import java.util.Objects;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
import org.kne.cloud.network.monitor.DelayMonitorData;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
public class RouteItem implements Comparable<RouteItem>,Cloneable{
private Inet6AddressGroup destination;
private Inet6Address nexthop;
private IPv6AddressGroup destination;
private IPv6Address nexthop;
private IPv6NetworkLink destlink;
private String proto;
private int pre;
@@ -44,7 +43,7 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
&& Objects.equals(flag, other.flag)
&& pre == other.pre && Objects.equals(proto, other.proto);
}
public RouteItem(Inet6AddressGroup destination, Inet6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
public RouteItem(IPv6AddressGroup destination, IPv6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
long cost,String flag,boolean isLoopback) {
super();
this.destination = destination;
@@ -56,7 +55,7 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
this.flag=flag;
this.isLoopback=isLoopback;
}
public RouteItem(Inet6AddressGroup destination, Inet6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
public RouteItem(IPv6AddressGroup destination, IPv6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
long cost,MonitorData monitor,String flag,boolean isLoopback) {
super();
this.destination = destination;
@@ -69,10 +68,10 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
this.flag=flag;
this.isLoopback=isLoopback;
}
public Inet6AddressGroup getDestination() {
public IPv6AddressGroup getDestination() {
return destination;
}
public Inet6Address getNexthop() {
public IPv6Address getNexthop() {
return nexthop;
}
public IPv6NetworkLink getDestlink() {
@@ -89,17 +88,17 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
}
@Override
public String toString() {
return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop().getHostAddress()+"\t"+getDestlink().getName();
return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop()+"\t"+getDestlink().getName();
}
public long getCost() {
return cost;
}
public boolean checkMatch(Inet6Address ia) {
/*public boolean checkMatch(IPv6Address ia) {
return destination.checkMatch(ia);
}
public boolean checkMatch(byte[] ia) {
return destination.checkMatch(ia);
}
}*/
@Override
public int compareTo(RouteItem o) {
int v1=destination.compareTo(o.destination);
@@ -109,13 +108,7 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
if(v2!=0)
return v2;
int v3=Long.compare(cost, o.cost);
if(v3!=0)
return v3;
if(monitor==null||o.monitor==null||(!(monitor instanceof DelayMonitorData))||(!(o.monitor instanceof DelayMonitorData)))
return v3;
if(!(monitor instanceof QueueingMonitorDataImpl)||!(o.monitor instanceof QueueingMonitorDataImpl))
return Long.compare(outDelay, o.outDelay);
return Long.compare(outDelay+queueingDelay, o.outDelay+o.queueingDelay);
return v3;
}
@Override
public Object clone() {
@@ -130,18 +123,13 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
}
}
long outDelay;
long queueingDelay;
public void preSort() {
if(monitor!=null) {
outDelay=((DelayMonitorData)monitor).getOutDelay();
if(monitor instanceof QueueingMonitorDataImpl) {
queueingDelay=((QueueingMonitorDataImpl)monitor).getQueueingDelay();
}
cost=((DelayMonitorData)monitor).getOutDelay();
}
}
public boolean ECMPequals(RouteItem prevr) {
return prevr.getDestination().getPrefixLength()==getDestination().getPrefixLength()&&prevr.getPre()==getPre()&&prevr.getCost()==getCost();
return prevr.getDestination().getPrefixLength()==getDestination().getPrefixLength()&&prevr.getPre()==getPre();
}
+2 -2
View File
@@ -19,7 +19,7 @@ public static final int PAD1=0;
if(getType()==PAD1)
setHeaderLength(1);
if(isDefault&&(getHeaderLength()>1)) {
data=NetworkPacket.bufferAllocator.allocate(512);
data=NetworkPacket.bufferAllocator.allocate(256);
}
}
@@ -33,7 +33,7 @@ public static final int PAD1=0;
header.put((byte) 0);
header.flip();
if(isDefault&&(getHeaderLength()>1)) {
data=NetworkPacket.bufferAllocator.allocate(512);
data=NetworkPacket.bufferAllocator.allocate(256);
}
}
+11 -12
View File
@@ -9,24 +9,23 @@ import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
import org.kne.cloud.network.ipv6.IPv6Address;
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
public class ADDRPacket extends KLALBPacket {
private static final int HEADER_LENGTH=18;
public Inet6AddressGroup getAddr() {
byte[]b=new byte[16];
klalbHeader.get(1, b);
try {
return new Inet6AddressGroup( (Inet6Address) Inet6Address.getByAddress(b),klalbHeader.get(17)&0xff);
} catch (UnknownHostException e) {
e.printStackTrace();
}
return null;
public IPv6AddressGroup getAddr() {
long high=klalbHeader.getLong(1);
long low=klalbHeader.getLong(9);
int perf=klalbHeader.get(17)&0xff;
return new IPv6AddressGroup(new IPv6Address(high, low), perf);
}
public ADDRPacket(Inet6AddressGroup addr) {
public ADDRPacket(IPv6AddressGroup addr) {
super(ADDR,HEADER_LENGTH);
klalbHeader.put(1, addr.getAddress().getAddress());
klalbHeader.putLong(1, addr.getAddress().getHigh());
klalbHeader.putLong(9, addr.getAddress().getLow());
klalbHeader.put(17,(byte) addr.getPrefixLength());
}
@@ -0,0 +1,18 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.Inet6Address;
import java.util.List;
import org.kne.cloud.network.ipv6.AbstractIPv6NetworkLink;
import org.kne.cloud.network.ipv6.ControlledIPv6NetworkLink;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
import org.kne.cloud.network.ipv6.Neighbor;
import org.kne.cloud.network.ipv6.RouteItem;
public abstract class AbstractControlledIPv6NetworkLink extends AbstractIPv6NetworkLink implements ControlledIPv6NetworkLink{
}
@@ -21,78 +21,9 @@ public abstract class AbstractKLALBPacketLink implements KLALBPacketLink {
AbstractKLALBPacketLink.defaultSoTimeout = defaultSoTimeout;
}
private LongAdder[] inputTrafficCounters;
private LongAdder[] outputTrafficCounters;
private LongAdder[] inputPacketsCounters;
private LongAdder[] outputPacketsCounters;
@Override
public void setOutputPacketsCounters(LongAdder[] outCounter) {
outputPacketsCounters=outCounter;
}
@Override
public void setInputPacketsCounters(LongAdder[] inCounter) {
inputPacketsCounters=inCounter;
}
@Override
public void setOutputTrafficCounters(LongAdder[] outCounter) {
this.outputTrafficCounters=outCounter;
}
@Override
public void setInputTrafficCounters(LongAdder[] inCounter) {
this.inputTrafficCounters=inCounter;
}
public LongAdder[] getInputTrafficCounters() {
return inputTrafficCounters;
}
public LongAdder[] getOutputTrafficCounters() {
return outputTrafficCounters;
}
public LongAdder[] getInputPacketsCounters() {
return inputPacketsCounters;
}
public LongAdder[] getOutputPacketsCounters() {
return outputPacketsCounters;
}
protected void incOutput(int packetLength) {
if(outputTrafficCounters!=null) {
for(LongAdder al:outputTrafficCounters) {
al.add(packetLength);
}
}
if(outputPacketsCounters!=null) {
for(LongAdder al:outputPacketsCounters) {
al.add(1);
}
}
}
protected void incInput(int packetLength) {
if(inputTrafficCounters!=null) {
for(LongAdder al:inputTrafficCounters) {
al.add(packetLength);
}
}
if(inputPacketsCounters!=null) {
for(LongAdder al:inputPacketsCounters) {
al.add(1);
}
}
}
@Override
public void writeKLALBPackets(List<KLALBPacket> kps) throws IOException {
for(KLALBPacket pack:kps) {
writeKLALBPacket(pack);
}
}
@Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
@@ -103,6 +34,8 @@ public abstract class AbstractKLALBPacketLink implements KLALBPacketLink {
writePacket(dataWrite);
}
protected abstract void writePacket(ByteBuffer dataWrite) throws IOException;
@Override
public KLALBPacket readKLALBPacket() throws IOException {
ByteBuffer buffer=readPacket();
@@ -111,4 +44,6 @@ public abstract class AbstractKLALBPacketLink implements KLALBPacketLink {
}
return KLALBPacket.readKLALBPacketFromChannel(KNEChannels.newReadableChannel(buffer));
}
protected abstract ByteBuffer readPacket() throws IOException;
}
@@ -25,7 +25,7 @@ public class BWINFPacket extends KLALBPacket {
}
public BWINFPacket(long upSpeed,long downSpeed) {
super( BWINF,HEADER_LENGTH,-1);
super( BWINF,HEADER_LENGTH);
klalbHeader.putLong(upSpeed);
klalbHeader.putLong(downSpeed);
}
+14 -5
View File
@@ -2,11 +2,20 @@ package org.kne.cloud.network.klalb;
public class CONST {
public static final String klalb="KLALB";
public static final String klalbver="3.4";
public static final int bversion=3;
public static final int sversion=1;
public static final int itemwidth = 720;
public static final int linepanelheight = 45;
public static final int settingheight = 30;
public static final int mversion=6;
public static final int sversion=0;
public static final String klalbver=bversion+"."+mversion+"."+sversion;
public static final String KLALB_DECENTRALIZED_S_RV6_NETWORK = "KLALB Decentralized SRv6 Network";
public static final String KLALB_S_RV6 = "KLALB_SRv6";
public static final int itemwidth = 1000;
public static final int linepanelheight = 41;
public static final int settingheight = 30;
public static final int dialwidth = 150;
}
@@ -21,7 +21,6 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
public long getTotalLength() {
return HEADER_LENGTH+dataBuffer.limit();
}
volatile long resendtimer=System.nanoTime();
private ByteBuffer dataBuffer;//=NetworkPacket.databufferpool_65535.borrow();
@@ -64,6 +63,7 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
}
private long numberc=Long.MIN_VALUE;
public long resendtimer;
public long getNumber() {
if(numberc!=Long.MIN_VALUE) {
return numberc;
@@ -188,7 +188,6 @@ public class DatagramKLALBPacketLink extends AbstractKLALBPacketLink implements
@Override
public void writePacket(ByteBuffer kp) throws IOException {
int length=kp.remaining();
incOutput(length);
kp.get(b,0,length);
DatagramPacket dp=new DatagramPacket(b,length);
ds.send(dp);
@@ -204,7 +203,6 @@ public class DatagramKLALBPacketLink extends AbstractKLALBPacketLink implements
dp=new DatagramPacket(c, c.length);
ds.receive(dp);
}
incInput(dp.getLength());
ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(dp.getLength());
bbf.put(dp.getData(),0,dp.getLength());
bbf.flip();
@@ -1,55 +0,0 @@
package org.kne.cloud.network.klalb;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Objects;
import java.util.UUID;
public class IPSequence {
private UUID uuid;
private boolean isPromise;
public IPSequence(UUID uuid, boolean isPromise) {
super();
this.uuid = uuid;
this.isPromise = isPromise;
}
public UUID getUuid() {
return uuid;
}
public boolean isPromise() {
return isPromise;
}
@Override
public String toString() {
return "IPSequence [uuid=" + uuid + ", isPromise=" + isPromise + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
IPSequence other = (IPSequence) obj;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
}
File diff suppressed because it is too large Load Diff
@@ -23,6 +23,16 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
private List<MultipurposeSocketAddress>LineTable=new ArrayList<>();
private List<MultipurposeSocketAddress>ConnectLineTable=new ArrayList<>();
private List<MultipurposeSocketAddress>ntpServerTable=new ArrayList<>();
private boolean denyLineTableQuery=false;
private boolean denyLineTableBroadcast=false;
private String congestionAlgorithm="BBR";
private double delayUpperBound=1.20;
private double delayLowerBound=1.15;
private long nagleDelayTime=1000000L;
private long linkNagleDelayTime=1000000L;
private int linkConnectionsCount=1;
private String TUNName=CONST.KLALB_S_RV6;
public void setNetworkInterfaceExcepts(List<String> networkInterfaceExcepts) {
NetworkInterfaceExcepts = networkInterfaceExcepts;
}
@@ -34,24 +44,6 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
public KLALBControllerConfigItem(String type, boolean nogui, String virtualAddress, Long virtualASN,
List<InetAddress> dNS, MultipurposeSocketAddress tCPListen, MultipurposeSocketAddress uDPListen,
String virtualSocketName, List<MultipurposeSocketAddress> lineTable,
List<MultipurposeSocketAddress> connectLineTable) {
super(type);
this.nogui = nogui;
VirtualAddress = virtualAddress;
VirtualASN = virtualASN;
DNS = dNS;
TCPListen = tCPListen;
UDPListen = uDPListen;
VirtualSocketName = virtualSocketName;
LineTable = lineTable;
ConnectLineTable = connectLineTable;
}
public List<String> getNetworkInterfaceExcepts() {
return NetworkInterfaceExcepts;
@@ -195,16 +187,126 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
this.ntpServerTable = ntpServerTable;
}
public String getCongestionAlgorithm() {
return congestionAlgorithm;
}
public void setCongestionAlgorithm(String congestionAlgorithm) {
this.congestionAlgorithm = congestionAlgorithm;
}
public double getDelayUpperBound() {
return delayUpperBound;
}
public void setDelayUpperBound(double delayUpperBound) {
this.delayUpperBound = delayUpperBound;
}
public double getDelayLowerBound() {
return delayLowerBound;
}
public void setDelayLowerBound(double delayLowerBound) {
this.delayLowerBound = delayLowerBound;
}
public boolean isDenyLineTableQuery() {
return denyLineTableQuery;
}
public void setDenyLineTableQuery(boolean denyLineTableQuery) {
this.denyLineTableQuery = denyLineTableQuery;
}
public boolean isDenyLineTableBroadcast() {
return denyLineTableBroadcast;
}
public void setDenyLineTableBroadcast(boolean denyLineTableBroadcast) {
this.denyLineTableBroadcast = denyLineTableBroadcast;
}
public long getNagleDelayTime() {
return nagleDelayTime;
}
public void setNagleDelayTime(long nagleDelayTime) {
this.nagleDelayTime = nagleDelayTime;
}
public int getLinkConnectionsCount() {
return linkConnectionsCount;
}
public void setLinkConnectionsCount(int linkConnectionsCount) {
this.linkConnectionsCount = linkConnectionsCount;
}
public long getLinkNagleDelayTime() {
return linkNagleDelayTime;
}
public void setLinkNagleDelayTime(long linkNagleDelayTime) {
this.linkNagleDelayTime = linkNagleDelayTime;
}
public String getTUNName() {
return TUNName;
}
public void setTUNName(String tUNName) {
TUNName = tUNName;
}
@Override
public String toString() {
return "KLALBControllerConfigItem [language=" + language + ", nogui=" + nogui + ", VirtualAddress="
+ VirtualAddress + ", VirtualASN=" + VirtualASN + ", DNS=" + DNS + ", TCPListen=" + TCPListen
+ ", UDPListen=" + UDPListen + ", VirtualSocketName=" + VirtualSocketName + ", LineTable=" + LineTable
+ ", ConnectLineTable=" + ConnectLineTable + ", ntpServerTable=" + ntpServerTable
+ ", NetworkInterfaceExcepts=" + NetworkInterfaceExcepts + "]";
+ ", denyLineTableQuery=" + denyLineTableQuery + ", denyLineTableBroadcast=" + denyLineTableBroadcast
+ ", congestionAlgorithm=" + congestionAlgorithm + ", delayUpperBound=" + delayUpperBound
+ ", delayLowerBound=" + delayLowerBound + ", nagleDelayTime=" + nagleDelayTime
+ ", linkNagleDelayTime=" + linkNagleDelayTime + ", linkConnectionsCount=" + linkConnectionsCount
+ ", TUNName=" + TUNName + ", NetworkInterfaceExcepts=" + NetworkInterfaceExcepts + "]";
}
@@ -218,11 +320,23 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
result = prime * result + ((LineTable == null) ? 0 : LineTable.hashCode());
result = prime * result + ((NetworkInterfaceExcepts == null) ? 0 : NetworkInterfaceExcepts.hashCode());
result = prime * result + ((TCPListen == null) ? 0 : TCPListen.hashCode());
result = prime * result + ((TUNName == null) ? 0 : TUNName.hashCode());
result = prime * result + ((UDPListen == null) ? 0 : UDPListen.hashCode());
result = prime * result + ((VirtualASN == null) ? 0 : VirtualASN.hashCode());
result = prime * result + ((VirtualAddress == null) ? 0 : VirtualAddress.hashCode());
result = prime * result + ((VirtualSocketName == null) ? 0 : VirtualSocketName.hashCode());
result = prime * result + ((congestionAlgorithm == null) ? 0 : congestionAlgorithm.hashCode());
long temp;
temp = Double.doubleToLongBits(delayLowerBound);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(delayUpperBound);
result = prime * result + (int) (temp ^ (temp >>> 32));
result = prime * result + (denyLineTableBroadcast ? 1231 : 1237);
result = prime * result + (denyLineTableQuery ? 1231 : 1237);
result = prime * result + ((language == null) ? 0 : language.hashCode());
result = prime * result + linkConnectionsCount;
result = prime * result + (int) (linkNagleDelayTime ^ (linkNagleDelayTime >>> 32));
result = prime * result + (int) (nagleDelayTime ^ (nagleDelayTime >>> 32));
result = prime * result + (nogui ? 1231 : 1237);
result = prime * result + ((ntpServerTable == null) ? 0 : ntpServerTable.hashCode());
return result;
@@ -264,6 +378,11 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
return false;
} else if (!TCPListen.equals(other.TCPListen))
return false;
if (TUNName == null) {
if (other.TUNName != null)
return false;
} else if (!TUNName.equals(other.TUNName))
return false;
if (UDPListen == null) {
if (other.UDPListen != null)
return false;
@@ -284,11 +403,30 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
return false;
} else if (!VirtualSocketName.equals(other.VirtualSocketName))
return false;
if (congestionAlgorithm == null) {
if (other.congestionAlgorithm != null)
return false;
} else if (!congestionAlgorithm.equals(other.congestionAlgorithm))
return false;
if (Double.doubleToLongBits(delayLowerBound) != Double.doubleToLongBits(other.delayLowerBound))
return false;
if (Double.doubleToLongBits(delayUpperBound) != Double.doubleToLongBits(other.delayUpperBound))
return false;
if (denyLineTableBroadcast != other.denyLineTableBroadcast)
return false;
if (denyLineTableQuery != other.denyLineTableQuery)
return false;
if (language == null) {
if (other.language != null)
return false;
} else if (!language.equals(other.language))
return false;
if (linkConnectionsCount != other.linkConnectionsCount)
return false;
if (linkNagleDelayTime != other.linkNagleDelayTime)
return false;
if (nagleDelayTime != other.nagleDelayTime)
return false;
if (nogui != other.nogui)
return false;
if (ntpServerTable == null) {
@@ -27,9 +27,10 @@ public class KLALBInputStream extends DataInputStream {
throw new StreamCorruptedException("no KLALB format");
}
int bv=readInt();
int mv=readInt();
int sv=readInt();
if(bv!=CONST.bversion)
throw new StreamCorruptedException("remote version is V"+bv+"."+sv+",not V"+CONST.klalbver);
if((bv!=CONST.bversion)||(mv!=CONST.mversion))
throw new StreamCorruptedException("remote version is V"+bv+"."+mv+",not V"+CONST.bversion+"."+CONST.mversion);
}
public KLALBPacket readKLALBPacket() throws IOException {
int len=readInt();
+41 -53
View File
@@ -19,22 +19,21 @@ import org.kne.cloud.network.SocketChannelListener;
import org.kne.cloud.network.SocketListener;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.ipv6.RouteItem;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI2;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI3;
import org.kne.cloud.network.klalb.ui.UIEnv;
import org.kne.cloud.network.perf.Kperf;
import org.kne.cloud.network.perf.MemcpyBenchmark;
import org.kne.cloud.network.perf.NodeBenchmark;
import org.kne.debug.Debuger;
import org.kne.debug.TimeDebugger;
import org.kne.membandboost.MembandBenchmark;
public class KLALBMain {
public static KLALBStateGUI3 ksg;
public static void main(String[] args) throws IOException {
try {
UIEnv.inituie();
}catch(Exception e) {
}catch(Throwable e) {
e.printStackTrace();
}
System.out.println(CONST.klalb+" V"+CONST.klalbver);
Scanner scn=new Scanner(System.in);
@@ -46,7 +45,9 @@ public class KLALBMain {
dtb.putTime("Create");
kpcje.loadConfigJson(configJson);
dtb.putTime("Load");
System.out.println("SRv6地址:"+kpcje.getKlalbController().getSelf().getAddress().getHostAddress());
System.out.println("=".repeat(65));
System.out.println(" - IPv6 Address / End SID: "+kpcje.getKlalbController().getSelf().getAddress());
System.out.println("=".repeat(65));
try {
if(!kpcje.getControllerConfig().isNogui())
openGUI(kpcje);
@@ -70,22 +71,28 @@ public class KLALBMain {
e.printStackTrace();
}
});
System.out.println("Done!");
while(true) {
System.out.print("KLALB>");
try {
String s=scn.nextLine();
String[]sc=s.trim().split(" ");
String tri=s.trim();
if(tri.isEmpty()) {
continue;
}
String[]sc=tri.split(" ");
switch(sc[0]) {
case "?":
case "help":
System.out.println("help:查看命令使用说明");
System.out.println("monitor:显示监视器图形界面");
System.out.println("lines-state:查看线路状态");
System.out.println("lines-add <地址:端口>:添加线路");
System.out.println("lines-remove <地址:端口>:删除线路");
System.out.println("lines-reconnect:所有离线线路立即尝试重连");
System.out.println("route:显示路由表");
System.out.println("kperf <地址:端口>:网络性能测试");
System.out.println("stop:退出程序");
System.out.println(" help / ?: see help");
System.out.println(" monitor: show monitor GUI");
System.out.println(" links-state: query link states");
System.out.println(" links-add <addr:port>: add link");
System.out.println(" links-remove <addr:port>: remove link");
System.out.println(" links-reconnect: reconnect all link");
System.out.println(" route: display internal route table");
System.out.println(" kperf <addr:port>: Porformance benchmark");
System.out.println(" exit: Exit");
break;
case "monitor":
@@ -95,8 +102,8 @@ public class KLALBMain {
e.printStackTrace();
}
break;
case "lines-state":
System.out.println("线路状态");
case "links-state":
System.out.println("links state");
System.out.println("状态\t上传流量\t下载流量\t上传速度\t下载速度\t上传延迟\t下载延迟\t上传抖动\t下载抖动");
synchronized (kpcje.getKlalbController().getLines()) {
for (Iterator<IPv6NetworkLink> iterator = kpcje.getKlalbController().getLines().iterator(); iterator.hasNext();) {
@@ -108,7 +115,7 @@ public class KLALBMain {
}
}
break;
case "lines-add":
case "links-add":
if(sc.length>=2) {
MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(sc[1]);
List<KLALBRemoteLine>addl=kpcje.getKlalbController().addRemoteLines(mpsa);
@@ -125,39 +132,39 @@ public class KLALBMain {
System.out.println("请输入要添加地址:端口!");
}
break;
case "lines-remove":
case "links-remove":
if(sc.length>=2) {
MultipurposeSocketAddress mpsa=new MultipurposeSocketAddress(sc[1]);
List<KLALBRemoteLine>rmvl=kpcje.getKlalbController().removeRemoteLines(mpsa);
if(rmvl.isEmpty()) {
System.out.println("未找到匹配移除项");
System.out.println("No matched link has been found.");
}else {
for (Iterator iterator = rmvl.iterator(); iterator.hasNext();) {
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next();
System.out.println("移除成功:"+klalbRemoteLine.getMonitor().getName());
System.out.println("Successfully removed: "+klalbRemoteLine.getMonitor().getName());
}
}
}else {
System.out.println("请输入要添加地址:端口!");
System.out.println("Invalid arguments.");
}
break;
case "stop":
System.out.println("已退出程序");
case "exit":
System.out.println("Exited.");
System.exit(0);
break;
case "lines-reconnect":
System.out.println("尝试重连断开的线路");
case "links-reconnect":
System.out.println("Trying to reconnect all links.");
kpcje.getKlalbController().reconnectImmediately();
break;
case "route":
List<RouteItem> lri=new ArrayList<>( kpcje.getKlalbController().getIpv6Router().getCurrentRouteTabel());
Collections.sort(lri);
System.out.println("路由表:");
System.out.println("前缀\t协议\t优先级\t开销\t标志\t下一跳\t接口");
System.out.println("Route Table:");
System.out.println("Prefix\tProtocol\tPref\tCost\tFlag\tNext Hop\tInterface");
for (Iterator<RouteItem> iterator = lri.iterator(); iterator.hasNext();) {
RouteItem routeItem = (RouteItem) iterator.next();
System.out.println(routeItem.getDestination()+"\t"+routeItem.getProto()+"\t"+routeItem.getPre()+"\t"+routeItem.getCost()+"\t"+routeItem.getFlag()+"\t"+routeItem.getNexthop().getHostAddress()+"\t"+routeItem.getDestlink().getName());
System.out.println(routeItem.getDestination()+"\t"+routeItem.getProto()+"\t"+routeItem.getPre()+"\t"+routeItem.getCost()+"\t"+routeItem.getFlag()+"\t"+routeItem.getNexthop()+"\t"+routeItem.getDestlink().getName());
}
break;
@@ -167,31 +174,12 @@ public class KLALBMain {
Kperf kp=new Kperf(mpsa);
kp.startPerfing();
}else {
System.out.println("请输入测速服务端地址:端口!");
System.out.println("Invalid arguments.");
}
break;
case "memcpy":
System.out.println("数组拷贝测试");
for (int i = 0; i < 10; i++) {
MemcpyBenchmark. testArrayCopySpeed(256*1024*1024);
}
System.out.println("Bytebuffer拷贝测试");
for (int i = 0; i < 10; i++) {
MemcpyBenchmark.testByteBufferCopySpeed(256*1024*1024);
}
System.out.println("Directbytebuffer分配测试");
for (int i = 0; i < 10; i++) {
MemcpyBenchmark.testDirectByteBufferAllocateSpeed(65536);
}
System.out.println("Bytebuffer分配测试");
for (int i = 0; i < 10; i++) {
MemcpyBenchmark.testByteBufferAllocateSpeed(65536);
}
System.out.println("BytebufferAllocator分配测试");
for (int i = 0; i < 10; i++) {
MemcpyBenchmark.testByteBufferAllocatorSpeed(65536);
}
MembandBenchmark.main(args);
break;
//case "$$SYSTEM:":
//System.out.println();
@@ -205,13 +193,13 @@ public class KLALBMain {
nbc.startPerfing();
break;
default:
System.out.println("未知命令,请输入help以查询命令说明");
System.out.println("Unknown command. See \"help\" or \"?\".");
}
}catch (NoSuchElementException err) {
System.out.println("已退出程序");
System.out.println("Exited.");
System.exit(0);
}catch(RuntimeException e) {
System.out.println("错误!");
System.out.println("Exception Occured!");
e.printStackTrace();
}
}
@@ -17,6 +17,7 @@ public class KLALBOutputStream extends DataOutputStream {
byte[]b=new byte[] {'K','L','A','L','B'};
write(b);
writeInt(CONST.bversion);
writeInt(CONST.mversion);
writeInt(CONST.sversion);
flush();
}
@@ -63,10 +63,6 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
klalbHeader.put((byte) type);
this.headerLength=headerLength;
}
public KLALBPacket(int type,int headerLength, long priority) {
this(type,headerLength);
setPriority(priority);
}
@Override
public String toString() {
return "KLALBPacket [type=" + getType() + "]";
@@ -146,7 +142,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public static KLALBPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException {
while(true) {
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40);
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(64);
bb.position(0);
bb.limit(1);
while(bb.hasRemaining()){
@@ -10,20 +10,9 @@ import java.util.concurrent.atomic.LongAdder;
import org.kne.cloud.network.MultipurposeSocketAddress;
public interface KLALBPacketLink {
public void setOutputTrafficCounters(LongAdder[] al);
public void setOutputPacketsCounters(LongAdder[] longAdders);
public void setInputTrafficCounters(LongAdder[] longAdders);
public void setInputPacketsCounters(LongAdder[] al);
public void writePacket(ByteBuffer kp) throws IOException;
public default void writePackets(ByteBuffer[] kpp,int off,int len) throws IOException {
for (int i = 0; i < len; i++) {
writePacket(kpp[off+i]);
}
}
public void writeKLALBPacket(KLALBPacket kp) throws IOException;
public void flush() throws IOException;
public KLALBPacket readKLALBPacket()throws IOException;
public ByteBuffer readPacket()throws IOException;
public void close() throws IOException;
public boolean isClosed();
public void setSoTimeout(int val) throws SocketException;
@@ -31,6 +20,5 @@ public interface KLALBPacketLink {
@Override
public String toString();
public boolean isStream();
public void writeKLALBPackets(List<KLALBPacket> kp) throws IOException;
}
@@ -46,7 +46,7 @@ public class KLALBProtocolDetectSocketListener extends SocketListener {
if(!pds.getProtocolStack().isEmpty()&&pds.getProtocolStack().pop().getName().equals("KLALB")) {
KLALBRemoteLine krs=null;
try {
krs = new KLALBRemoteLine(new StreamKLALBPacketLink(pds));
krs = new KLALBRemoteLine(klalbController,new StreamKLALBPacketLink(pds));
klalbController.addRemoteLine(krs);
} catch (Exception e) {
e.printStackTrace();
@@ -24,7 +24,6 @@ import java.util.Map;
import java.util.Map.Entry;
import org.kne.cloud.network.*;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI2;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI3;
import org.kne.cloud.network.klalb.ui.Language;
import org.kne.cloud.network.klalb.ui.UIEnv;
@@ -122,7 +121,6 @@ public class KLALBProxySystem {
}
public void loadConfigJson(JsonElement json) {
KLALBConfig config= gson.fromJson(json, KLALBConfig.class);
System.out.println(config);
loadConfig(config);
}
public void loadConfig(KLALBConfig config) {
@@ -141,31 +139,10 @@ public class KLALBProxySystem {
}
}
}
String vase= kcci.getVirtualAddress();
//System.out.println(vase);
List<InetAddress>daddr=new ArrayList<InetAddress>();
List<InetAddress> vdns= kcci.getDNS();
if(vdns!=null) {
for(InetAddress dnsaddr:vdns) {
daddr.add(dnsaddr);
}
}
if(vase!=null) {
try {
klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase),daddr);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}else {
klalbController=new KLALBController(daddr);
}
Long vasn= kcci.getVirtualASN();
if(vasn!=null) {
klalbController.getIpv6Router().setASN (vasn);
}
klalbController=new KLALBController(kcci);
String vsne=kcci.getVirtualSocketName();
@@ -183,7 +160,7 @@ public class KLALBProxySystem {
KLALBRemoteLine krs=null;
try {
krs = new KLALBRemoteLine(new StreamChannelKLALBPacketLink(soc));
krs = new KLALBRemoteLine(klalbController,new StreamChannelKLALBPacketLink(soc));
klalbController.addRemoteLine(krs);
} catch (IOException e) {
e.printStackTrace();
@@ -206,7 +183,7 @@ public class KLALBProxySystem {
KLALBRemoteLine krs=null;
try {
krs = new KLALBRemoteLine(new SplitedDatagramKLALBPacketLink(soc));
krs = new KLALBRemoteLine(klalbController,new SplitedDatagramKLALBPacketLink(soc));
klalbController.addRemoteLine(krs);
} catch (IOException e) {
e.printStackTrace();
@@ -219,33 +196,7 @@ public class KLALBProxySystem {
e1.printStackTrace();
}
}
List<MultipurposeSocketAddress> linele=kcci.getLineTable();
if(linele!=null) {
klalbController.getSelflineTable().addAll(linele);
}
List<MultipurposeSocketAddress> linetoc=kcci.getConnectLineTable();
if(linetoc!=null) {
linetoc.forEach((aline)->{
klalbController.addRemoteLines(aline);
});
}
List<MultipurposeSocketAddress> ntps=kcci.getNtpServerTable();
if(ntps!=null) {
klalbController.getNTPTable().addAll(ntps);
}
List<String> strexc=kcci.getNetworkInterfaceExcepts();
klalbController.getNetworkInterfaceExcept().clear();
if(strexc!=null) {
for(String strexci:strexc) {
try {
klalbController.getNetworkInterfaceExcept().add(NetworkInterface.getByName(strexci));
} catch (SocketException e) {
e.printStackTrace();
}
}
}
}else if(item instanceof SocketBridgeConfigItem) {
SocketBridgeConfigItem scci=(SocketBridgeConfigItem) item;
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More