forked from KNEMC/KLALB
KLALB V3.6.0 写了一半
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
+110
-20
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+23
-11
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -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;
|
||||
+2
-2
@@ -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);
|
||||
+161
-131
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+23
-32
@@ -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);
|
||||
}
|
||||
+3
-3
@@ -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
-1
@@ -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
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新最小RTT(BaseRTT)
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置包UUID(16字节)
|
||||
*/
|
||||
public void setPacketUUID(UUID uuid) {
|
||||
data.putLong(UUID_OFFSET, uuid.getMostSignificantBits());
|
||||
data.putLong(UUID_OFFSET + 8, uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包UUID(16字节)
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -79,14 +79,11 @@ public class KLALBRemoteManagement {
|
||||
jklbrl.addProperty("ipport", klalbRemoteLine.getSocketAddress().toString());
|
||||
jklbrl.addProperty("state",MonitorData.parseStateToString( klalbRemoteLine.getMonitor().getState()));
|
||||
|
||||
jklbrl.addProperty("Vaddr", klalbRemoteLine.getRemoteVaddr().getAddress().getHostAddress());
|
||||
jklbrl.addProperty("Vaddr", klalbRemoteLine.getRemoteVaddr().getAddress().toString());
|
||||
|
||||
jklbrl.addProperty("uploadspeed", klalbRemoteLine.getMonitor().getOutSpeed());
|
||||
jklbrl.addProperty("downloadspeed", klalbRemoteLine.getMonitor().getInSpeed());
|
||||
|
||||
jklbrl.addProperty("uploadspeedavg", klalbRemoteLine.getMonitor().getOutSpeedAvg());
|
||||
jklbrl.addProperty("downloadspeedavg", klalbRemoteLine.getMonitor().getInSpeedAvg());
|
||||
|
||||
jklbrl.addProperty("uploadtraffic", klalbRemoteLine.getMonitor().getOutTraffic());
|
||||
jklbrl.addProperty("downloadtraffic", klalbRemoteLine.getMonitor().getInTraffic());
|
||||
|
||||
@@ -139,9 +136,6 @@ public class KLALBRemoteManagement {
|
||||
jrsp.addProperty("uploadspeed", klalbProxySystem.getKlalbController().getLinkMonitor().getOutSpeed());
|
||||
jrsp.addProperty("downloadspeed", klalbProxySystem.getKlalbController().getLinkMonitor().getInSpeed());
|
||||
|
||||
jrsp.addProperty("uploadspeedavg", klalbProxySystem.getKlalbController().getLinkMonitor().getOutSpeedAvg());
|
||||
jrsp.addProperty("downloadspeedavg", klalbProxySystem.getKlalbController().getLinkMonitor().getInSpeedAvg());
|
||||
|
||||
jrsp.addProperty("uploadtraffic", klalbProxySystem.getKlalbController().getLinkMonitor().getOutTraffic());
|
||||
jrsp.addProperty("downloadtraffic", klalbProxySystem.getKlalbController().getLinkMonitor().getInTraffic());
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
@@ -14,6 +15,7 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.kne.cloud.network.MultipurposeSocketAddress;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
|
||||
public class KLALBUtils {
|
||||
public static Inet6Address uuidToIP(UUID uuid) {
|
||||
@@ -36,6 +38,18 @@ public class KLALBUtils {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static IPv6Address randomKLALBIPv6Address() {
|
||||
SecureRandom sc = new SecureRandom();
|
||||
byte[] v = new byte[16];
|
||||
sc.nextBytes(v);
|
||||
v[0] = (byte) 0x24;
|
||||
v[1] = (byte) 0x86;
|
||||
v[2] = 0x00;
|
||||
v[3] = 0x01;
|
||||
return IPv6Address.valueOf(v);
|
||||
}
|
||||
public static void main(String[] args) {
|
||||
System.out.println(uuidToIP(new UUID(-1,-1)));
|
||||
}
|
||||
@@ -366,6 +380,37 @@ public static String parseAbbrIPv6(String IPv6Str) {
|
||||
}
|
||||
return join(arr, ":").replaceAll(":{2,}", "::");
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class UUIDGenarator{
|
||||
|
||||
private final long id;
|
||||
private long counter=0;
|
||||
private UUID randUUID=UUID.randomUUID();
|
||||
private long time=System.nanoTime();
|
||||
private static final long INTERVAL=1000000L;
|
||||
public UUIDGenarator(long threadId) {
|
||||
this.id=threadId;
|
||||
}
|
||||
public UUID genarateUUID() {
|
||||
long curr=System.nanoTime();
|
||||
if(curr-time>INTERVAL) {
|
||||
time=curr;
|
||||
randUUID=UUID.randomUUID();
|
||||
}
|
||||
long h=randUUID.getMostSignificantBits()^id;
|
||||
long l=randUUID.getLeastSignificantBits()^counter;
|
||||
|
||||
UUID ret=new UUID(h, l);
|
||||
counter++;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
private static ThreadLocal<UUIDGenarator> gens=ThreadLocal.withInitial(()->{
|
||||
return new UUIDGenarator(Thread.currentThread().threadId());
|
||||
});
|
||||
public static UUID createGlobalUUID() {
|
||||
//return UUID.randomUUID();
|
||||
return gens.get().genarateUUID();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.VirtualDatagramSocketImpl;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.kne.cloud.network.tcp.UDPPacket;
|
||||
import org.kne.concurrent.HighPerformanceExecutor;
|
||||
@@ -82,7 +83,7 @@ public class KLALBVirtualDatagramSocketImpl extends VirtualDatagramSocketImpl im
|
||||
if (!(host instanceof Inet6Address)) {
|
||||
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 virtualaddress");
|
||||
}
|
||||
if ((!host.isAnyLocalAddress()) && (!host.equals(controller.getSelf().getAddress()))) {
|
||||
if ((!host.isAnyLocalAddress()) && (!IPv6Address.valueOf( host).equals(controller.getSelf().getAddress()))) {
|
||||
throw new BindException("must bind to self");
|
||||
}
|
||||
localaddr = (Inet6Address) host;
|
||||
@@ -97,8 +98,9 @@ public class KLALBVirtualDatagramSocketImpl extends VirtualDatagramSocketImpl im
|
||||
UDPPacket udp=new UDPPacket(localPort, p.getPort());
|
||||
udp.getData().put(p.getData(), p.getOffset(), p.getLength());
|
||||
udp.getData().flip();
|
||||
HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
||||
controller.sendPacketToAddress((Inet6Address) p.getAddress(),0, udp);
|
||||
controller.getIpv6Router().enqueuePacketSendTask(()->{
|
||||
IPv6Packet uip=controller.createPacketToAddress(IPv6Address.valueOf( p.getAddress()),0, udp);
|
||||
return uip;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -121,7 +123,7 @@ public class KLALBVirtualDatagramSocketImpl extends VirtualDatagramSocketImpl im
|
||||
}
|
||||
|
||||
private void copyTo(UDPPacket pack, DatagramPacket p) throws IOException {
|
||||
p.setAddress(pack.getParent().getSourceAddress());
|
||||
p.setAddress(pack.getParent().getSourceAddress2());
|
||||
p.setPort(pack.getSrcPort());
|
||||
ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength());
|
||||
|
||||
@@ -216,7 +218,7 @@ public class KLALBVirtualDatagramSocketImpl extends VirtualDatagramSocketImpl im
|
||||
private Queue<UDPPacket> recvQueue = new ConcurrentLinkedQueue<UDPPacket>();
|
||||
private AtomicInteger recvQueueUsed=new AtomicInteger(0);
|
||||
@Override
|
||||
public void accept(Inet6Address t,NetworkPacket np) {
|
||||
public void accept(IPv6Address t,NetworkPacket np) {
|
||||
UDPPacket u=(UDPPacket) np;
|
||||
if(recvQueueUsed.get()<=inputchachesize) {
|
||||
if(recvQueue.offer(u)) {
|
||||
|
||||
@@ -15,7 +15,9 @@ import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.ByteBufferAllocator;
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
@@ -24,7 +26,9 @@ import org.kne.cloud.network.ThreadTool;
|
||||
import org.kne.cloud.network.VirtualRawSocketImpl;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload;
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
||||
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
||||
import org.kne.cloud.network.ipv6.LoopbackIPv6NetworkLink;
|
||||
import org.kne.cloud.network.srv6.PacketConsumer;
|
||||
import org.kne.cloud.network.srv6.SRv6Router;
|
||||
@@ -139,8 +143,8 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
|
||||
}
|
||||
if (!address.isAnyLocalAddress() ) {
|
||||
boolean contains=false;
|
||||
for(Inet6AddressGroup adg:link.getAddressGroups()) {
|
||||
if(adg.checkMatch((Inet6Address) address)) {
|
||||
for(IPv6AddressGroup adg:link.getAddressGroups()) {
|
||||
if(adg.checkMatch(IPv6Address.valueOf( address))) {
|
||||
contains=true;
|
||||
break;
|
||||
}
|
||||
@@ -187,14 +191,19 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
|
||||
if(ipHeaderInclude) {
|
||||
|
||||
}else {
|
||||
HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
||||
IPv6Payload pl=new IPv6Payload(bindProtocolNumber);
|
||||
pl.getData().put(buf);
|
||||
pl.getData().flip();
|
||||
BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>>cons=link.getReceiveConsumer();
|
||||
if(cons!=null) {
|
||||
cons.accept(link,() -> {
|
||||
IPv6Packet ipv=new IPv6Packet();
|
||||
ipv.setVersion(6);
|
||||
ipv.setTrafficClass(0);
|
||||
ipv.setFlowLabel(0);
|
||||
ipv.setHopLimit(255);
|
||||
if(!localaddr.isAnyLocalAddress()) {
|
||||
ipv.setSourceAddress(localaddr);
|
||||
ipv.setSourceAddress2(localaddr);
|
||||
}else {
|
||||
ipv.setSourceAddress(link.getRouter().getLocator().getAddress());
|
||||
}
|
||||
@@ -202,24 +211,18 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
|
||||
if (!(address instanceof Inet6Address)) {
|
||||
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address");
|
||||
}
|
||||
ipv.setDestinationAddress((Inet6Address)address);
|
||||
ipv.setPriority(3);
|
||||
ipv.setDestinationAddress2((Inet6Address)address);
|
||||
//ipv.enableECN();
|
||||
IPv6Payload pl=new IPv6Payload(bindProtocolNumber);
|
||||
pl.getData().put(buf);
|
||||
pl.getData().flip();
|
||||
ipv.setPayload(pl);
|
||||
Consumer<IPv6Packet>cons=link.getReceiveConsumer();
|
||||
if(cons!=null) {
|
||||
cons.accept(ipv);
|
||||
}
|
||||
return ipv;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InetAddress peek() throws IOException {
|
||||
return peekNextPacket().getSourceAddress();
|
||||
return peekNextPacket().getSourceAddress2();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -229,7 +232,7 @@ public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements P
|
||||
}
|
||||
|
||||
private void copyTo(IPv6Packet pack, DatagramPacket p) throws IOException {
|
||||
p.setAddress(pack.getSourceAddress());
|
||||
p.setAddress(pack.getSourceAddress2());
|
||||
ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength());
|
||||
if(ipHeaderInclude) {
|
||||
|
||||
|
||||
@@ -75,12 +75,7 @@ public class KLALBVirtualSocket extends VirtualSocket {
|
||||
}
|
||||
|
||||
|
||||
public void associateSocket(Socket associateSocket) throws IOException {
|
||||
((KLALBVirtualSocketImpl)getVirtualImpl()).associateSocket(associateSocket);
|
||||
}
|
||||
public void associateSocketChannel(SocketChannel b) throws IOException{
|
||||
((KLALBVirtualSocketImpl)getVirtualImpl()).associateSocketChannel(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocketChannel getChannel() {
|
||||
return channel;
|
||||
|
||||
@@ -145,10 +145,6 @@ public class KLALBVirtualSocketChannel extends SocketChannel{
|
||||
}
|
||||
}
|
||||
|
||||
public void associateSocketChannel(SocketChannel b) throws IOException {
|
||||
socket.associateSocketChannel(b);
|
||||
}
|
||||
|
||||
public boolean isAutoFlush() throws IOException {
|
||||
return ((KVSIOutputStream)socket.getOutputStream()).isAutoFlush();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
package org.kne.cloud.network.klalb;
|
||||
|
||||
public class MemUseTest {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
Thread.sleep(1000);
|
||||
Runtime r=Runtime.getRuntime();
|
||||
System.out.println("total:"+r.totalMemory()+" max:"+r.maxMemory()+" free:"+r.freeMemory());
|
||||
while(true) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,30 +7,36 @@ import java.net.Socket;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
import org.kne.cloud.network.FilterSocket;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
|
||||
|
||||
public class MonitoredSocket extends FilterSocket {
|
||||
public SpeedAndTrafficMonitorDataImpl getMonitor() {
|
||||
return monitor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private SpeedAndTrafficMonitorDataImpl monitor;
|
||||
private LongAdder inMonitor;
|
||||
private LongAdder outMonitor;
|
||||
|
||||
|
||||
|
||||
public LongAdder getInMonitor() {
|
||||
return inMonitor;
|
||||
}
|
||||
public LongAdder getOutMonitor() {
|
||||
return outMonitor;
|
||||
}
|
||||
@Override
|
||||
public synchronized void close() throws IOException {
|
||||
super.close();
|
||||
}
|
||||
public MonitoredSocket(Socket socket) {
|
||||
this(socket,new SpeedAndTrafficMonitorDataImpl());
|
||||
this(socket,new LongAdder(),new LongAdder());
|
||||
}
|
||||
public MonitoredSocket(Socket socket,SpeedAndTrafficMonitorDataImpl monitor) {
|
||||
public MonitoredSocket(Socket socket,LongAdder inMonitor,LongAdder outMonitor) {
|
||||
super(socket);
|
||||
this.monitor=monitor;
|
||||
this.inMonitor=inMonitor;
|
||||
this.outMonitor=outMonitor;
|
||||
}
|
||||
|
||||
|
||||
@@ -41,14 +47,14 @@ public class MonitoredSocket extends FilterSocket {
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
if(in==null)
|
||||
in=new MonitoredInputStream(socket.getInputStream(), monitor.getInTrafficAL());
|
||||
in=new MonitoredInputStream(socket.getInputStream(), inMonitor);
|
||||
return in;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
if(out==null) {
|
||||
out=new MonitoredOutputStream(socket.getOutputStream(), monitor.getOutTrafficAL());
|
||||
out=new MonitoredOutputStream(socket.getOutputStream(), outMonitor);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -9,16 +9,24 @@ import java.nio.ByteBuffer;
|
||||
|
||||
public class PINGPacket extends KLALBPacket {
|
||||
|
||||
private static final int HEADER_LENGTH=9;
|
||||
private static final int HEADER_LENGTH=25;
|
||||
|
||||
public long getTime() {
|
||||
return klalbHeader.getLong(17);
|
||||
}
|
||||
|
||||
public long getUpSpeed() {
|
||||
return klalbHeader.getLong(1);
|
||||
}
|
||||
|
||||
public long getDownSpeed() {
|
||||
return klalbHeader.getLong(9);
|
||||
}
|
||||
|
||||
|
||||
public PINGPacket(long time) {
|
||||
super(PING,HEADER_LENGTH,-1);
|
||||
public PINGPacket(long time,long upSpeed,long downSpeed) {
|
||||
super(PING,HEADER_LENGTH);
|
||||
klalbHeader.putLong(upSpeed);
|
||||
klalbHeader.putLong(downSpeed);
|
||||
klalbHeader.putLong(time);
|
||||
}
|
||||
public PINGPacket(ByteBuffer bb) {
|
||||
|
||||
@@ -9,21 +9,27 @@ import java.nio.ByteBuffer;
|
||||
|
||||
public class PONGPacket extends KLALBPacket {
|
||||
|
||||
private static final int HEADER_LENGTH=25;
|
||||
private static final int HEADER_LENGTH=41;
|
||||
|
||||
public long getTimepingsnd() {
|
||||
return klalbHeader.getLong(1);
|
||||
}
|
||||
|
||||
public long getTimepingrcv() {
|
||||
return klalbHeader.getLong(9);
|
||||
}
|
||||
|
||||
public long getTimepongsnd() {
|
||||
return klalbHeader.getLong(17);
|
||||
}
|
||||
|
||||
|
||||
public long getTimepingrcv() {
|
||||
return klalbHeader.getLong(25);
|
||||
}
|
||||
|
||||
public long getTimepongsnd() {
|
||||
return klalbHeader.getLong(33);
|
||||
}
|
||||
|
||||
public long getUpSpeed() {
|
||||
return klalbHeader.getLong(1);
|
||||
}
|
||||
|
||||
public long getDownSpeed() {
|
||||
return klalbHeader.getLong(9);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@@ -31,8 +37,10 @@ public class PONGPacket extends KLALBPacket {
|
||||
return HEADER_LENGTH;
|
||||
}
|
||||
|
||||
public PONGPacket( long timepingsnd,long timepingrcv, long timepongsnd) {
|
||||
super(PONG,HEADER_LENGTH,-1);
|
||||
public PONGPacket( long timepingsnd,long timepingrcv, long timepongsnd,long upSpeed,long downSpeed) {
|
||||
super(PONG,HEADER_LENGTH);
|
||||
klalbHeader.putLong(upSpeed);
|
||||
klalbHeader.putLong(downSpeed);
|
||||
klalbHeader.putLong(timepingsnd);
|
||||
klalbHeader.putLong(timepingrcv);
|
||||
klalbHeader.putLong(timepongsnd);
|
||||
|
||||
@@ -5,7 +5,8 @@ import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
|
||||
public interface PacketConsumer extends BiConsumer<Inet6Address, NetworkPacket> {
|
||||
public interface PacketConsumer extends BiConsumer<IPv6Address, NetworkPacket> {
|
||||
|
||||
}
|
||||
|
||||
@@ -18,29 +18,24 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReadWriteLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import org.kne.cloud.network.IPv6SocketAddress;
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
|
||||
import com.google.gson.internal.Pair;
|
||||
|
||||
public class PortBinder {
|
||||
private static Inet6Address ANYLA;
|
||||
static {
|
||||
try {
|
||||
ANYLA=(Inet6Address) Inet6Address.getByAddress(new byte[16]);
|
||||
} catch (UnknownHostException e) {
|
||||
}
|
||||
}
|
||||
private KLALBController controller;
|
||||
public PortBinder(KLALBController controller) {
|
||||
super();
|
||||
this.controller = controller;
|
||||
}
|
||||
private ReentrantReadWriteLock bindMaplock=new ReentrantReadWriteLock();
|
||||
private Map<InetSocketAddress,BindableKLALBPacketConsumer>bindMap=new ConcurrentHashMap<>(1024,0.2f);
|
||||
private Map<IPv6SocketAddress,BindableKLALBPacketConsumer>bindMap=new ConcurrentHashMap<>(1024,0.2f);
|
||||
private ReentrantReadWriteLock listenMaplock=new ReentrantReadWriteLock();
|
||||
private Map<InetSocketAddress,BindableKLALBPacketConsumer>listenMap=new ConcurrentHashMap<>(1024,0.2f);
|
||||
private Map<IPv6SocketAddress,BindableKLALBPacketConsumer>listenMap=new ConcurrentHashMap<>(1024,0.2f);
|
||||
private ReentrantReadWriteLock connectMaplock=new ReentrantReadWriteLock();
|
||||
private Map<Pair<InetSocketAddress,InetSocketAddress>,BindableKLALBPacketConsumer>connectMap=new ConcurrentHashMap<>(1024,0.2f);
|
||||
private Map<Pair<IPv6SocketAddress,IPv6SocketAddress>,BindableKLALBPacketConsumer>connectMap=new ConcurrentHashMap<>(1024,0.2f);
|
||||
private volatile int portn=65535;
|
||||
public void bind(BindableKLALBPacketConsumer ks) throws BindException {
|
||||
bindMaplock.writeLock().lock();
|
||||
@@ -64,10 +59,10 @@ public class PortBinder {
|
||||
}
|
||||
}
|
||||
boolean flag=true;
|
||||
for (Iterator<InetSocketAddress> iterator = bindMap.keySet().iterator(); iterator.hasNext();) {
|
||||
InetSocketAddress bindableKLALBPacketConsumer = (InetSocketAddress) iterator
|
||||
for (Iterator<IPv6SocketAddress> iterator = bindMap.keySet().iterator(); iterator.hasNext();) {
|
||||
IPv6SocketAddress bindableKLALBPacketConsumer = (IPv6SocketAddress) iterator
|
||||
.next();
|
||||
if(Objects.equals(ks.getLocalInetAddress(), bindableKLALBPacketConsumer.getAddress())&&portn==bindableKLALBPacketConsumer.getPort()) {
|
||||
if(Objects.equals(IPv6Address.valueOf( ks.getLocalInetAddress()), bindableKLALBPacketConsumer.getAddress())&&portn==bindableKLALBPacketConsumer.getPort()) {
|
||||
flag=false;
|
||||
break;
|
||||
}
|
||||
@@ -77,15 +72,15 @@ public class PortBinder {
|
||||
}
|
||||
ks.setLocalPort(portn);
|
||||
}else {
|
||||
for (Iterator<InetSocketAddress> iterator = bindMap.keySet().iterator(); iterator.hasNext();) {
|
||||
InetSocketAddress bindableKLALBPacketConsumer = (InetSocketAddress) iterator
|
||||
for (Iterator<IPv6SocketAddress> iterator = bindMap.keySet().iterator(); iterator.hasNext();) {
|
||||
IPv6SocketAddress bindableKLALBPacketConsumer = (IPv6SocketAddress) iterator
|
||||
.next();
|
||||
if(Objects.equals(ks.getLocalInetAddress(), bindableKLALBPacketConsumer.getAddress())&&pold==bindableKLALBPacketConsumer.getPort()) {
|
||||
if(Objects.equals(IPv6Address.valueOf( ks.getLocalInetAddress()), bindableKLALBPacketConsumer.getAddress())&&pold==bindableKLALBPacketConsumer.getPort()) {
|
||||
throw new BindException("port " + pold + " is already bind!");
|
||||
}
|
||||
}
|
||||
}
|
||||
bindMap.put(new InetSocketAddress(ks.getLocalInetAddress(), ks.getLocalPort()),ks);
|
||||
bindMap.put(new IPv6SocketAddress(IPv6Address.valueOf( ks.getLocalInetAddress()), ks.getLocalPort()),ks);
|
||||
}finally {
|
||||
bindMaplock.writeLock().unlock();
|
||||
}
|
||||
@@ -102,7 +97,7 @@ public class PortBinder {
|
||||
public void connect(BindableKLALBPacketConsumer ks) throws BindException {
|
||||
connectMaplock.writeLock().lock();
|
||||
try {
|
||||
connectMap.put(new Pair<InetSocketAddress, InetSocketAddress>( new InetSocketAddress(ks.getLocalInetAddress(), ks.getLocalPort()), new InetSocketAddress(ks.getRemoteInetAddress(), ks.getPort())),ks);
|
||||
connectMap.put(new Pair<IPv6SocketAddress, IPv6SocketAddress>( new IPv6SocketAddress(IPv6Address.valueOf(ks.getLocalInetAddress()), ks.getLocalPort()), new IPv6SocketAddress(IPv6Address.valueOf(ks.getRemoteInetAddress()), ks.getPort())),ks);
|
||||
}finally {
|
||||
connectMaplock.writeLock().unlock();
|
||||
}
|
||||
@@ -119,7 +114,7 @@ public class PortBinder {
|
||||
public void listen(BindableKLALBPacketConsumer ks) throws BindException {
|
||||
listenMaplock.writeLock().lock();
|
||||
try {
|
||||
listenMap.put(new InetSocketAddress(ks.getLocalInetAddress(), ks.getLocalPort()),ks);
|
||||
listenMap.put(new IPv6SocketAddress(IPv6Address.valueOf(ks.getLocalInetAddress()), ks.getLocalPort()),ks);
|
||||
}finally {
|
||||
listenMaplock.writeLock().unlock();
|
||||
}
|
||||
@@ -206,16 +201,16 @@ public class PortBinder {
|
||||
}
|
||||
return b;
|
||||
}*/
|
||||
public boolean distributePacketToConsumer(Inet6Address srcAddr,PortPacket packet) {
|
||||
InetSocketAddress local=new InetSocketAddress(controller.getSelf().getAddress(), packet.getDstPort());
|
||||
InetSocketAddress remote=new InetSocketAddress(srcAddr, packet.getSrcPort());
|
||||
BindableKLALBPacketConsumer bkc=connectMap.get(new Pair<InetSocketAddress, InetSocketAddress>(local, remote));
|
||||
public boolean distributePacketToConsumer(IPv6Address srcAddr,PortPacket packet) {
|
||||
IPv6SocketAddress local=new IPv6SocketAddress(controller.getSelf().getAddress(), packet.getDstPort());
|
||||
IPv6SocketAddress remote=new IPv6SocketAddress(srcAddr, packet.getSrcPort());
|
||||
BindableKLALBPacketConsumer bkc=connectMap.get(new Pair<IPv6SocketAddress, IPv6SocketAddress>(local, remote));
|
||||
if(bkc!=null) {
|
||||
bkc.accept(srcAddr, (NetworkPacket) packet);
|
||||
return true;
|
||||
}
|
||||
InetSocketAddress localany=new InetSocketAddress(ANYLA, packet.getDstPort());
|
||||
bkc=connectMap.get(new Pair<InetSocketAddress, InetSocketAddress>(localany, remote));
|
||||
IPv6SocketAddress localany=new IPv6SocketAddress(IPv6Address.UNSPECIFIED, packet.getDstPort());
|
||||
bkc=connectMap.get(new Pair<IPv6SocketAddress, IPv6SocketAddress>(localany, remote));
|
||||
if(bkc!=null) {
|
||||
bkc.accept(srcAddr, (NetworkPacket) packet);
|
||||
return true;
|
||||
@@ -239,7 +234,7 @@ public class PortBinder {
|
||||
return bindMap.containsValue(klalbVirtualSocketImpl);
|
||||
}
|
||||
public boolean checkIsConnect(BindableKLALBPacketConsumer kservers,InetSocketAddress isaf) throws BindException {
|
||||
return connectMap.containsKey(new Pair<InetSocketAddress, InetSocketAddress>( new InetSocketAddress(kservers.getLocalInetAddress(), kservers.getLocalPort()),isaf));
|
||||
return connectMap.containsKey(new Pair<IPv6SocketAddress, IPv6SocketAddress>( new IPv6SocketAddress(IPv6Address.valueOf( kservers.getLocalInetAddress()), kservers.getLocalPort()),IPv6SocketAddress.valueOf( isaf)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
|
||||
public class SendItem<T extends NetworkPacket> {
|
||||
|
||||
private long packetLength;
|
||||
private T packet;
|
||||
private final long packetLength;
|
||||
private final T packet;
|
||||
private long sendtime=System.nanoTime();
|
||||
|
||||
public SendItem(T packet) {
|
||||
@@ -25,5 +25,9 @@ public class SendItem<T extends NetworkPacket> {
|
||||
public long getPacketLength() {
|
||||
return packetLength;
|
||||
}
|
||||
|
||||
public void setSendtime(long sendtimex) {
|
||||
this.sendtime=sendtimex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class SocketBridgeConfigItem extends KLALBConfigItem {
|
||||
if(string.startsWith("SocketBridge")) {
|
||||
return new DefaultSocketBridgeFactory();
|
||||
}else if(string.startsWith("MinecraftSocketBridge")) {
|
||||
return new DefaultMinecraftSocketBridgeFactory(controller.getSelf().getAddress(), Integer.parseInt(string.substring(21)));
|
||||
return new DefaultMinecraftSocketBridgeFactory(controller.getSelf().getAddress().toInet6Address(), Integer.parseInt(string.substring(21)));
|
||||
}
|
||||
throw new IllegalArgumentException("unknown SocketBridge type:"+string);
|
||||
}
|
||||
|
||||
@@ -342,7 +342,6 @@ public class SplitedDatagramKLALBPacketLink extends AbstractKLALBPacketLink impl
|
||||
|
||||
@Override
|
||||
public void writePacket(ByteBuffer kp) throws IOException {
|
||||
incOutput(kp.remaining());
|
||||
pslr.write(kp);
|
||||
}
|
||||
|
||||
@@ -351,7 +350,6 @@ public class SplitedDatagramKLALBPacketLink extends AbstractKLALBPacketLink impl
|
||||
ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(65535);
|
||||
pbdr.read(bbf );
|
||||
bbf.flip();
|
||||
incInput(bbf.remaining());
|
||||
return bbf;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ import org.kne.cloud.network.TimeoutTimer;
|
||||
import org.kne.io.KNEChannels;
|
||||
|
||||
public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
|
||||
private static final boolean debug = false;
|
||||
private volatile long timeoutTimer;
|
||||
private volatile boolean timerenabled=false;
|
||||
private boolean enableBuffer=true;
|
||||
@@ -126,6 +127,7 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
checkflush();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,7 +142,6 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
|
||||
szeWrite.limit(4);
|
||||
//szeWrite.clear();
|
||||
incOutput(kp.limit());
|
||||
szeWrite.putInt(kp.limit());
|
||||
szeWrite.flip();
|
||||
KLALBVirtualSocketChannel obj = null;
|
||||
@@ -150,42 +151,7 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
|
||||
}
|
||||
|
||||
private ByteBuffer[] bbfwx=new ByteBuffer[100<<1];
|
||||
{
|
||||
for(int i=0;i<100;i++) {
|
||||
bbfwx[i<<1]=NetworkPacket.bufferAllocator.allocate(4);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void writePackets(ByteBuffer[] kpp,int off,int len) throws IOException {
|
||||
if(len>100) {
|
||||
ByteBuffer[] bbfw=new ByteBuffer[len<<1];
|
||||
for(int i=0;i<len;i++) {
|
||||
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
|
||||
szeWrite.limit(4);
|
||||
//szeWrite.clear();
|
||||
incOutput(kpp[off+i].limit());
|
||||
szeWrite.putInt(kpp[off+i].limit());
|
||||
szeWrite.flip();
|
||||
KLALBVirtualSocketChannel obj = null;
|
||||
bbfw[i<<1]=szeWrite;
|
||||
bbfw[(i<<1)+1]=kpp[off+i];
|
||||
}
|
||||
writableChannel.write(bbfw);
|
||||
}else {
|
||||
for(int i=0;i<len;i++) {
|
||||
bbfwx[i<<1].clear();
|
||||
bbfwx[i<<1].limit(4);
|
||||
incOutput(kpp[off+i].limit());
|
||||
bbfwx[i<<1].putInt(kpp[off+i].limit());
|
||||
bbfwx[i<<1].flip();
|
||||
bbfwx[(i<<1)+1]=kpp[off+i];
|
||||
}
|
||||
writableChannel.write(bbfwx,0,len<<1);
|
||||
}
|
||||
checkflush();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@@ -203,7 +169,6 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
szeRead.flip();
|
||||
int size=szeRead.getInt(0);
|
||||
kp=NetworkPacket.bufferAllocator.allocate(size);
|
||||
incInput(size);
|
||||
kp.limit(size);
|
||||
KNEChannels.readFully(readableChannel, kp);
|
||||
kp.flip();
|
||||
@@ -213,41 +178,7 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeKLALBPackets(List<KLALBPacket> pkts) throws IOException {
|
||||
KLALBVirtualSocketChannel obj = null;
|
||||
if(writableChannel instanceof KLALBVirtualSocketChannel) {
|
||||
obj=(KLALBVirtualSocketChannel) writableChannel;
|
||||
}
|
||||
boolean isaflush=false;
|
||||
if(obj!=null) {
|
||||
isaflush=obj.isAutoFlush();
|
||||
obj.setAutoFlush(false);
|
||||
}
|
||||
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
|
||||
szeWrite.limit(4);
|
||||
for(KLALBPacket kp:pkts) {
|
||||
szeWrite.clear();
|
||||
int length=(int) kp.getTotalLength();
|
||||
incOutput(length);
|
||||
szeWrite.putInt(length);
|
||||
szeWrite.flip();
|
||||
|
||||
|
||||
writableChannel.write(szeWrite);
|
||||
|
||||
KLALBPacket.writeKLALBPacketToChannel(writableChannel, kp);
|
||||
|
||||
}
|
||||
if(obj!=null) {
|
||||
obj.flush();
|
||||
}
|
||||
|
||||
checkflush();
|
||||
if(obj!=null) {
|
||||
obj.setAutoFlush(isaflush);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
@@ -257,35 +188,25 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
szeWrite.limit(4);
|
||||
//szeWrite.clear();
|
||||
int length=(int) kp.getTotalLength();
|
||||
incOutput(length);
|
||||
szeWrite.putInt(length);
|
||||
szeWrite.flip();
|
||||
KLALBVirtualSocketChannel obj = null;
|
||||
if(writableChannel instanceof KLALBVirtualSocketChannel) {
|
||||
obj=(KLALBVirtualSocketChannel) writableChannel;
|
||||
}
|
||||
boolean isaflush=false;
|
||||
if(obj!=null) {
|
||||
isaflush=obj.isAutoFlush();
|
||||
obj.setAutoFlush(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
writableChannel.write(szeWrite);
|
||||
|
||||
if(debug) {
|
||||
|
||||
AtomicLong al=new AtomicLong(0);
|
||||
KLALBPacket.writeKLALBPacketToChannel(new MonitoredChannel(writableChannel,null,new AtomicLong[] { al}), kp);
|
||||
if(length!=al.get()) {
|
||||
throw new StreamCorruptedException(kp+" packet length error:"+al.get()+"!="+length);
|
||||
}
|
||||
}else {
|
||||
KLALBPacket.writeKLALBPacketToChannel(writableChannel, kp);
|
||||
}
|
||||
|
||||
|
||||
KLALBPacket.writeKLALBPacketToChannel(writableChannel, kp);
|
||||
if(obj!=null) {
|
||||
obj.flush();
|
||||
}
|
||||
checkflush();
|
||||
/*AtomicLong al=new AtomicLong(0);
|
||||
KLALBPacket.writeKLALBPacketToChannel(new MonitoredChannel(connectSocket,null,new AtomicLong[] { al}), kp);
|
||||
if(length!=al.get()) {
|
||||
throw new StreamCorruptedException(kp+" packet length error:"+al.get()+"!="+length);
|
||||
}*/
|
||||
if(obj!=null) {
|
||||
obj.setAutoFlush(isaflush);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkflush() throws IOException {
|
||||
@@ -302,13 +223,13 @@ public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implem
|
||||
KNEChannels.readFully(readableChannel, szeWrite);
|
||||
szeWrite.flip();
|
||||
int readSize=szeWrite.getInt();
|
||||
incInput(readSize);
|
||||
KLALBPacket kp=KLALBPacket.readKLALBPacketFromChannel(readableChannel);
|
||||
/*
|
||||
long kpl=kp.getLength();
|
||||
if(debug) {
|
||||
long kpl=kp.getTotalLength();
|
||||
if(kpl!=readSize) {
|
||||
throw new StreamCorruptedException(kp+" packet length error:"+kpl+"!="+readSize);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
return kp;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 VADDRPacket extends KLALBPacket {
|
||||
private static final int HEADER_LENGTH=18;
|
||||
public Inet6AddressGroup getVaddr() {
|
||||
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 getVaddr() {
|
||||
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 VADDRPacket(Inet6AddressGroup vaddr) {
|
||||
public VADDRPacket(IPv6AddressGroup vaddr) {
|
||||
super(VADDR,HEADER_LENGTH);
|
||||
klalbHeader.put(1, vaddr.getAddress().getAddress());
|
||||
klalbHeader.putLong(1, vaddr.getAddress().getHigh());
|
||||
klalbHeader.putLong(9, vaddr.getAddress().getLow());
|
||||
klalbHeader.put(17,(byte) vaddr.getPrefixLength());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package org.kne.cloud.network.klalb.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.LineBorder;
|
||||
|
||||
import org.jfree.chart.ChartPanel;
|
||||
import org.jfree.chart.JFreeChart;
|
||||
import org.jfree.chart.plot.dial.DialPlot;
|
||||
import org.jfree.chart.plot.dial.DialPointer;
|
||||
import org.jfree.chart.plot.dial.DialTextAnnotation;
|
||||
import org.jfree.chart.plot.dial.StandardDialFrame;
|
||||
import org.jfree.chart.plot.dial.StandardDialRange;
|
||||
import org.jfree.chart.plot.dial.StandardDialScale;
|
||||
import org.jfree.chart.title.TextTitle;
|
||||
import org.jfree.data.general.DefaultValueDataset;
|
||||
|
||||
public class DialPanel extends JPanel {
|
||||
|
||||
private DialTextAnnotation textAnnotation;
|
||||
private DialPlot plot;
|
||||
|
||||
public DialPanel(int size,String title,DefaultValueDataset primary, DefaultValueDataset secondary,
|
||||
Color pointerColor, Color outlineColor) {
|
||||
plot=createDialPlot(primary,secondary,pointerColor,outlineColor);
|
||||
textAnnotation = new DialTextAnnotation("");
|
||||
textAnnotation.setFont(UIEnv.getFont().deriveFont(20.0f));
|
||||
plot.addLayer(textAnnotation);
|
||||
setLayout(new BorderLayout());
|
||||
add(createChartPanel (createChart(plot),new Dimension(size, size)),BorderLayout.CENTER);
|
||||
JLabel jlb=new JLabel(title);
|
||||
jlb.setFont(UIEnv.getFont().deriveFont(16.0f));
|
||||
jlb.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
add(jlb,BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
public DialTextAnnotation getTextAnnotation() {
|
||||
return textAnnotation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建图表面板
|
||||
* @param dashSize
|
||||
*/
|
||||
private ChartPanel createChartPanel(JFreeChart chart, Dimension dashSize) {
|
||||
ChartPanel panel = new ChartPanel(chart);
|
||||
panel.setPreferredSize(dashSize);
|
||||
panel.setSize(panel.getPreferredSize());
|
||||
panel.setBackground(Color.WHITE);
|
||||
panel.setBorder(new LineBorder(Color.LIGHT_GRAY));
|
||||
return panel;
|
||||
}
|
||||
/**
|
||||
* 创建图表
|
||||
*/
|
||||
private JFreeChart createChart(DialPlot plot) {
|
||||
JFreeChart chart = new JFreeChart(plot);
|
||||
chart.setBorderPaint(Color.WHITE);
|
||||
chart.setTitle((TextTitle)null);
|
||||
plot.setView(0, 0, 1, 1);
|
||||
return chart;
|
||||
}
|
||||
/**
|
||||
* 创建仪表盘图表
|
||||
*/
|
||||
private DialPlot createDialPlot(DefaultValueDataset primary, DefaultValueDataset secondary,
|
||||
Color pointerColor, Color outlineColor) {
|
||||
DialPlot plot = new DialPlot();
|
||||
plot.setDataset(1, primary);
|
||||
plot.setDataset(0, secondary);
|
||||
|
||||
StandardDialFrame frame = new StandardDialFrame();
|
||||
frame.setVisible(false);
|
||||
plot.setDialFrame(frame);
|
||||
|
||||
// 添加刻度
|
||||
StandardDialScale scale = new StandardDialScale(0, 100, -120, -300, 10, 5);
|
||||
scale.setTickRadius(0.80);
|
||||
scale.setTickLabelsVisible(false);
|
||||
plot.addScale(0, scale);
|
||||
|
||||
|
||||
// 添加指针
|
||||
addDialPointers(plot, pointerColor, outlineColor);
|
||||
|
||||
return plot;
|
||||
}
|
||||
/**
|
||||
* 为仪表盘添加颜色范围
|
||||
*/
|
||||
public void addDefaultDialRanges() {
|
||||
// 绿色范围: 0-70%
|
||||
StandardDialRange greenRange = new StandardDialRange(0, 70, Color.GREEN);
|
||||
addDialRange( greenRange);
|
||||
|
||||
// 黄色范围: 70-90%
|
||||
StandardDialRange yellowRange = new StandardDialRange(70, 90, Color.YELLOW);
|
||||
addDialRange( yellowRange);
|
||||
|
||||
// 红色范围: 90-100%
|
||||
StandardDialRange redRange = new StandardDialRange(90, 100, Color.RED);
|
||||
addDialRange( redRange);
|
||||
}
|
||||
|
||||
private static final double INNER=0.85;
|
||||
private static final double OUTER=0.90;
|
||||
public void addDialRange( StandardDialRange greenRange) {
|
||||
greenRange.setInnerRadius(INNER);
|
||||
greenRange.setOuterRadius(OUTER);
|
||||
plot.addLayer(greenRange);
|
||||
}
|
||||
|
||||
/**
|
||||
* 为仪表盘添加指针
|
||||
*/
|
||||
private void addDialPointers(DialPlot plot, Color primaryColor, Color secondaryColor) {
|
||||
// 次要指针(透明)
|
||||
DialPointer.Pointer secondaryPointer = new DialPointer.Pointer();
|
||||
secondaryPointer.setRadius(0.8);
|
||||
secondaryPointer.setFillPaint(new Color(secondaryColor.getRed(), secondaryColor.getGreen(),
|
||||
secondaryColor.getBlue(), 0));
|
||||
secondaryPointer.setOutlinePaint(secondaryColor);
|
||||
secondaryPointer.setDatasetIndex(0);
|
||||
plot.addLayer(secondaryPointer);
|
||||
|
||||
// 主要指针
|
||||
DialPointer.Pointer primaryPointer = new DialPointer.Pointer();
|
||||
primaryPointer.setRadius(0.8);
|
||||
primaryPointer.setFillPaint(primaryColor);
|
||||
primaryPointer.setOutlinePaint(primaryColor);
|
||||
primaryPointer.setDatasetIndex(1);
|
||||
plot.addLayer(primaryPointer);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.kne.cloud.network.klalb.ui;
|
||||
|
||||
import org.jfree.chart.ChartPanel;
|
||||
|
||||
public class Dials {
|
||||
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.klalb.KLALBUtils;
|
||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
|
||||
|
||||
@@ -110,10 +111,10 @@ public class GraphPanel extends JPanel {
|
||||
|
||||
|
||||
|
||||
private Map<Inet6Address,GraphNode> nodes=new ConcurrentHashMap<Inet6Address,GraphNode>();
|
||||
private Map<IPv6Address,GraphNode> nodes=new ConcurrentHashMap<IPv6Address,GraphNode>();
|
||||
private List<GraphEdgeGroup> edgeGroups=new ArrayList<GraphEdgeGroup>();
|
||||
|
||||
public Map<Inet6Address, GraphNode> getNodes() {
|
||||
public Map<IPv6Address, GraphNode> getNodes() {
|
||||
return nodes;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
package org.kne.cloud.network.klalb.ui;
|
||||
|
||||
import java.awt.AWTException;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.SystemTray;
|
||||
import java.awt.TrayIcon;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.ComponentListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.LineBorder;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
||||
import org.kne.cloud.network.klalb.CONST;
|
||||
import org.kne.cloud.network.klalb.KLALBController;
|
||||
import org.kne.cloud.network.klalb.KLALBRemoteLine;
|
||||
import org.kne.ui.XFrame;
|
||||
import org.kne.ui.YScrollPane;
|
||||
|
||||
public class KLALBStateGUI extends XFrame {
|
||||
private BufferedImage bi;
|
||||
|
||||
private TimerTask tsk;
|
||||
|
||||
private SystemTray st;
|
||||
|
||||
private TrayIcon ti;
|
||||
|
||||
public KLALBStateGUI(KLALBController kpcje) throws IOException {
|
||||
this(kpcje ,CONST.klalb+" network accelerator V"+CONST.klalbver);
|
||||
}
|
||||
public KLALBStateGUI(KLALBController kc,String title) throws IOException {
|
||||
setResizable(false);
|
||||
try {
|
||||
bi = ImageIO.read(KLALBStateGUI.class.getResourceAsStream("/assets/KNEL.png"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(bi!=null)
|
||||
setIconImage(bi);
|
||||
|
||||
setTitleColor(new Color(255, 255, 255, 250));
|
||||
//getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f));
|
||||
getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY));
|
||||
/*
|
||||
setTitleColor(new Color(0,0,0,80));
|
||||
getContentPane().setBackground(new Color(0,0,0,80));
|
||||
getTitlelabel().setForeground(Color.WHITE);*/
|
||||
|
||||
|
||||
|
||||
YScrollPane ysp = new YScrollPane(660);
|
||||
ysp.setOpaque(false);
|
||||
getContentPane().add(ysp);
|
||||
JPanel wv = ysp.getView();
|
||||
|
||||
/*JProgressBar progressBar = new JProgressBar();
|
||||
progressBar.setIndeterminate(true);
|
||||
progressBar.setForeground(Color.YELLOW);
|
||||
progressBar.setBorder(null);
|
||||
progressBar.setPreferredSize(new Dimension(100, 4));
|
||||
ysp.add(progressBar, BorderLayout.NORTH);*/
|
||||
wv.addComponentListener(new ComponentListener() {
|
||||
|
||||
@Override
|
||||
public void componentShown(ComponentEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentMoved(ComponentEvent e) {
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentHidden(ComponentEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
});
|
||||
setTitle(title);
|
||||
setSize(680, 430);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
//setVisible(true);
|
||||
|
||||
if (SystemTray.isSupported()) {
|
||||
st = SystemTray.getSystemTray();
|
||||
ti = new TrayIcon(bi);
|
||||
ti.setImageAutoSize(true);
|
||||
PopupMenu jpm = new PopupMenu();
|
||||
MenuItem mix = new MenuItem("open");
|
||||
mix.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
setVisible(true);
|
||||
}
|
||||
});
|
||||
jpm.add(mix);
|
||||
MenuItem mi = new MenuItem("exit");
|
||||
mi.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
close();
|
||||
}
|
||||
});
|
||||
jpm.add(mi);
|
||||
ti.setPopupMenu(jpm);
|
||||
try {
|
||||
st.add(ti);
|
||||
} catch (AWTException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
ti.addActionListener((x) -> {
|
||||
setVisible(true);
|
||||
});
|
||||
}
|
||||
|
||||
repaint();
|
||||
|
||||
/*progressBar.setIndeterminate(false);
|
||||
progressBar.setValue(100);
|
||||
progressBar.setForeground(Color.GREEN);*/
|
||||
Timer t= new Timer("状态刷新线程",true);
|
||||
tsk=new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (kc.getLines()) {
|
||||
loop:for (Iterator<IPv6NetworkLink> iterator = kc.getLines().iterator(); iterator.hasNext();) {
|
||||
IPv6NetworkLink link=iterator.next();
|
||||
if(link instanceof KLALBRemoteLine) {
|
||||
KLALBRemoteLine ent = (KLALBRemoteLine)link ;
|
||||
Component[] count=ysp.getView().getComponents();
|
||||
for (int i = 0; i < count.length; i++) {
|
||||
Component tp=count[i];
|
||||
if(tp instanceof TPanel) {
|
||||
if(((TPanel) tp).getTunnel().equals(ent)) {
|
||||
continue loop;
|
||||
}
|
||||
}
|
||||
}
|
||||
TPanel tp=new TPanel(ent);
|
||||
ysp.getView().add(tp);
|
||||
}
|
||||
}
|
||||
Component[] count=ysp.getView().getComponents();
|
||||
for (int i = 0; i < count.length; i++) {
|
||||
Component tp=count[i];
|
||||
if(tp instanceof TPanel) {
|
||||
if(kc.getLines().contains(((TPanel) tp).getTunnel())) {
|
||||
((TPanel) tp).updateTraffic();
|
||||
}else {
|
||||
ysp.getView().remove(tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
t.schedule(tsk, 500, 500);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
setVisible(false);
|
||||
if(tsk!=null) {
|
||||
tsk.cancel();
|
||||
}
|
||||
st.remove(ti);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException, InterruptedException {//,new MultipurposeSocketAddress("frp-mom.top:22226"),new MultipurposeSocketAddress("0.0.0.0:26468")
|
||||
KLALBStateGUI kcg=new KLALBStateGUI(new KLALBController());
|
||||
kcg.setVisible(true);
|
||||
//Thread.sleep(10000);
|
||||
//kcg.close();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@ import org.jfree.chart.ui.RectangleEdge;
|
||||
import org.jfree.data.general.DefaultValueDataset;
|
||||
import org.kne.cloud.network.MultipurposeSocketAddress;
|
||||
import org.kne.cloud.network.klalb.KLALBUtils;
|
||||
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
|
||||
import org.kne.cloud.network.perf.Kperf;
|
||||
import org.kne.cloud.network.perf.KperfReports;
|
||||
import org.kne.ui.XFrame;
|
||||
@@ -65,7 +65,7 @@ public class KperfGUI extends XFrame{
|
||||
private DialTextAnnotation downSpeedText;
|
||||
private JTextField sourceAddressField;
|
||||
|
||||
private QueueingMonitorDataImpl monitor;
|
||||
private SpeedAndTrafficAndDelayMonitorDataImpl monitor;
|
||||
|
||||
private DefaultValueDataset upPPS;
|
||||
|
||||
@@ -94,7 +94,7 @@ public class KperfGUI extends XFrame{
|
||||
updateButton();
|
||||
}
|
||||
@Override
|
||||
public void updateDial(QueueingMonitorDataImpl mdt) {
|
||||
public void updateDial(SpeedAndTrafficAndDelayMonitorDataImpl mdt) {
|
||||
monitor=mdt;
|
||||
}
|
||||
@Override
|
||||
@@ -504,27 +504,27 @@ public class KperfGUI extends XFrame{
|
||||
@Override
|
||||
public void run() {
|
||||
if(monitor!=null) {
|
||||
double outload = monitor.getOutSpeed() * 100.0 / monitor.getOutSpeedMax2();
|
||||
double outload = monitor.getOutSpeed() * 100.0 / monitor.getOutSpeedMax();
|
||||
if (Double.isFinite(outload)) {
|
||||
upSpeedText.setLabel(KLALBUtils.convertIBUint(monitor.getOutSpeedAvg()) + "/s");
|
||||
upSpeedText.setLabel(KLALBUtils.convertIBUint(monitor.getOutSpeed()) + "/s");
|
||||
upSpeed.setValue(Math.min(upSpeed.getValue().doubleValue() * 0.98 + outload * 0.02, 101.0));
|
||||
}
|
||||
|
||||
double inload = monitor.getInSpeed() * 100.0 / monitor.getInSpeedMax2();
|
||||
double inload = monitor.getInSpeed() * 100.0 / monitor.getInSpeedMax();
|
||||
if (Double.isFinite(inload)) {
|
||||
downSpeedText.setLabel(KLALBUtils.convertIBUint(monitor.getInSpeedAvg()) + "/s");
|
||||
downSpeedText.setLabel(KLALBUtils.convertIBUint(monitor.getInSpeed()) + "/s");
|
||||
downSpeed.setValue(Math.min(downSpeed.getValue().doubleValue() * 0.98 + inload * 0.02, 101.0));
|
||||
}
|
||||
|
||||
double outPPSload = monitor.getOutPPS() * 100.0 / monitor.getOutPPSMax2();
|
||||
double outPPSload = monitor.getOutPPS() * 100.0 / monitor.getOutPPSMax();
|
||||
if (Double.isFinite(outPPSload)) {
|
||||
upPPSText.setLabel(KLALBUtils.convertUintDefalut(monitor.getOutPPSAvg()) + "PPS");
|
||||
upPPSText.setLabel(KLALBUtils.convertUintDefalut(monitor.getOutPPS()) + "PPS");
|
||||
upPPS.setValue(Math.min(upPPS.getValue().doubleValue() * 0.98 + outPPSload * 0.02, 101.0));
|
||||
}
|
||||
|
||||
double inPPSload = monitor.getInPPS() * 100.0 / monitor.getInPPSMax2();
|
||||
double inPPSload = monitor.getInPPS() * 100.0 / monitor.getInPPSMax();
|
||||
if (Double.isFinite(inPPSload)) {
|
||||
downPPSText.setLabel(KLALBUtils.convertUintDefalut(monitor.getInPPSAvg()) + "PPS");
|
||||
downPPSText.setLabel(KLALBUtils.convertUintDefalut(monitor.getInPPS()) + "PPS");
|
||||
downPPS.setValue(Math.min(downPPS.getValue().doubleValue() * 0.98 + inPPSload * 0.02, 101.0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,9 +28,12 @@ import org.jfree.data.time.RegularTimePeriod;
|
||||
import org.jfree.data.time.TimePeriod;
|
||||
import org.jfree.data.time.TimeSeries;
|
||||
import org.jfree.data.time.TimeSeriesCollection;
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
||||
import org.kne.cloud.network.klalb.KLALBRemoteLine;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.TimestampMonitorValue;
|
||||
import org.kne.math.Long128;
|
||||
import org.kne.ui.XFrame;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
@@ -48,186 +51,186 @@ import java.awt.Font;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.JSlider;
|
||||
|
||||
public class LineMonitorGUI extends XFrame{
|
||||
public class LineMonitorGUI extends XFrame {
|
||||
private Timer timer;
|
||||
private Timer timer1;
|
||||
private Timer timer2;
|
||||
private TimerTask tsk3 ;
|
||||
private TimerTask tsk3;
|
||||
|
||||
private TimerTask tsk4, tsk5;
|
||||
private TimerTask d1;
|
||||
private TimerTask d2;
|
||||
|
||||
private TimeSeries spdup = new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
|
||||
private TimeSeries spddown = new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
|
||||
|
||||
private TimeSeries delayup = new TimeSeries(UIEnv.getRsb().getString("uploaddelay"));
|
||||
private TimeSeries delaydown = new TimeSeries(UIEnv.getRsb().getString("downloaddelay"));
|
||||
// private TimeSeries delayupmin=new TimeSeries("Upload delay minimum");
|
||||
// private TimeSeries delaydownmin=new TimeSeries("Download delay minimum");
|
||||
|
||||
|
||||
private TimerTask tsk4 ,tsk5;
|
||||
private TimerTask d1 ;
|
||||
private TimerTask d2 ;
|
||||
|
||||
private TimeSeries spdup=new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
|
||||
private TimeSeries spddown=new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
|
||||
|
||||
private TimeSeries delayup=new TimeSeries(UIEnv.getRsb().getString("uploaddelay"));
|
||||
private TimeSeries delaydown=new TimeSeries(UIEnv.getRsb().getString("downloaddelay"));
|
||||
|
||||
//private TimeSeries delayupmin=new TimeSeries("Upload delay minimum");
|
||||
//private TimeSeries delaydownmin=new TimeSeries("Download delay minimum");
|
||||
|
||||
private KLALBRemoteLine tr;
|
||||
private JTextField vaddrs;
|
||||
private JFreeChart jfc;
|
||||
private JFreeChart jfce;
|
||||
private JLabel spdp;
|
||||
private JLabel delp;
|
||||
private long timeRange=5000;
|
||||
private long[]values=new long[] {1000,2000,5000,10000,20000,50000,100000,200000,500000,1000000};
|
||||
private long timeRange = 5000;
|
||||
private long[] values = new long[] { 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000 };
|
||||
private JPanel panel_1;
|
||||
private JLabel lblNewLabel;
|
||||
//private ChartPanel delp;
|
||||
//private ChartPanel spdp;
|
||||
|
||||
// private ChartPanel delp;
|
||||
// private ChartPanel spdp;
|
||||
public LineMonitorGUI(KLALBRemoteLine t) {
|
||||
this.tr=t;
|
||||
this.tr = t;
|
||||
setSize(1200, 780);
|
||||
setLocationRelativeTo(null);
|
||||
|
||||
|
||||
setIconImage(UIEnv.getIcon());
|
||||
setTitle("Line Monitor:"+t.getMonitor().getName());
|
||||
setTitle("Line Monitor:" + t.getMonitor().getName());
|
||||
setTitleColor(UIEnv.getDefaultTitleColor());
|
||||
getContentPane().setBackground(UIEnv.getDefaultBackgroundColor());
|
||||
getTitlelabel().setFont(UIEnv.getFont().deriveFont(17.0f));
|
||||
getTitlepanel().setBorder(new LineBorder(Color.LIGHT_GRAY));
|
||||
|
||||
JPanel jp=new JPanel();
|
||||
|
||||
JPanel jp = new JPanel();
|
||||
jp.setLayout(new GridLayout(2, 1));
|
||||
getContentPane().add(jp);
|
||||
|
||||
TimeSeriesCollection tsc=new TimeSeriesCollection();
|
||||
|
||||
TimeSeriesCollection tsc = new TimeSeriesCollection();
|
||||
tsc.addSeries(spdup);
|
||||
tsc.addSeries(spddown);
|
||||
jfc = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("speermonitor"), UIEnv.getRsb().getString("time")+"(s)", UIEnv.getRsb().getString("speed")+"(KiB/s)", tsc);
|
||||
jfc = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("speermonitor"),
|
||||
UIEnv.getRsb().getString("time") + "(s)", UIEnv.getRsb().getString("speed") + "(KiB/s)", tsc);
|
||||
jfc.getXYPlot().setBackgroundPaint(Color.BLACK);
|
||||
jfc.getXYPlot().getRenderer().setSeriesPaint(0,Color.RED);
|
||||
jfc.getXYPlot().getRenderer().setSeriesPaint(1,Color.GREEN);
|
||||
jfc.getXYPlot().getRenderer().setSeriesPaint(0, Color.RED);
|
||||
jfc.getXYPlot().getRenderer().setSeriesPaint(1, Color.GREEN);
|
||||
changeFont(jfc);
|
||||
spdp = new JLabel();
|
||||
spdp.setBorder(new LineBorder(Color.DARK_GRAY));
|
||||
jp.add(spdp);
|
||||
|
||||
TimeSeriesCollection tsce=new TimeSeriesCollection();
|
||||
|
||||
TimeSeriesCollection tsce = new TimeSeriesCollection();
|
||||
tsce.addSeries(delayup);
|
||||
tsce.addSeries(delaydown);
|
||||
|
||||
//tsce.addSeries(delayupmin);
|
||||
//tsce.addSeries(delaydownmin);
|
||||
jfce = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("delaymonitor"), UIEnv.getRsb().getString("time")+"(s)", UIEnv.getRsb().getString("delay")+"(ms)", tsce);
|
||||
jfce.getXYPlot().setBackgroundPaint(Color.BLACK);
|
||||
jfce.getXYPlot().getRenderer().setSeriesPaint(0,Color.RED);
|
||||
jfce.getXYPlot().getRenderer().setSeriesPaint(1,Color.GREEN);
|
||||
|
||||
BasicStroke dotted = new BasicStroke(2, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND, 0, new float[]{0,6,0,6}, 0);
|
||||
/*jfce.getXYPlot().getRenderer().setSeriesPaint(2,Color.RED);
|
||||
jfce.getXYPlot().getRenderer().setSeriesStroke(2, dotted);
|
||||
jfce.getXYPlot().getRenderer().setSeriesPaint(3,Color.GREEN);
|
||||
jfce.getXYPlot().getRenderer().setSeriesStroke(3, dotted);*/
|
||||
// tsce.addSeries(delayupmin);
|
||||
// tsce.addSeries(delaydownmin);
|
||||
jfce = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("delaymonitor"),
|
||||
UIEnv.getRsb().getString("time") + "(s)", UIEnv.getRsb().getString("delay") + "(ms)", tsce);
|
||||
jfce.getXYPlot().setBackgroundPaint(Color.BLACK);
|
||||
jfce.getXYPlot().getRenderer().setSeriesPaint(0, Color.RED);
|
||||
jfce.getXYPlot().getRenderer().setSeriesPaint(1, Color.GREEN);
|
||||
|
||||
BasicStroke dotted = new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0,
|
||||
new float[] { 0, 6, 0, 6 }, 0);
|
||||
/*
|
||||
* jfce.getXYPlot().getRenderer().setSeriesPaint(2,Color.RED);
|
||||
* jfce.getXYPlot().getRenderer().setSeriesStroke(2, dotted);
|
||||
* jfce.getXYPlot().getRenderer().setSeriesPaint(3,Color.GREEN);
|
||||
* jfce.getXYPlot().getRenderer().setSeriesStroke(3, dotted);
|
||||
*/
|
||||
changeFont(jfce);
|
||||
delp = new JLabel();
|
||||
delp.setBorder(new LineBorder(Color.DARK_GRAY));
|
||||
jp.add(delp);
|
||||
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
panel.setOpaque(false);
|
||||
getContentPane().add(panel, BorderLayout.NORTH);
|
||||
panel.setLayout(new GridLayout(2, 1, 0, 0));
|
||||
|
||||
vaddrs = new JTextField();
|
||||
vaddrs.setHorizontalAlignment(SwingConstants.CENTER);
|
||||
vaddrs.setFont(new Font("宋体", Font.PLAIN, 14));
|
||||
vaddrs.setEditable(false);
|
||||
panel.add(vaddrs);
|
||||
vaddrs.setColumns(10);
|
||||
|
||||
panel.setLayout(new GridLayout(1, 1, 0, 0));
|
||||
|
||||
panel_1 = new JPanel();
|
||||
panel.add(panel_1);
|
||||
panel_1.setLayout(new BorderLayout(0, 0));
|
||||
|
||||
|
||||
JSlider windowSlider = new JSlider();
|
||||
windowSlider.setValue(2);
|
||||
windowSlider.setMaximum(9);
|
||||
panel_1.add(windowSlider, BorderLayout.CENTER);
|
||||
JLabel windowSelect = new JLabel("5s");
|
||||
windowSlider.addChangeListener(new ChangeListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
updateTimeRange(windowSlider,windowSelect);
|
||||
updateTimeRange(windowSlider, windowSelect);
|
||||
}
|
||||
});
|
||||
updateTimeRange(windowSlider,windowSelect);
|
||||
updateTimeRange(windowSlider, windowSelect);
|
||||
panel_1.add(windowSelect, BorderLayout.EAST);
|
||||
|
||||
|
||||
lblNewLabel = new JLabel(UIEnv.getRsb().getString("timerange"));
|
||||
panel_1.add(lblNewLabel, BorderLayout.WEST);
|
||||
Dimension dms=new Dimension(140, 20);
|
||||
|
||||
/*JButton btnNewButton_2 = new JButton("Pressure test");
|
||||
btnNewButton_2.setPreferredSize(dms);
|
||||
btnNewButton_2.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
tr.pressureTest();
|
||||
}
|
||||
});
|
||||
panel_1.add(btnNewButton_2);
|
||||
btnNewButton_2.setForeground(Color.BLUE);*/
|
||||
Dimension dms = new Dimension(140, 20);
|
||||
|
||||
/*
|
||||
* JButton btnNewButton_2 = new JButton("Pressure test");
|
||||
* btnNewButton_2.setPreferredSize(dms); btnNewButton_2.addActionListener(new
|
||||
* ActionListener() { public void actionPerformed(ActionEvent e) {
|
||||
* tr.pressureTest(); } }); panel_1.add(btnNewButton_2);
|
||||
* btnNewButton_2.setForeground(Color.BLUE);
|
||||
*/
|
||||
addWindowListener(new WindowListener() {
|
||||
|
||||
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
protected void updateTimeRange(JSlider windowSlider,JLabel windowSelect) {
|
||||
timeRange=values[windowSlider.getValue()];
|
||||
|
||||
protected void updateTimeRange(JSlider windowSlider, JLabel windowSelect) {
|
||||
timeRange = values[windowSlider.getValue()];
|
||||
synchronized (jfc) {
|
||||
|
||||
jfc.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
|
||||
|
||||
jfc.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
|
||||
spdup.setMaximumItemCount((int) timeRange);
|
||||
spddown.setMaximumItemCount((int) timeRange);
|
||||
}
|
||||
synchronized (jfce) {
|
||||
|
||||
jfce.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
|
||||
|
||||
jfce.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
|
||||
delayup.setMaximumItemCount((int) timeRange);
|
||||
delaydown.setMaximumItemCount((int) timeRange);
|
||||
}
|
||||
windowSelect.setText(timeRange/1000+"s");
|
||||
windowSelect.setText(timeRange / 1000 + "s");
|
||||
}
|
||||
|
||||
private void changeFont(JFreeChart jfc2) {
|
||||
jfc2.getTitle().setFont(UIEnv.getFont().deriveFont(16.0f));
|
||||
jfc2.getLegend().setItemFont(UIEnv.getFont());
|
||||
@@ -236,152 +239,157 @@ public class LineMonitorGUI extends XFrame{
|
||||
jfc2.getXYPlot().getDomainAxis().setLabelFont(UIEnv.getFont());
|
||||
jfc2.getXYPlot().getDomainAxis().setTickLabelFont(UIEnv.getFont());
|
||||
}
|
||||
|
||||
private void recordSpeedData() {
|
||||
if(isVisible()) {
|
||||
Millisecond ms= new Millisecond();
|
||||
|
||||
if (isVisible()) {
|
||||
Millisecond ms = new Millisecond(
|
||||
new Date(tr.getMonitor().getClock().getCurrentTimeMillis()));
|
||||
synchronized (jfc) {
|
||||
spdup.addOrUpdate(ms, tr.getMonitor().getOutSpeed()/1024.0);
|
||||
spddown.addOrUpdate(ms, tr.getMonitor().getInSpeed()/1024.0);
|
||||
spdup.addOrUpdate(ms, tr.getMonitor().getOutSpeed() / 1024.0);
|
||||
spddown.addOrUpdate(ms, tr.getMonitor().getInSpeed() / 1024.0);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void recordDelayData() {
|
||||
if(isVisible()) {
|
||||
Millisecond ms= new Millisecond();
|
||||
if (isVisible()) {
|
||||
|
||||
|
||||
|
||||
synchronized (jfce) {
|
||||
delayup.addOrUpdate(ms, (tr.getMonitor().getOutDelay()+tr.getMonitor().getQueueingDelay())/1000000.0);
|
||||
delaydown.addOrUpdate(ms, tr.getMonitor().getInDelay()/1000000.0);
|
||||
TimestampMonitorValue valup = tr.getMonitor().getUploadBandwidth().getRecentDelayEntry();
|
||||
if (valup != null) {
|
||||
Millisecond ms = new Millisecond(
|
||||
new Date(valup.getTimestamp().divide(new Long128(1000000L)).longValue()));
|
||||
//System.out.println(ms+" "+new Millisecond());
|
||||
delayup.addOrUpdate(ms, valup.getDelay() / 1000000.0);
|
||||
}
|
||||
TimestampMonitorValue valdown = tr.getMonitor().getDownloadBandwidth().getRecentDelayEntry();
|
||||
if (valdown != null) {
|
||||
Millisecond ms2 = new Millisecond(
|
||||
new Date(valdown.getTimestamp().divide(new Long128(1000000L)).longValue()));
|
||||
delaydown.addOrUpdate(ms2, valdown.getDelay() / 1000000.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b) {
|
||||
if(b) {
|
||||
if(timer==null) {
|
||||
timer=new Timer();
|
||||
timer1=new Timer();
|
||||
timer2=new Timer();
|
||||
tsk3= new TimerTask() {
|
||||
if (b) {
|
||||
if (timer == null) {
|
||||
timer = new Timer();
|
||||
timer1 = new Timer();
|
||||
timer2 = new Timer();
|
||||
tsk3 = new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
updateTraffic();
|
||||
}
|
||||
};
|
||||
tsk4= new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
recordSpeedData();
|
||||
}
|
||||
};
|
||||
|
||||
tsk5= new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
recordDelayData();
|
||||
}
|
||||
};
|
||||
d1= new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if(isVisible()) {
|
||||
synchronized (jfc) {
|
||||
ImageIcon i1=new ImageIcon(jfc.createBufferedImage(spdp.getWidth(), spdp.getHeight()));
|
||||
spdp.setIcon(i1);
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
updateTraffic();
|
||||
}
|
||||
}
|
||||
};
|
||||
d2= new TimerTask() {
|
||||
};
|
||||
tsk4 = new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if(isVisible()) {
|
||||
synchronized (jfce) {
|
||||
ImageIcon i2=new ImageIcon(jfce.createBufferedImage(delp.getWidth(), delp.getHeight()));
|
||||
delp.setIcon(i2);
|
||||
@Override
|
||||
public void run() {
|
||||
recordSpeedData();
|
||||
}
|
||||
};
|
||||
|
||||
tsk5 = new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
recordDelayData();
|
||||
}
|
||||
};
|
||||
d1 = new TimerTask() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (isVisible()) {
|
||||
synchronized (jfc) {
|
||||
ImageIcon i1 = new ImageIcon(
|
||||
jfc.createBufferedImage(spdp.getWidth(), spdp.getHeight()));
|
||||
spdp.setIcon(i1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.scheduleAtFixedRate(tsk3, 25, 25);
|
||||
timer1.scheduleAtFixedRate(tsk4, 5, 5);
|
||||
timer1.scheduleAtFixedRate(d1, 25, 25);
|
||||
timer2.scheduleAtFixedRate(tsk5, 5, 5);
|
||||
timer2.scheduleAtFixedRate(d2, 25, 25);
|
||||
}
|
||||
|
||||
}else {
|
||||
if(tsk3!=null)
|
||||
tsk3.cancel();
|
||||
if(tsk4!=null)
|
||||
tsk4.cancel();
|
||||
if(tsk5!=null)
|
||||
tsk5.cancel();
|
||||
if(d1!=null)
|
||||
d1.cancel();
|
||||
if(d2!=null)
|
||||
d2.cancel();
|
||||
if(timer!=null)
|
||||
timer.cancel();
|
||||
if(timer1!=null)
|
||||
timer1.cancel();
|
||||
};
|
||||
d2 = new TimerTask() {
|
||||
|
||||
if(timer2!=null)
|
||||
timer2.cancel();
|
||||
timer=null;
|
||||
@Override
|
||||
public void run() {
|
||||
if (isVisible()) {
|
||||
synchronized (jfce) {
|
||||
ImageIcon i2 = new ImageIcon(
|
||||
jfce.createBufferedImage(delp.getWidth(), delp.getHeight()));
|
||||
delp.setIcon(i2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
timer.scheduleAtFixedRate(tsk3, 25, 25);
|
||||
timer1.scheduleAtFixedRate(tsk4, 5, 5);
|
||||
timer1.scheduleAtFixedRate(d1, 25, 25);
|
||||
timer2.scheduleAtFixedRate(tsk5, 1, 1);
|
||||
timer2.scheduleAtFixedRate(d2, 25, 25);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (tsk3 != null)
|
||||
tsk3.cancel();
|
||||
if (tsk4 != null)
|
||||
tsk4.cancel();
|
||||
if (tsk5 != null)
|
||||
tsk5.cancel();
|
||||
if (d1 != null)
|
||||
d1.cancel();
|
||||
if (d2 != null)
|
||||
d2.cancel();
|
||||
if (timer != null)
|
||||
timer.cancel();
|
||||
if (timer1 != null)
|
||||
timer1.cancel();
|
||||
|
||||
if (timer2 != null)
|
||||
timer2.cancel();
|
||||
timer = null;
|
||||
}
|
||||
super.setVisible(b);
|
||||
}
|
||||
|
||||
public void updateTraffic() {
|
||||
switch (tr.getMonitor().getState()) {
|
||||
case MonitorData.OFFLINE:
|
||||
getTitlelabel().setForeground(Color.RED);
|
||||
break;
|
||||
case MonitorData.CONNECTING:
|
||||
getTitlelabel().setForeground(Color.YELLOW);
|
||||
break;
|
||||
case MonitorData.ONLINE:
|
||||
getTitlelabel().setForeground(Color.GREEN);
|
||||
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(isVisible()) {
|
||||
//spddown.fireSeriesChanged();
|
||||
//delaydown.fireSeriesChanged();
|
||||
Inet6AddressGroup irg=tr.getRemoteVaddr();
|
||||
String text;
|
||||
if(irg==null) {
|
||||
|
||||
text="unknown";
|
||||
}else {
|
||||
Inet6Address i6a= irg.getAddress();
|
||||
|
||||
text=i6a.getHostAddress();
|
||||
|
||||
}
|
||||
if(!vaddrs.getText().equals(text)) {
|
||||
vaddrs.setText(text);
|
||||
}
|
||||
case MonitorData.DOWN:
|
||||
getTitlelabel().setForeground(Color.RED);
|
||||
break;
|
||||
case MonitorData.UNSTABLE:
|
||||
getTitlelabel().setForeground(Color.YELLOW);
|
||||
break;
|
||||
case MonitorData.UP:
|
||||
getTitlelabel().setForeground(Color.GREEN);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (isVisible()) {
|
||||
// spddown.fireSeriesChanged();
|
||||
// delaydown.fireSeriesChanged();
|
||||
IPv6AddressGroup irg = tr.getRemoteVaddr();
|
||||
String text;
|
||||
if (irg == null) {
|
||||
|
||||
text = "unknown";
|
||||
} else {
|
||||
IPv6Address i6a = irg.getAddress();
|
||||
|
||||
text = i6a.toString();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ import javax.swing.JPopupMenu;
|
||||
import javax.swing.border.LineBorder;
|
||||
|
||||
import org.kne.cloud.network.MultipurposeSocketAddress;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.klalb.KLALBController;
|
||||
import org.kne.cloud.network.klalb.KLALBUtils;
|
||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
||||
@@ -60,7 +61,7 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
|
||||
private class InetGraphNode extends GraphNode{
|
||||
|
||||
private InetAddress address;
|
||||
private IPv6Address address;
|
||||
private JPopupMenu popupMenu;
|
||||
|
||||
public InetGraphNode() {
|
||||
@@ -68,7 +69,7 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
initign();
|
||||
}
|
||||
|
||||
public InetGraphNode(InetAddress address, Color color, double x, double y, boolean ismarked) {
|
||||
public InetGraphNode(IPv6Address address, Color color, double x, double y, boolean ismarked) {
|
||||
super(getText(address), color, x, y, ismarked);
|
||||
this.address=address;
|
||||
initign();
|
||||
@@ -82,7 +83,7 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(address.getHostAddress()), null);
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(address.toString()), null);
|
||||
}
|
||||
});
|
||||
popupMenu.add(mcpyitm);
|
||||
@@ -104,8 +105,8 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
KperfGUI kpfg=new KperfGUI();
|
||||
kpfg.setVisible(true);
|
||||
MultipurposeSocketAddress source=new MultipurposeSocketAddress("KLALB_Stream",controller.getIpv6Router().getLocator().getAddress().getHostAddress(),0);
|
||||
MultipurposeSocketAddress target=new MultipurposeSocketAddress("KLALB_Stream", address.getHostAddress(), 4564);
|
||||
MultipurposeSocketAddress source=new MultipurposeSocketAddress("KLALB_Stream",controller.getIpv6Router().getLocator().getAddress().toString(),0);
|
||||
MultipurposeSocketAddress target=new MultipurposeSocketAddress("KLALB_Stream", address.toString(), 4564);
|
||||
kpfg.setTarget(target,source);
|
||||
}
|
||||
});
|
||||
@@ -116,7 +117,7 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if(e.isPopupTrigger())
|
||||
if(e.getButton()==MouseEvent.BUTTON3)
|
||||
popupMenu.show(NetworkGraphPanel.this,e.getX(),e.getY());
|
||||
}
|
||||
|
||||
@@ -155,21 +156,15 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
|
||||
|
||||
|
||||
private static String getText(InetAddress address2) {
|
||||
String text;
|
||||
if(address2 instanceof Inet6Address) {
|
||||
text=KLALBUtils.parseAbbrIPv6(address2.getHostAddress());
|
||||
}else {
|
||||
text=address2.getHostAddress();
|
||||
}
|
||||
return text;
|
||||
private static String getText(IPv6Address address2) {
|
||||
return address2.toCompressedString();
|
||||
}
|
||||
|
||||
public InetAddress getAddress() {
|
||||
public IPv6Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(InetAddress address) {
|
||||
public void setAddress(IPv6Address address) {
|
||||
this.address = address;
|
||||
super.setText(getText(address));
|
||||
}
|
||||
@@ -192,18 +187,18 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
}
|
||||
}
|
||||
protected void loadNodes() {
|
||||
Map<Inet6Address, Long> addr= controller.getIpv6Router().getKlalbRouteProtol().getAddresses();
|
||||
Set<Inet6Address> ks=addr.keySet();
|
||||
for (Iterator<Inet6Address> iterator = ks.iterator(); iterator.hasNext();) {
|
||||
Inet6Address inet6Address = (Inet6Address) iterator.next();
|
||||
Map<IPv6Address, Long> addr= controller.getIpv6Router().getKlalbRouteProtol().getAddresses();
|
||||
Set<IPv6Address> ks=addr.keySet();
|
||||
for (Iterator<IPv6Address> iterator = ks.iterator(); iterator.hasNext();) {
|
||||
IPv6Address inet6Address = (IPv6Address) iterator.next();
|
||||
if(!getNodes().containsKey(inet6Address)) {
|
||||
Vector2 v2pos=super.getRandomPos();
|
||||
getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(controller.getIpv6Router().getLocator().getAddress())));
|
||||
}
|
||||
}
|
||||
Set<Inet6Address> kns=getNodes().keySet();
|
||||
for (Iterator<Inet6Address> iterator = kns.iterator(); iterator.hasNext();) {
|
||||
Inet6Address inet6Address = (Inet6Address) iterator.next();
|
||||
Set<IPv6Address> kns=getNodes().keySet();
|
||||
for (Iterator<IPv6Address> iterator = kns.iterator(); iterator.hasNext();) {
|
||||
IPv6Address inet6Address = (IPv6Address) iterator.next();
|
||||
if(!addr.containsKey(inet6Address)) {
|
||||
iterator.remove();
|
||||
}
|
||||
@@ -212,10 +207,10 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
synchronized (getEdgeGroups()) {
|
||||
|
||||
getEdgeGroups().clear();
|
||||
Map<Inet6Address, List<LinkDirection>> addr1= controller.getIpv6Router().getKlalbRouteProtol().getPaths();
|
||||
Set<Entry<Inet6Address, List<LinkDirection>>> salink=addr1.entrySet();
|
||||
for (Iterator<Entry<Inet6Address, List<LinkDirection>>> iterator = salink.iterator(); iterator.hasNext();) {
|
||||
Entry<Inet6Address, List<LinkDirection>> entry = (Entry<Inet6Address, List<LinkDirection>>) iterator.next();
|
||||
Map<IPv6Address, List<LinkDirection>> addr1= controller.getIpv6Router().getKlalbRouteProtol().getPaths();
|
||||
Set<Entry<IPv6Address, List<LinkDirection>>> salink=addr1.entrySet();
|
||||
for (Iterator<Entry<IPv6Address, List<LinkDirection>>> iterator = salink.iterator(); iterator.hasNext();) {
|
||||
Entry<IPv6Address, List<LinkDirection>> entry = (Entry<IPv6Address, List<LinkDirection>>) iterator.next();
|
||||
List<LinkDirection>lps=entry.getValue();
|
||||
for (Iterator<LinkDirection> iterator2 = lps.iterator(); iterator2.hasNext();) {
|
||||
LinkDirection linkPath = (LinkDirection) iterator2.next();
|
||||
@@ -240,15 +235,15 @@ public class NetworkGraphPanel extends GraphPanel {
|
||||
}
|
||||
|
||||
private GraphEdgeGroup getGroup(InetGraphNode a,InetGraphNode b) {
|
||||
for (Iterator iterator = getEdgeGroups().iterator(); iterator.hasNext();) {
|
||||
for (Iterator<GraphEdgeGroup> iterator = getEdgeGroups().iterator(); iterator.hasNext();) {
|
||||
GraphEdgeGroup graphEdgeGroup = (GraphEdgeGroup) iterator.next();
|
||||
if(graphEdgeGroup.match(a,b)) {
|
||||
return graphEdgeGroup;
|
||||
}
|
||||
}
|
||||
GraphEdgeGroup ng=new InetGraphEdgeGroup(a, b);
|
||||
Inet6Address aprev= controller.getIpv6Router().getKlalbRouteProtol().getDijkstraPrevNode((Inet6Address) a.getAddress());
|
||||
Inet6Address bprev= controller.getIpv6Router().getKlalbRouteProtol().getDijkstraPrevNode((Inet6Address) b.getAddress());
|
||||
IPv6Address aprev= controller.getIpv6Router().getKlalbRouteProtol().getDijkstraPrevNode( a.getAddress());
|
||||
IPv6Address bprev= controller.getIpv6Router().getKlalbRouteProtol().getDijkstraPrevNode( b.getAddress());
|
||||
|
||||
if( b.getAddress().equals(aprev)||a.getAddress().equals(bprev)) {
|
||||
ng.setShortest(true);
|
||||
|
||||
@@ -23,6 +23,7 @@ import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import org.kne.cloud.klalb.uitool.XDefaultListModel;
|
||||
import org.kne.cloud.network.MultipurposeSocketAddress;
|
||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||
import org.kne.cloud.network.klalb.KLALBController;
|
||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
||||
@@ -37,7 +38,7 @@ import java.awt.event.MouseListener;
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
public class NodeInformationPanel extends JPanel {
|
||||
private InetAddress address;
|
||||
private IPv6Address address;
|
||||
private KLALBRoutingProtocolAPIClient client;
|
||||
private KLALBController controller;
|
||||
private Image image;
|
||||
@@ -46,14 +47,14 @@ public class NodeInformationPanel extends JPanel {
|
||||
public KLALBController getController() {
|
||||
return controller;
|
||||
}
|
||||
public InetAddress getAddress() {
|
||||
public IPv6Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public Image getImage() {
|
||||
return image;
|
||||
}
|
||||
public NodeInformationPanel (KLALBController controller,InetAddress address,Image image) {
|
||||
public NodeInformationPanel (KLALBController controller,IPv6Address address,Image image) {
|
||||
this.controller=controller;
|
||||
this.address=address;
|
||||
this.image=image;
|
||||
@@ -115,16 +116,14 @@ public class NodeInformationPanel extends JPanel {
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent e) {
|
||||
if(e.isPopupTrigger()) {
|
||||
if(e.getButton()==MouseEvent.BUTTON3) {
|
||||
jpop.show(list, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
if(e.isPopupTrigger()) {
|
||||
jpop.show(list, e.getX(), e.getY());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,7 +150,7 @@ public class NodeInformationPanel extends JPanel {
|
||||
|
||||
client=new KLALBRoutingProtocolAPIClient(controller.getIpv6Router().getKlalbRouteProtol());
|
||||
try {
|
||||
client.requestOpenLines(new InetSocketAddress(address, KLALBRoutingProtocol.DEFAULT_PORT), (result)->{
|
||||
client.requestOpenLines(new InetSocketAddress( address.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT), (result)->{
|
||||
listModel.clear();
|
||||
for (MultipurposeSocketAddress multipurposeSocketAddress : result) {
|
||||
listModel.addElement(multipurposeSocketAddress);
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
package org.kne.cloud.network.klalb.ui;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JLabel;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.border.LineBorder;
|
||||
|
||||
import org.kne.cloud.network.klalb.KLALBRemoteLine;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.util.Objects;
|
||||
|
||||
public class TPanel extends JPanel {
|
||||
private JLabel tname;
|
||||
private JLabel targ;
|
||||
private KLALBRemoteLine tunnel;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(tunnel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
TPanel other = (TPanel) obj;
|
||||
return Objects.equals(tunnel, other.tunnel);
|
||||
}
|
||||
|
||||
public JLabel getTname() {
|
||||
return tname;
|
||||
}
|
||||
|
||||
public JLabel getTarg() {
|
||||
return targ;
|
||||
}
|
||||
|
||||
/**
|
||||
* @wbp.parser.constructor
|
||||
*/
|
||||
public TPanel(KLALBRemoteLine t) {
|
||||
this.tunnel = t;
|
||||
setOpaque(false);
|
||||
setLayout(new BorderLayout(0, 0));
|
||||
|
||||
tname = new JLabel();
|
||||
tname.setText(t.getMonitor().getName());
|
||||
tname.setFont(new Font("宋体", Font.BOLD, 16));
|
||||
add(tname, BorderLayout.WEST);
|
||||
|
||||
targ = new JLabel();
|
||||
targ.setFont(new Font("宋体", Font.PLAIN, 13));
|
||||
targ.setHorizontalAlignment(SwingConstants.TRAILING);
|
||||
targ.setForeground(Color.YELLOW);
|
||||
add(targ, BorderLayout.CENTER);
|
||||
|
||||
setBorder(new LineBorder(Color.BLACK));
|
||||
setSize(650, 25);
|
||||
setPreferredSize(getSize());
|
||||
}
|
||||
|
||||
private volatile long up, down, ups, downs;
|
||||
private volatile long delay=Long.MAX_VALUE;
|
||||
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
private void updateText() {
|
||||
String dl;
|
||||
if (delay == Long.MIN_VALUE)
|
||||
dl = "??";
|
||||
else
|
||||
dl = Long.toString(delay / 1000000L);
|
||||
targ.setText(bytesUnit(up) + "\u2191 " + bytesUnit(down) + "\u2193 " + bytesUnit(ups) + "/s\u2191 "
|
||||
+ bytesUnit(downs) + "/s\u2193 " + dl + "ms");
|
||||
}
|
||||
|
||||
public KLALBRemoteLine getTunnel() {
|
||||
return tunnel;
|
||||
}
|
||||
|
||||
private String bytesUnit(long v) {
|
||||
if (v >= 1024L * 1024 * 1024 * 1024 * 1024) {
|
||||
return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0)) + "PB";
|
||||
} else if (v >= 1024L * 1024 * 1024 * 1024) {
|
||||
return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0 * 1024.0)) + "TB";
|
||||
} else if (v >= 1024L * 1024 * 1024) {
|
||||
return String.format("%.1f", v / (1024.0 * 1024.0 * 1024.0)) + "GB";
|
||||
} else if (v >= 1024L * 1024) {
|
||||
return String.format("%.1f", v / (1024.0 * 1024.0)) + "MB";
|
||||
} else if (v >= 1024L) {
|
||||
return String.format("%.1f", v / (1024.0)) + "KB";
|
||||
} else {
|
||||
return v + "B";
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTraffic() {
|
||||
switch (tunnel.getMonitor().getState()) {
|
||||
case MonitorData.OFFLINE:
|
||||
tname.setForeground(Color.RED);
|
||||
break;
|
||||
case MonitorData.CONNECTING:
|
||||
tname.setForeground(Color.YELLOW);
|
||||
break;
|
||||
case MonitorData.ONLINE:
|
||||
tname.setForeground(Color.GREEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
up = tunnel.getMonitor().getOutTraffic();
|
||||
down = tunnel.getMonitor().getInTraffic();
|
||||
this.ups = tunnel.getMonitor().getOutSpeed();
|
||||
this.downs = tunnel.getMonitor().getInSpeed();
|
||||
this.delay = tunnel.getMonitor().getLatency();
|
||||
//System.out.println(delay);
|
||||
updateText();
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user