This commit is contained in:
Administrator
2025-04-24 10:16:38 +08:00
parent 6de65562be
commit 7267aec1fd
108 changed files with 7621 additions and 1890 deletions
@@ -14,15 +14,15 @@ import java.util.concurrent.atomic.AtomicInteger;
public class ACKTPacket extends KLALBPacket implements PortPacket {
private static final int HEADER_LENGTH=28;
private static final int HEADER_LENGTH=35;
public ACKTPacket(int sport,int dport,long number,boolean avaliable,boolean congress,long rcvSpeed,int sendcount) {
public ACKTPacket(int sport,int dport,long number,long avaliableRcvWindow,boolean congress,long rcvSpeed,int sendcount) {
super(ACKT,HEADER_LENGTH);
klalbHeader.putInt(sport);
klalbHeader.putInt(dport);
klalbHeader.putLong(number);
klalbHeader.put((byte) sendcount);
klalbHeader.put((byte) (avaliable?1:0));
klalbHeader.putLong(avaliableRcvWindow);
klalbHeader.put((byte) (congress?1:0));
klalbHeader.putLong(rcvSpeed);
}
@@ -33,7 +33,7 @@ public class ACKTPacket extends KLALBPacket implements PortPacket {
@Override
public String toString() {
return "ACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[] "+isAvaliable();
return "ACKT "+getSport()+"->"+getDport()+" "+getNumber()+"[] avaliable:"+getAvaliableRcvWindow();
}
public int getSport() {
@@ -41,7 +41,7 @@ public class ACKTPacket extends KLALBPacket implements PortPacket {
}
public boolean isCongress() {
return klalbHeader.get(19)!=0;
return klalbHeader.get(26)!=0;
}
public int getDport() {
@@ -52,8 +52,8 @@ public class ACKTPacket extends KLALBPacket implements PortPacket {
return klalbHeader.getLong(9);
}
public boolean isAvaliable() {
return klalbHeader.get(18)!=0;
public long getAvaliableRcvWindow() {
return klalbHeader.getLong(18);
}
@@ -61,6 +61,6 @@ public class ACKTPacket extends KLALBPacket implements PortPacket {
return klalbHeader.getInt(17);
}
public long getRcvSpeed() {
return klalbHeader.getLong(20);
return klalbHeader.getLong(27);
}
}
@@ -41,7 +41,7 @@ public class ADDLINESPacket extends KLALBPacket {
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
public void writeToChannel(WritableByteChannel dto) throws IOException {
byte[]bta=lines.getBytes(Charset.forName("UTF-8"));
klalbHeader.putChar(1,(char) bta.length);
super.writeToChannel(dto);
@@ -49,7 +49,7 @@ public class ADDLINESPacket extends KLALBPacket {
}
@Override
protected void readFromChannel(ReadableByteChannel din) throws IOException {
public void readFromChannel(ReadableByteChannel din) throws IOException {
super.readFromChannel(din);
int lth=klalbHeader.getChar(1);
byte[]b=new byte[lth];
@@ -0,0 +1,97 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
public abstract class AbstractKLALBPacketLink implements KLALBPacketLink {
private AtomicLong[] inputTrafficCounters;
private AtomicLong[] outputTrafficCounters;
private AtomicLong[] inputPacketsCounters;
private AtomicLong[] outputPacketsCounters;
@Override
public void setOutputPacketsCounters(AtomicLong[] outCounter) {
outputPacketsCounters=outCounter;
}
@Override
public void setInputPacketsCounters(AtomicLong[] inCounter) {
inputPacketsCounters=inCounter;
}
@Override
public void setOutputTrafficCounters(AtomicLong[] outCounter) {
this.outputTrafficCounters=outCounter;
}
@Override
public void setInputTrafficCounters(AtomicLong[] inCounter) {
this.inputTrafficCounters=inCounter;
}
public AtomicLong[] getInputTrafficCounters() {
return inputTrafficCounters;
}
public AtomicLong[] getOutputTrafficCounters() {
return outputTrafficCounters;
}
public AtomicLong[] getInputPacketsCounters() {
return inputPacketsCounters;
}
public AtomicLong[] getOutputPacketsCounters() {
return outputPacketsCounters;
}
protected void incOutput(int packetLength) {
if(outputTrafficCounters!=null) {
for(AtomicLong al:outputTrafficCounters) {
al.addAndGet(packetLength);
}
}
if(outputPacketsCounters!=null) {
for(AtomicLong al:outputPacketsCounters) {
al.incrementAndGet();
}
}
}
protected void incInput(int packetLength) {
if(inputTrafficCounters!=null) {
for(AtomicLong al:inputTrafficCounters) {
al.addAndGet(packetLength);
}
}
if(inputPacketsCounters!=null) {
for(AtomicLong al:inputPacketsCounters) {
al.incrementAndGet();
}
}
}
@Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
ByteBuffer dataWrite=NetworkPacket.bufferAllocator.allocate((int) kp.getLength());
//dataWrite.clear();
KLALBPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel( dataWrite), kp);
dataWrite.flip();
writePacket(dataWrite);
}
@Override
public KLALBPacket readKLALBPacket() throws IOException {
ByteBuffer buffer=readPacket();
if(buffer==null) {
return null;
}
return KLALBPacket.readKLALBPacketFromChannel(KNEChannels.newReadableChannel(buffer));
}
}
@@ -1,36 +0,0 @@
package org.kne.cloud.network.klalb;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class ByteArrayPool {
private Queue<byte[]> rec;
private int maxcount;
private int length;
public ByteArrayPool(int maxcount, int length) {
super();
this.maxcount = maxcount;
this.length = length;
rec=new ConcurrentLinkedQueue<byte[]>();
}
public void back(byte[]b) {
if(b.length!=length)
throw new IllegalArgumentException("wrong length");
rec.offer(b);
}
public byte[] borrow() {
byte[]b=rec.poll();
if(b==null) {
b=new byte[length];
}
return b;
}
public int getMaxCount() {
return maxcount;
}
public int getLength() {
return length;
}
}
@@ -1,113 +0,0 @@
package org.kne.cloud.network.klalb;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.kne.concurrent.SpinLock;
import org.kne.debug.TimeDebugger;
/*
public class ByteBufferPool {
private Queue<ByteBuffer> rec;
private int maxcount;
private int length;
private boolean direct;
public ByteBufferPool(int maxcount, int length,boolean direct) {
super();
this.maxcount = maxcount;
this.length = length;
this.direct=direct;
rec=new ConcurrentLinkedQueue<ByteBuffer>();
}
public ByteBufferPool(int maxcount, int length) {
this(maxcount, length, true);
}
public void back(ByteBuffer b) {
if(b.capacity()!=length)
throw new IllegalArgumentException("wrong length");
b.clear();
rec.offer(b);
}
public ByteBuffer borrow() {
ByteBuffer b=rec.poll();
if(b==null) {
if(direct)
b=ByteBuffer.allocateDirect(length);
else
b=ByteBuffer.allocate(length);
}
return b;
}
public int getMaxCount() {
return maxcount;
}
public int getLength() {
return length;
}
}*/
public class ByteBufferPool {
private ByteBuffer[]rec;
private volatile int pos=0;
private Lock lock=new SpinLock();
private int maxcount;
private int length;
private int mcj;
private boolean direct;
public ByteBufferPool(int maxcount, int length,boolean direct) {
super();
this.maxcount = maxcount;
this.length = length;
this.direct=direct;
rec=new ByteBuffer[maxcount];
mcj=rec.length-1;
}
public ByteBufferPool(int maxcount, int length) {
this(maxcount, length, true);
}
public void back(ByteBuffer b) {
if(b.capacity()!=length)
throw new IllegalArgumentException("wrong length");
b.clear();
lock.lock();
try {
if(pos<mcj)
rec[++pos]= b;
}finally{
lock.unlock();
}
}
public ByteBuffer borrow() {
ByteBuffer b=null;
lock.lock();
try {
if(pos>0) {
b=rec[pos--];
//rec[pos--]=null;
}
}finally{
lock.unlock();
}
if(b==null) {
if(direct)
b=ByteBuffer.allocateDirect(length);
else
b=ByteBuffer.allocate(length);
}
return b;
}
public int getMaxCount() {
return maxcount;
}
public int getLength() {
return length;
}
}
+6 -2
View File
@@ -2,7 +2,11 @@ package org.kne.cloud.network.klalb;
public class CONST {
public static final String klalb="KLALB";
public static final String klalbver="3.0";
public static final String klalbver="3.2";
public static final int bversion=3;
public static final int sversion=0;
public static final int sversion=1;
public static final int itemwidth = 720;
public static final int linepanelheight = 45;
public static final int settingheight = 30;
}
@@ -39,7 +39,7 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
klalbHeader.putChar((char) 0);
//dataBuffer.limit(mtulimit);
dataBuffer=ByteBuffer.allocate(mtulimit);
dataBuffer=NetworkPacket.bufferAllocator.allocate(mtulimit);
}
public int getSendcount() {
@@ -100,7 +100,7 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
}
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
public void writeToChannel(WritableByteChannel dto) throws IOException {
klalbHeader.put(17, (byte) getSendCounter());
klalbHeader.putChar(18, (char) dataBuffer.limit());
super.writeToChannel(dto);
@@ -109,13 +109,13 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
}
@Override
protected void readFromChannel(ReadableByteChannel din) throws IOException {
public void readFromChannel(ReadableByteChannel din) throws IOException {
super.readFromChannel(din);
numberc=Long.MIN_VALUE;
int limit=klalbHeader.getChar(18);
//dataBuffer.clear();
//dataBuffer.limit();
dataBuffer=ByteBuffer.allocate(limit);
dataBuffer=NetworkPacket.bufferAllocator.allocate(limit);
while(dataBuffer.hasRemaining()){
if(din.read(dataBuffer)==-1) {
throw new EOFException();
@@ -124,12 +124,5 @@ public class DATATPacket extends KLALBPacket implements PortPacket{
dataBuffer.flip();
}
@Override
public void dispose() {
super.dispose();
/*ByteBuffer datan=dataBuffer;
dataBuffer=null;
NetworkPacket.databufferpool_65535.back(datan);*/
}
}
@@ -125,12 +125,14 @@ import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import org.kne.cloud.network.DatagramServerSocket;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.SpeedLimiter;
public class DatagramKLALBPacketLink implements KLALBPacketLink {
public class DatagramKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
@Override
public String toString() {
@@ -145,17 +147,20 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink {
private ByteArrayOutputStream bos=new ByteArrayOutputStream(65535);
private DataOutputStream dos=new DataOutputStream(bos);
@Override
public void writePacket(KLALBPacket kp) throws IOException {
/*@Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
//System.out.println(" TX:"+kp);
KLALBPacket.writeKLALBPacketToStream(dos, kp);
byte[]bt=bos.toByteArray();
DatagramPacket dp=new DatagramPacket(bt,bt.length);
ds.send(dp);
bos.reset();
}
private byte[]bc=new byte[65535];
DataInputStream dis;
@Override
public KLALBPacket readPacket() throws IOException {
public KLALBPacket readKLALBPacket() throws IOException {
KLALBPacket kp=null;
do {
if(dis==null) {
@@ -176,8 +181,37 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink {
//System.out.println(" RX:"+kp);
}while(true);
return kp;
}*/
byte[]b=new byte[65536];
@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);
}
byte[]c=new byte[65536];
@Override
public ByteBuffer readPacket() throws IOException {
DatagramPacket dp;
if(ds instanceof DatagramServerSocket.SubDatagramSocket) {
dp=((DatagramServerSocket.SubDatagramSocket) ds).receive();
}else {
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();
return bbf;
}
@Override
public void close() throws IOException {
ds.close();
@@ -200,10 +234,7 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink {
@Override
public void flush() throws IOException {
byte[]bt=bos.toByteArray();
DatagramPacket dp=new DatagramPacket(bt,bt.length);
ds.send(dp);
bos.reset();
}
@@ -211,4 +242,6 @@ public class DatagramKLALBPacketLink implements KLALBPacketLink {
public boolean isStream() {
return false;
}
}
@@ -0,0 +1,47 @@
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() {
return Objects.hash(uuid);
}
@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;
return Objects.equals(uuid, other.uuid);
}
}
@@ -10,26 +10,6 @@ import org.kne.cloud.network.ipv6.IPv6Packet;
public class IPv6OverKLALBPacket extends KLALBPacket {
private static final int HEADER_LENGTH=9;
@Override
public boolean isSomeDisposed() {
return super.isDisposed()||ipv6Packet.isSomeDisposed();
}
@Override
public void lockAll() {
super.lockAll();
ipv6Packet.lockAll();
}
@Override
public void unlockAll() {
ipv6Packet.unlockAll();
super.unlockAll();
}
@Override
@@ -56,12 +36,6 @@ public class IPv6OverKLALBPacket extends KLALBPacket {
super(bb,HEADER_LENGTH);
this.ipv6Packet=new IPv6Packet();
}
@Override
public void disposeAll() {
super.disposeAll();
ipv6Packet.disposeAll();
}
public IPv6Packet getIPv6Packet() {
return ipv6Packet;
@@ -78,24 +52,16 @@ public class IPv6OverKLALBPacket extends KLALBPacket {
}
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
public void writeToChannel(WritableByteChannel dto) throws IOException {
klalbHeader.putLong(1, ipv6Packet.getLength());
super.writeToChannel(dto);
ipv6Packet.writeToChannel(dto);
}
@Override
protected void readFromChannel(ReadableByteChannel din,long length) throws IOException {
public void readFromChannel(ReadableByteChannel din,long length) throws IOException {
super.readFromChannel(din,length);
ipv6Packet.readFromChannel(din, klalbHeader.getLong(1));
}
@Override
public void doDisposeAfterSend() {
super.doDisposeAfterSend();
ipv6Packet.doDisposeAfterSend();
}
}
@@ -56,14 +56,18 @@ import org.kne.cloud.network.ipv6.IPv6TUNLoopbackNetworkLink;
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
import org.kne.cloud.network.srv6.PacketConsumer;
import org.kne.cloud.network.srv6.SRv6Router;
import org.kne.cloud.network.te.BandwidthDistributer;
import org.kne.cloud.network.te.DWRRLoadingBalanceAlgorithm;
import org.kne.concurrent.DisruptorExecutor;
import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.io.KNEChannels;
import org.pcap4j.packet.IpV6Packet.IpV6Header;
import com.google.gson.JsonElement;
public class KLALBController {
@@ -80,6 +84,12 @@ public class KLALBController {
private static List<IPMulticastDiscovery> ipmd=new ArrayList<>();
private List<InetAddress>dnsAddresses=new ArrayList<>();
public List<InetAddress> getDnsAddresses() {
return dnsAddresses;
}
private Timer twk=new Timer("网卡检测扫描计时器", true);
{
@@ -210,48 +220,49 @@ public class KLALBController {
continue;
}
if(networkInterface.isUp()) {
boolean b=true;
Enumeration<InetAddress>ei= networkInterface.getInetAddresses();
loop:while (ei.hasMoreElements()) {
InetAddress bidr = (InetAddress) ei.nextElement();
for (Iterator<IPMulticastDiscovery> iterator = ipmd.iterator(); iterator.hasNext();) {
IPMulticastDiscovery ipMulticastDiscovery = (IPMulticastDiscovery) iterator.next();
if(networkInterface.equals(ipMulticastDiscovery.getNinterface())) {
b=false;
break;
if(networkInterface.equals(ipMulticastDiscovery.getNinterface())&&bidr.equals(ipMulticastDiscovery.getBind().getAddress())) {
continue loop;
}
}
if(b) {
/*InetAddress bidr=null;
Enumeration<InetAddress>ei= networkInterface.getInetAddresses();
while (ei.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) ei.nextElement();
if(inetAddress instanceof Inet6Address) {
Inet6Address i6=(Inet6Address) inetAddress;
if(i6.getHostAddress().startsWith("fe80")) {
bidr=i6;
break;
}
}
}
if(bidr!=null)*/
try {
InetAddress bidr=InetAddress.getByName("::0");
IPMulticastDiscovery ipd=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("ff02::2486"),DISCOVERY_PORT), networkInterface,selflineTable);
//InetAddress bidr=InetAddress.getByName("::0");
if(bidr instanceof Inet6Address) {
IPMulticastDiscovery ipd=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("ff02::2486"),DISCOVERY_PORT), networkInterface,selflineTable,10000L);
ipd.setCon((mpa)->{
//System.out.println("添加本地IPv6链路:"+mpa);
addRemoteLines(mpa);
try {
if(!checkIsSelf(mpa))
addRemoteLines(mpa);
} catch (UnknownHostException e) {
}
});
ipd.start();
ipmd.add(ipd);
bidr=InetAddress.getByName("0.0.0.0");
IPMulticastDiscovery ipd2=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("224.0.0.86"),DISCOVERY_PORT), networkInterface,selflineTable);
}else if(bidr instanceof Inet4Address) {
//bidr=InetAddress.getByName("0.0.0.0");
IPMulticastDiscovery ipd2=new IPMulticastDiscovery(new InetSocketAddress(bidr,DISCOVERY_PORT), new InetSocketAddress(InetAddress.getByName("224.0.0.86"),DISCOVERY_PORT), networkInterface,selflineTable,10000L);
ipd2.setCon((mpa)->{
//System.out.println("添加本地IPv4链路:"+mpa);
addRemoteLines(mpa);
try {
if(!checkIsSelf(mpa))
addRemoteLines(mpa);
} catch (UnknownHostException e) {
}
});
ipd2.start();
ipmd.add(ipd2);
}
System.out.println("添加网卡:"+networkInterface);
}catch(BindException e) {
//e.printStackTrace();
@@ -259,8 +270,11 @@ public class KLALBController {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//}
}
}
@@ -270,6 +284,11 @@ public class KLALBController {
}
}
private boolean checkIsSelf(MultipurposeSocketAddress inetAddress) throws UnknownHostException {
return inetAddress.getInetAddress().isAnyLocalAddress()||inetAddress.getInetAddress().isLoopbackAddress()||selflineTable.contains(inetAddress);
}
}, 2000, 2000);
}
public SpeedAndTrafficMonitorDataImpl getLinkMonitor() {
@@ -326,10 +345,10 @@ public class KLALBController {
}
private Inet6AddressGroup self;
//private Inet6AddressGroup self;
public Inet6Address getSelf() {
return self.getAddress();
public Inet6AddressGroup getSelf() {
return srv6Router.getLocator();
}
private List<KLALBRemoteLine> lines=new CopyOnWriteArrayList<>();
private ReadWriteLock lineslock=new ReentrantReadWriteLock();
@@ -339,11 +358,16 @@ public class KLALBController {
}
private PortBinder streamPortBinder=new PortBinder(this);
private PortBinder rawPortBinder=new PortBinder(this);
protected PortBinder getStreamPortBinder() {
return streamPortBinder;
}
public PortBinder getRawPortBinder() {
return rawPortBinder;
}
public void reconnectImmediately() {
for (Iterator<KLALBRemoteLine> iterator = lines.iterator(); iterator.hasNext();) {
@@ -380,7 +404,8 @@ public class KLALBController {
}
public List<KLALBRemoteLine> addRemoteLines(MultipurposeSocketAddress target) {
public List<KLALBRemoteLine> addRemoteLines(MultipurposeSocketAddress target) {lineslock.writeLock().lock();
try {
List<KLALBRemoteLine>added=new ArrayList<>();
try {
Enumeration<NetworkInterface>eu= NetworkInterface.getNetworkInterfaces();
@@ -419,6 +444,9 @@ public class KLALBController {
}
return added;
}finally {
lineslock.writeLock().unlock();
}
}
public List<KLALBRemoteLine> removeRemoteLines(MultipurposeSocketAddress mpsa) {
@@ -477,15 +505,15 @@ public class KLALBController {
}
public void addRemoteLine(KLALBRemoteLine krs) {
lineslock.writeLock().lock();
try {
krs.setPacketReceiver(prc);
krs.setKlalbController(this);
krs.setLocalVaddrSupplier(()->{return self;});
krs.setLocalVaddrSupplier(()->{return getSelf();});
krs.startIO();
String selflineTable=generateSelfLineTable();
if(selflineTable!=null&&!selflineTable.equals(""))
krs.sendPacket(new ADDLINESPacket(selflineTable));
lineslock.writeLock().lock();
try {
lines.add(krs);
}finally {
lineslock.writeLock().unlock();
@@ -502,16 +530,12 @@ public class KLALBController {
}
return sbd.toString();
}
public KLALBController(Inet6Address self) {
this.self =new Inet6AddressGroup(self, PREFIX);
loadSRv6ProtocolStack();
}
private class KLALBProtocolPacketConsumer implements PacketConsumer{
@Override
public void accept(IPv6Packet packx) throws IOException {
HighPerformanceExecutor.defaultExecutor.execute(()->{
//HighPerformanceExecutor.defaultExecutor.execute(()->{
/*System.out.println("RCV:"+packx.getPayload().getData());
byte[]b=new byte[packx.getPayload().getData().limit()];
@@ -539,18 +563,18 @@ public class KLALBController {
}
}
}
packx.dispose();
});
//packx.dispose();
//});
}
}
private void loadSRv6ProtocolStack() {
srv6Router=new SRv6Router(self);
private void loadSRv6ProtocolStack(Inet6AddressGroup selfx,boolean enableVirtualAdapter) {
srv6Router=new SRv6Router(selfx);
if(enableVirtualAdapter)
try {
IPv6TUNLoopbackNetworkLink tunlink=new IPv6TUNLoopbackNetworkLink(new Inet6AddressGroup( srv6Router.getLocator().getAddress(),32),SRv6Router.MTU);
IPv6TUNLoopbackNetworkLink tunlink=new IPv6TUNLoopbackNetworkLink(new Inet6AddressGroup( srv6Router.getLocator().getAddress(),32),SRv6Router.MTU, dnsAddresses);
tunlink.setMonitor(datatMonitor);
srv6Router.getLinkTabel().add(tunlink);
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
@@ -558,8 +582,19 @@ public class KLALBController {
srv6Router.getProtocolNumberRegister().put(KLALBPacket.KLALB_PROTOCOL_NUMBER,new KLALBProtocolPacketConsumer());
System.out.println("SRv6协议栈已加载");
}
public KLALBController() {
this(true,null);
}
public KLALBController (Inet6Address self) {
this(self,true,null);
}
public KLALBController(Inet6Address self,boolean enableVirtualAdapter,List<InetAddress> dnsaddr) {
this.dnsAddresses=dnsaddr;
Inet6AddressGroup selfg =new Inet6AddressGroup(self, PREFIX);
loadSRv6ProtocolStack(selfg,enableVirtualAdapter);
}
public KLALBController(boolean enableVirtualAdapter,List<InetAddress> dnsaddr) {
this.dnsAddresses=dnsaddr;
SecureRandom sc=new SecureRandom();
byte[]v=new byte[16];
sc.nextBytes(v);
@@ -569,27 +604,31 @@ public class KLALBController {
v[3]=1;
v[14]=0;
v[15]=1;
Inet6AddressGroup selfx=null;
try {
this.self=new Inet6AddressGroup( (Inet6Address) InetAddress.getByAddress(v),PREFIX);
selfx=new Inet6AddressGroup( (Inet6Address) InetAddress.getByAddress(v),PREFIX);
} catch (UnknownHostException e) {
e.printStackTrace();
}
loadSRv6ProtocolStack();
loadSRv6ProtocolStack(selfx,enableVirtualAdapter);
}
public KLALBController(List<InetAddress> daddr) {
this(true,daddr);
}
public KLALBController(Inet6Address self, List<InetAddress> daddr) {
this(self,true,daddr);
}
public KLALBController(boolean enableVirtualAdapter) {
this(enableVirtualAdapter,null);
}
protected KLALBVirtualSocketImpl createVirtualImpl() {
return new KLALBVirtualSocketImpl(this);
}
protected void sendPacketToLinkAddress(Inet6Address addr, KLALBPacket packet)
throws IOException {
sendPacketToLinkAddress(addr, packet, 1);
}
private SRv6Router srv6Router;
@@ -603,7 +642,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
@Override
public void run() {
Map<Inet6Address,DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>> lines2 =new ConcurrentHashMap<>();
//Map<Inet6Address,DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>> lines2 =new ConcurrentHashMap<>();
for (Iterator<KLALBRemoteLine> iterator = lines.iterator(); iterator.hasNext();) {
KLALBRemoteLine klalbRemoteLine = (KLALBRemoteLine) iterator.next();
if(klalbRemoteLine.isClosed()) {
@@ -615,20 +654,20 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
}
}else {
if(klalbRemoteLine.getRemoteVaddr()!=null&&klalbRemoteLine.getMonitor().getState()==MonitorData.ONLINE) {
if(lines2.containsKey(klalbRemoteLine.getRemoteVaddr())) {
/* if(lines2.containsKey(klalbRemoteLine.getRemoteVaddr())) {
lines2.get(klalbRemoteLine.getRemoteVaddr()).getEntries().add(klalbRemoteLine);
}else {
ArrayList<KLALBRemoteLine>al1=new ArrayList<>();
al1.add(klalbRemoteLine);
lines2.put(klalbRemoteLine.getRemoteVaddr().getAddress(), new DWRRLoadingBalanceAlgorithm<>(al1));
}
}*/
if(!srv6Router.getLinkTabel().contains(klalbRemoteLine)) {
srv6Router.getLinkTabel().add(klalbRemoteLine);
}
}
}
}
for (Iterator<Entry<Inet6Address, DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>>> iterator = lines2.entrySet().iterator(); iterator.hasNext();) {
/*for (Iterator<Entry<Inet6Address, DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>>> iterator = lines2.entrySet().iterator(); iterator.hasNext();) {
Entry<Inet6Address, DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>> klalbRemoteLine = (Entry<Inet6Address, DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>>) iterator.next();
List<KLALBRemoteLine> lineList=klalbRemoteLine.getValue().getEntries();
lineList.forEach((r)->{
@@ -641,7 +680,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
}
}
KLALBController.this.lines2=lines2;
KLALBController.this.lines2=lines2;*/
if(srv6Router!=null) {
srv6Router.getLinkTabel().removeIf((v)->{
return (v instanceof KLALBRemoteLine)&&(!v.isUp());
@@ -649,7 +688,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
srv6Router.updateRouteTabel();
}
}
}, 1, 1);
}, 2, 2);
}
/*private void updateLines2(Inet6Address addr) throws SocketTimeoutException {
List<KLALBRemoteLine> l=new ArrayList();
@@ -675,122 +714,7 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
lines2.put(addr, l);
}
}*/
private Map<Inet6Address, DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>> lines2 = new ConcurrentHashMap<>();
protected void sendPacketToLinkAddress(Inet6Address addr, KLALBPacket packet, int count)
throws IOException {
if(packet==null)
throw new NullPointerException("packet is null!");
//TimeDebugger tdb=new TimeDebugger();
//tdb.putTime("start");
packet.genseq();
/*loop:while(true) {
if(packet.isDisposed())
return;
List<KLALBRemoteLine> lines2x;
lines2x=lines2.get(addr);
if (lines2x == null || lines2x.isEmpty()) {
throw new NoRouteToHostException("address unreachable: " + addr);
}
int count0 = Math.min(count, lines2x.size());
for (int i = 0; i < lines2x.size(); i++) {
KLALBRemoteLine krst =lines2x.get(i);
if(krst.getMonitor().getState()==MonitorData.ONLINE)
if(!packet.getSendRecord().contains(krst)) {
if(krst.getQueue().size()<10) {
packet.getSendRecord().add(krst);
//System.out.println(krst);
krst.sendPacket(packet);
count0--;
if (count0 <= 0)
break loop;
}
}
}
for (int i = 0; i < lines2x.size(); i++) {
KLALBRemoteLine krst =lines2x.get(i);
if(krst.getMonitor().getState()==MonitorData.ONLINE)
if(packet.getSendRecord().contains(krst)) {
if(krst.getQueue().size()<10) {
packet.getSendRecord().add(krst);
//System.out.println(krst);
krst.sendPacket(packet);
count0--;
if (count0 <= 0)
break loop;
}
}
}
LockSupport.parkNanos(50000);
//tdb.putTime("sendfailed");
}*/
//tdb.putTime("sendsuccess");
//tdb.print();
/* List<KLALBRemoteLine> lines2x;
lines2x=lines2.get(addr);
if (lines2x == null || lines2x.isEmpty()) {
throw new NoRouteToHostException("address unreachable: " + addr);
}
KLALBRemoteLine kr= lines2x.get(0);
kr.sendPacket(packet);
packet.getSendRecord().add(kr);*/
/*loop:while(true) {
if(packet.isDisposed())
return;
DWRRLoadingBalanceAlgorithm<KLALBRemoteLine> dwrlines2x;
dwrlines2x=lines2.get(addr);
if (dwrlines2x == null || dwrlines2x.getEntries().isEmpty()) {
throw new NoRouteToHostException("address unreachable: " + addr);
}
List<KLALBRemoteLine>lines2x=dwrlines2x.roundEntriesList();
int count0 = Math.min(count, lines2x.size());
for (int i = 0; i < lines2x.size(); i++) {
KLALBRemoteLine krst =lines2x.get(i);
if(krst.getMonitor().getState()==MonitorData.ONLINE)
if(!packet.getSendRecord().contains(krst)) {
if(krst.getQueue().size()<5) {
packet.getSendRecord().add(krst);
//System.out.println(krst);
krst.sendPacket(packet);
count0--;
if (count0 <= 0)
break loop;
}
}
}
for (int i = 0; i < lines2x.size(); i++) {
KLALBRemoteLine krst =lines2x.get(i);
if(krst.getMonitor().getState()==MonitorData.ONLINE)
if(packet.getSendRecord().contains(krst)) {
if(krst.getQueue().size()<5) {
packet.getSendRecord().add(krst);
//System.out.println(krst);
krst.sendPacket(packet);
count0--;
if (count0 <= 0)
break loop;
}
}
}
LockSupport.parkNanos(50000);
//tdb.putTime("sendfailed");
}*/
}
//private Map<Inet6Address, DWRRLoadingBalanceAlgorithm<KLALBRemoteLine>> lines2 = new ConcurrentHashMap<>();
@@ -804,11 +728,8 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
HighPerformanceExecutor.defaultExecutor.execute(()->{
IPv6Packet ipv=new IPv6Packet();
packet.getDisposeLock().lock();
try {
if(packet.isDisposed()) {
return;
}
if(showpacket)
System.out.println("KLALB_TX:"+packet);
@@ -816,10 +737,15 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
ipv.setTrafficClass(0);
ipv.setFlowLabel(flowlabel);
ipv.setHopLimit(255);
ipv.setSourceAddress(self.getAddress());
ipv.setSourceAddress(getSelf().getAddress());
ipv.setDestinationAddress(addr);
ipv.setPriority(packet.getPriority());
if(packet instanceof DATATPacket) {
ipv.setPromise(true);
}
ipv.enableECN();
/* if(b)
ipv.markCE();*/
ipv.setPayload(packet);
//System.out.println(ipv.getPayload().getProtocolNumber());
/*System.out.println("SND:"+ipv.getPayload().getData());
@@ -828,13 +754,12 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
System.out.println(Arrays.toString(b));*/
//packet.getSendRecord().add(null);
packet.incSendCounter();
}finally {
packet.getDisposeLock().unlock();
}
packet.putTimePassport("packedInIPv6");
packet.printPassport();
ipv.putTimePassport("packed");
srv6Router.putProtocolNumberPacketAndInsertSRH(ipv);
srv6Router.insertSRHandRoutePacket(ipv);
//srv6Router.putProtocolNumberPacketAndInsertSRHAsync(ipv);
});
}
@@ -869,7 +794,11 @@ private Timer trtr=new Timer("路由表刷新计时器", true);
try {
BandwidthDistributer<PortPair> bdr= bandwidthDistrmap.get(targetaAddress);
if(bdr==null) {
bandwidthDistrmap.put(targetaAddress, bdr=new BandwidthDistributer<>(1024*20000L*1024));
bdr=new BandwidthDistributer<>(1024*20000L*1024);
bdr.setTotalRequestUpdateConsumer((treq)->{
KLALBRoutingProtocol krp= srv6Router.getKlalbRouteProtol();
krp.updateTotalRequestBandwidth(targetaAddress,treq);});
bandwidthDistrmap.put(targetaAddress, bdr);
}
bdr.setDistrUpdateConsumer(portp, updateConsumer);
@@ -920,7 +849,6 @@ private List<MultipurposeSocketAddress> listens=new CopyOnWriteArrayList<>();
}
/*@Override
public void listen(MultipurposeSocketAddress msa) {
// TODO 自动生成的方法存根
@@ -8,10 +8,18 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.StreamCorruptedException;
import java.net.Inet6Address;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import org.kne.cloud.network.NetworkPacket;
import org.kne.io.KNEChannels;
public class KLALBInputStream extends DataInputStream {
private ReadableByteChannel channel;
public KLALBInputStream(InputStream in) throws IOException {
super(in);
channel=Channels.newChannel(in);
byte[]b=new byte[5];
readFully(b);
String s=new String(b,"ascii");
@@ -23,8 +31,16 @@ public class KLALBInputStream extends DataInputStream {
if(bv!=CONST.bversion)
throw new StreamCorruptedException("remote version is V"+bv+"."+sv+",not V"+CONST.klalbver);
}
public KLALBPacket readPacket() throws IOException {
public KLALBPacket readKLALBPacket() throws IOException {
int len=readInt();
return KLALBPacket.readKLALBPacketFromStream(this);
}
public ByteBuffer readPacket() throws IOException {
int len=readInt();
ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(len);
bbf.limit(len);
KNEChannels.readFully(channel, bbf);
return bbf;
}
}
+33 -1
View File
@@ -20,6 +20,8 @@ import org.kne.cloud.network.ipv6.RouteItem;
import org.kne.cloud.network.klalb.ui.KLALBStateGUI2;
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;
public class KLALBMain {
@@ -37,7 +39,7 @@ public class KLALBMain {
KLALBProxySystem kpcje=new KLALBProxySystem();
kpcje.loadConfigJson(configJson);
System.out.println("SRv6地址:"+kpcje.getKlalbController().getSelf().getHostAddress());
System.out.println("SRv6地址:"+kpcje.getKlalbController().getSelf().getAddress().getHostAddress());
try {
openGUI(kpcje);
}catch(RuntimeException e) {
@@ -152,10 +154,40 @@ public class KLALBMain {
System.out.println("请输入测速服务端地址:端口!");
}
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);
}
break;
//case "$$SYSTEM:":
//System.out.println();
//break;
case "nodebenchmark":
int nodenumber=100;
if(sc.length>=2) {
nodenumber=Integer.parseInt(sc[1]);
}
NodeBenchmark nbc=new NodeBenchmark(kpcje.getKlalbController(),nodenumber);
nbc.startPerfing();
break;
default:
System.out.println("未知命令,请输入help以查询命令说明");
}
@@ -4,19 +4,29 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Inet6Address;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
public class KLALBOutputStream extends DataOutputStream {
private WritableByteChannel channel;
public KLALBOutputStream(OutputStream out) throws IOException {
super(out);
this.channel=Channels.newChannel(out);
byte[]b=new byte[] {'K','L','A','L','B'};
write(b);
writeInt(CONST.bversion);
writeInt(CONST.sversion);
flush();
}
public void writePacket(KLALBPacket klb) throws IOException {
public void writeKLALBPacket(KLALBPacket klb) throws IOException {
writeInt((int) klb.getLength());
KLALBPacket.writeKLALBPacketToStream(this, klb);
}
public void writePacket(ByteBuffer kp) throws IOException {
writeInt( kp.limit());
channel.write(kp);
}
}
@@ -4,6 +4,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.StreamCorruptedException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
@@ -15,6 +16,8 @@ import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.perf.TEST1Packet;
import org.kne.cloud.network.perf.TESTNPacket;
public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public static final int KLALB_PROTOCOL_NUMBER=254;
@@ -32,12 +35,13 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public static final int VADDR=8;
public static final int ADDLINES=9;
public static final int NACKT=10;
public static final int TEST=11;
public static final int TESTN=11;
public static final int VADDRACK=12;
public static final int VADDRREQ=13;
public static final int IPV6OVERKLALB=14;
public static final int ADDR=15;
public static final int ADDRREQ=16;
public static final int TEST1=17;
//private static final int HEADER_CAPACITY = 32;
@@ -45,7 +49,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
//public static final ByteArrayPool dataarraypool=new ByteArrayPool(5000, 8192);
protected volatile ByteBuffer klalbHeader;
protected ByteBuffer klalbHeader;
protected KLALBPacket(ByteBuffer klalbHeader,int headerLength) {
super(KLALB_PROTOCOL_NUMBER,false);
@@ -55,7 +59,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public KLALBPacket(int type,int headerLength) {
super(KLALB_PROTOCOL_NUMBER,false);
klalbHeader=ByteBuffer.allocate(headerLength);
klalbHeader=NetworkPacket.bufferAllocator.allocate(headerLength);
klalbHeader.put((byte) type);
this.headerLength=headerLength;
}
@@ -83,7 +87,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
return joinqueuetime;
}
protected void writeToChannel(WritableByteChannel dto) throws IOException {
public void writeToChannel(WritableByteChannel dto) throws IOException {
sndtime=System.nanoTime();
dto.write(klalbHeader.slice(0, headerLength));
}
@@ -93,7 +97,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
return false;
}
protected void readFromChannel(ReadableByteChannel din,long length) throws IOException {
public void readFromChannel(ReadableByteChannel din,long length) throws IOException {
klalbHeader.limit(headerLength);
while(klalbHeader.hasRemaining()){
if(din.read(klalbHeader)==-1) {
@@ -135,13 +139,6 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
return klalbHeader;
}
public void dispose() {
super.dispose();
/* ByteBuffer datax=klalbHeader;
klalbHeader=null;
if(datax!=null)
KLALBPacket.databufferpool_40.back(datax);*/
}
public static KLALBPacket readKLALBPacketFromStream(DataInputStream in) throws IOException {
return readKLALBPacketFromChannel(Channels.newChannel(in));
@@ -149,14 +146,14 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
public static KLALBPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException {
while(true) {
ByteBuffer bb=databufferpool_40.borrow();
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40);
bb.limit(1);
while(bb.hasRemaining()){
if(in.read(bb)==-1) {
return null;
}
}
int type=bb.get(0);
int type=bb.get(0)&0xff;
bb.limit(bb.capacity());
KLALBPacket klp;
@@ -196,8 +193,8 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
klp=new NACKTPacket(bb);
klp.readFromChannel(in);
return klp;
case TEST:
klp=new TESTPacket(bb);
case TESTN:
klp=new TESTNPacket(bb);
klp.readFromChannel(in);
return klp;
case VADDRACK:
@@ -220,9 +217,13 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
klp=new ADDRREQPacket(bb);
klp.readFromChannel(in);
return klp;
case TEST1:
klp=new TEST1Packet(bb);
klp.readFromChannel(in);
return klp;
}
//throw new StreamCorruptedException("unknown package type:"+type);
System.err.println("ignore unknown KLALBPacket type:"+type);
throw new StreamCorruptedException("unknown package type:"+type);
//System.err.println("ignore unknown KLALBPacket type:"+type);
}
}
@@ -237,10 +238,7 @@ public abstract class KLALBPacket extends IPv6Packet.IPv6Payload {
return null;
}
public void doDisposeAfterSend() {
if(isDisposeAfterSend())
dispose();
}
private boolean ce=false;
public void setCE(boolean ce) {
this.ce=ce;
@@ -2,13 +2,26 @@ package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.MultipurposeSocketAddress;
public interface KLALBPacketLink {
public void writePacket(KLALBPacket kp) throws IOException;
public void setOutputTrafficCounters(AtomicLong[] al);
public void setOutputPacketsCounters(AtomicLong[] al);
public void setInputTrafficCounters(AtomicLong[] al);
public void setInputPacketsCounters(AtomicLong[] 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 readPacket()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;
@@ -11,11 +11,13 @@ import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -112,15 +114,43 @@ public class KLALBProxySystem {
case "KLALBController":
JsonElement vase= entry.get("VirtualAddress");
//System.out.println(vase);
List<InetAddress>daddr=new ArrayList<InetAddress>();
JsonElement vdns= entry.get("DNS");
if(vdns!=null) {
if(vdns instanceof JsonArray) {
JsonArray arr=(JsonArray) vdns;
for(JsonElement str:arr) {
try {
daddr.add((Inet6Address) InetAddress.getByName(str.getAsString()));
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}else {
try {
daddr.add((Inet6Address) InetAddress.getByName(vdns.getAsString()));
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
}
if(vase!=null) {
try {
klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase.getAsString()));
klalbController=new KLALBController((Inet6Address) InetAddress.getByName(vase.getAsString()),daddr);
} catch (UnknownHostException e) {
e.printStackTrace();
}
}else {
klalbController=new KLALBController();
klalbController=new KLALBController(daddr);
}
JsonElement vasn= entry.get("VirtualASN");
if(vasn!=null) {
klalbController.getIpv6Router().setASN (Long.parseLong( vasn.getAsString()));
}
JsonElement vsne=entry.get("VirtualSocketName");
//if(vsne!=null) {
MultipurposeSocketAddress.getSocketTypeRegister().put(vsne.getAsString(), klalbController.getSocketType());
@@ -280,7 +310,7 @@ public class KLALBProxySystem {
if(string.startsWith("SocketBridge")) {
return new DefaultSocketBridgeFactory();
}else if(string.startsWith("MinecraftSocketBridge")) {
return new DefaultMinecraftSocketBridgeFactory(klalbController.getSelf(), Integer.parseInt(string.substring(21)));
return new DefaultMinecraftSocketBridgeFactory(klalbController.getSelf().getAddress(), Integer.parseInt(string.substring(21)));
}
throw new IllegalArgumentException("unknown SocketBridge type:"+string);
}
@@ -5,42 +5,69 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.StreamCorruptedException;
import java.lang.foreign.MemorySegment;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.UnresolvedAddressException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.kne.cloud.clock.AdjustedNanoClock;
import org.kne.cloud.clock.ReliabilityBackoffTimeClock;
import org.kne.cloud.network.ByteBufferAllocator;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.SpeedLimiter;
import org.kne.cloud.network.ThreadTool;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6EmptyPayload;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader;
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
import org.kne.cloud.network.ipv6.Neighbor;
import org.kne.cloud.network.ipv6.RouteItem;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.monitor.NanoTimeSeries;
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
import org.kne.cloud.network.perf.TESTNPacket;
import org.kne.cloud.network.srv6.ACKSEQSSegmentRoutingTLV;
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
import org.kne.cloud.network.srv6.SEQSSegmentRoutingTLV;
import org.kne.cloud.network.te.BandwidthDistributer;
import org.kne.cloud.network.te.LoadingBalanceEntry;
import org.kne.concurrent.DisruptorExecutor;
import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.io.KNEChannels;
public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteLine> ,LoadingBalanceEntry<KLALBRemoteLine>{
public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteLine> {
private static final int HEADER_CALIBRATE = 40;
private static final boolean debug = false;
private static final boolean showpacket = false;
@@ -221,10 +248,19 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
}
private static long MIN_SPEED=256*1024L;
private SpeedLimiter congress = new SpeedLimiter(MIN_SPEED,10000000L);
private SpeedLimiter congress = new SpeedLimiter(MIN_SPEED,20*1000000L);//50*1000000L
private long congressSpeed = 0;
private double loadPercent = 1.01;
private double burstPercent = 1.3;//10.0
private double windowPercent = 2;
private long MIN_RTTVAR=25000000L;
private AtomicBoolean firstUpdate=new AtomicBoolean(true);
private volatile long RTTMin=1000000000L;
private volatile long RTTVar=1000000000L;
private volatile long RTTAvg=1000000000L;
private volatile long RTO=1000000000L;
protected void startIO() {
ThreadTool.makeVDaemonThreadIfSupport("远程接收线程", () -> {
//Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
@@ -251,87 +287,153 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
addressGroup=new Inet6AddressGroup(i6a, 112);
}
} else {
kplink = KLALBUtils. createKLALBPacketLink(bindAddress, socketAddress);
kplink = KLALBUtils. createKLALBPacketLink(bindAddress, socketAddress,false);
}
//startRecord();
if (klalbController != null) {
kplink.setInputTrafficCounters(new AtomicLong[] {monitor.getInTrafficAL(),klalbController.getLinkMonitor().getInTrafficAL()});
kplink.setOutputTrafficCounters(new AtomicLong[] {monitor.getOutTrafficAL(),klalbController.getLinkMonitor().getOutTrafficAL()});
kplink.setInputPacketsCounters(new AtomicLong[] {monitor.getInPacketCounterAL(),klalbController.getLinkMonitor().getInPacketCounterAL()});
kplink.setOutputPacketsCounters(new AtomicLong[] {monitor.getOutPacketCounterAL(),klalbController.getLinkMonitor().getOutPacketCounterAL()});
} else {
kplink.setInputTrafficCounters(new AtomicLong[] {monitor.getInTrafficAL()});
kplink.setOutputTrafficCounters(new AtomicLong[] {monitor.getOutTrafficAL()});
kplink.setInputPacketsCounters(new AtomicLong[] {monitor.getInPacketCounterAL()});
kplink.setOutputPacketsCounters(new AtomicLong[] {monitor.getOutPacketCounterAL()});
}
kplink.setSoTimeout(20000);
if(kplink.isStream()) {
windowPercent=1.4;
MIN_RTTVAR=50000000;
burstPercent=2.0;//1.5
//ackInterval=10000000L;
}else {
windowPercent=1.2;
MIN_RTTVAR=20000000;
burstPercent=2.0;
//ackInterval=1000000L;
}
Thread timer = ThreadTool.makeVDaemonThread("重路由计时器线程", () -> {
Thread.currentThread().setPriority(Thread.NORM_PRIORITY+1);
while((!kplink.isClosed()) && (!closed)) {
Collection<SendItem>vals= sendMap.values();
for (Iterator<SendItem> iterator = vals.iterator(); iterator.hasNext();) {
SendItem sitm = (SendItem) iterator.next();
if(System.nanoTime() -sitm.getSendtime()>RTO) {
iterator.remove();
sendmapWindowUsed.addAndGet((int) -(sitm.getPacket().getPayload().getLength()+HEADER_CALIBRATE));
//if(!kplink.isStream())
if(sitm.getPacket().isPromise()) {
IPv6Packet pktr=sitm.getPacket();
pktr.setPriority(pktr.getPriority()-1);
rerouteConsumer.accept(pktr);
}
//System.out.println("reroute");
}
}
for (Iterator<Entry<UUID, Long>> iterator = recvedUIDMap.entrySet().iterator(); iterator.hasNext();) {
Entry<UUID, Long> sendItem = (Entry<UUID, Long>) iterator.next();
if(System.nanoTime()-sendItem.getValue()>10000000000L) {
iterator.remove();
}
}
if(checkACKTime()) {
sendALLIPv6ACK();
//System.out.println("ACK发送");
}
try {
Thread.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
timer.start();
Thread t = ThreadTool.makeVDaemonThreadIfSupport("远程发送线程", () -> {
tlock = Thread.currentThread();
//tlock.setPriority(Thread.NORM_PRIORITY+1);
try {
writePacketToKPL(new ADDRREQPacket());
writePacketToKPL(new ADDRREQPacket());
writeKLALBPacketToKPL(new ADDRREQPacket());
writeKLALBPacketToKPL(new ADDRREQPacket());
if(addressGroup!=null) {
writePacketToKPL(new ADDRPacket(addressGroup));
writePacketToKPL(new ADDRPacket(addressGroup));
writeKLALBPacketToKPL(new ADDRPacket(addressGroup));
writeKLALBPacketToKPL(new ADDRPacket(addressGroup));
}
writePacketToKPL(new VADDRREQPacket());
writePacketToKPL(new VADDRREQPacket());
writePacketToKPL(new VADDRPacket(localVaddrSupplier.get()));
writePacketToKPL(new VADDRPacket(localVaddrSupplier.get()));
writeKLALBPacketToKPL(new VADDRREQPacket());
writeKLALBPacketToKPL(new VADDRREQPacket());
writeKLALBPacketToKPL(new VADDRPacket(localVaddrSupplier.get()));
writeKLALBPacketToKPL(new VADDRPacket(localVaddrSupplier.get()));
flushKPL();
KLALBPacket kpp = null;
ByteBuffer[] kpp = null;
int kppslen=0;
while ((!kplink.isClosed()) && (!closed)) {
// TimeDebugger tdb=new TimeDebugger();
// tdb.putTime("start");
if(checkBandwidthReportTime()) {
sendIPacket(new BWINFPacket(monitor.getOutSpeedAvg2(), monitor.getInSpeedAvg2()));
sendIPacket(new BWINFPacket(monitor.getOutSpeedAvg(), monitor.getInSpeedAvg()));
}
if (checkPingTimeSleep()) {
writePacketToKPL(new PINGPacket(System.nanoTime()));
writeKLALBPacketToKPL(new PINGPacket(System.nanoTime()));
if (remoteVaddr == null)
writePacketToKPL(new VADDRREQPacket());
writeKLALBPacketToKPL(new VADDRREQPacket());
if(peerAddress==null)
writePacketToKPL(new ADDRREQPacket());
writeKLALBPacketToKPL(new ADDRREQPacket());
}else {
KLALBPacket kpip = IsendDequeList.poll();
if (kpip != null) {
writePacketToKPL(kpip);
writeKLALBPacketToKPL(kpip);
}else {
// tdb.putTime("Isend");
if (kpp == null) {
do {
kpp = sendDequeList.poll();
} while (kpp != null && kpp.isDisposed());
if(kpp==null) {
ByteBuffer tkpp = sendDequeList.poll();
if(tkpp==null) {
monitor.setQueueingDelay(0);
}else {
kpp=new ByteBuffer[10];
kpp[0]=tkpp;
int i=1;
for(;i<kpp.length;i++) {
ByteBuffer xkpp=sendDequeList.poll();
if(xkpp==null)
break;
kpp[i]=xkpp;
}
kppslen=i;
}
}
// System.out.println(sendDequeList.size());
if (kpp != null) {
// TimeDebugger tdb=new TimeDebugger();
//tdb.putTime("start");
KLALBPacket kppt=kpp;
kppt.lockAll();
try {
if (kpp.isSomeDisposed()) {
kpp = null;
} else {
// if (congress.checkTransmit(length)) {
writePacketToKPL(kpp);
kplink.writePackets(kpp,0,kppslen);
if (checkPingTime()) {
writePacketToKPL(new PINGPacket(System.nanoTime()));
writeKLALBPacketToKPL(new PINGPacket(System.nanoTime()));
}
monitor.setQueueingDelay( System.nanoTime()- kpp.getJoinqueuetime());
//monitor.setQueueingDelay( System.nanoTime()- kpp.getJoinqueuetime());
/*if (kpp instanceof DATATPacket||kpp instanceof IPv6OverKLALBPacket) {
resetSleepTimer();
}*/
kpp.doDisposeAfterSend();
kpp = null;
}
//}
} finally {
kppt.unlockAll();
}
//tdb.putTime("sendToLink");
//tdb.print();
}else {
LockSupport.parkNanos(1000000);
LockSupport.parkNanos(10000000L);
}
}
}
@@ -358,6 +460,8 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
// System.out.println(sendDequeList.isEmpty());
Thread.yield();
}
}catch(StreamCorruptedException sce) {
sce.printStackTrace();
} catch (IOException | UnresolvedAddressException e) {
if (debug)
e.printStackTrace();
@@ -370,28 +474,26 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
}
});
t.start();
boolean fst = true;
AtomicBoolean fst = new AtomicBoolean(true);
long stime = 5000000000L;
while ((!kplink.isClosed()) && (!closed)) {
long readStart = System.nanoTime();
KLALBPacket kpp = readPacketFromKPL();
/*long readTime = System.nanoTime() - readStart;
readTime *= 10;
if (readTime > stime) {
stime = readTime;
} else {
stime = (stime * 999 + readTime) / 1000;
}
if (stime < 2000000000L) {
stime = 2000000000L;
}*/
// System.out.println(readTime);
ByteBuffer kppb = kplink.readPacket();
kplink.setSoTimeout(3000);
kplink.setSoTimeout((int) (stime / 1000000));
if (kpp == null) {
if (kppb == null) {
break;
}
HighPerformanceExecutor.defaultExecutor.execute(()->{
KLALBPacket kpp=null;
try {
kpp = KLALBPacket.readKLALBPacketFromChannel(KNEChannels.newReadableChannel(kppb));
} catch (IOException e) {
e.printStackTrace();
}
if(kpp==null)
return;
debugShowPacket("RX",kpp);
switch (kpp.getType()) {
case KLALBPacket.PING:
sendIPacket(new PONGPacket(((PINGPacket) kpp).getTime() ,kpp.getRcvtime(), System.nanoTime()));
@@ -404,29 +506,30 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
long DrcvDelayFactor0 = png.getRcvtime() - png.getTimepongsnd();
long DsndDelayFactor;
long DrcvDelayFactor;
adjnc.getLock().lock();
AdjustedNanoClock adjc=adjnc;
adjc.getLock().lock();
try {
adjnc.calibrate(png.getTimepongsnd() + ul / 2 - png.getRcvtime(), ul / 2);
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
adjc.calibrate(png.getTimepongsnd() + ul / 2 - png.getRcvtime(), ul / 2);
DsndDelayFactor = DsndDelayFactor0 - adjc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjc.getDelta();
if (DsndDelayFactor < 0) {
if (DrcvDelayFactor < 0) {
} else {
adjnc.setDelta(adjnc.getDelta() + DsndDelayFactor);
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
adjc.setDelta(adjc.getDelta() + DsndDelayFactor);
DsndDelayFactor = DsndDelayFactor0 - adjc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjc.getDelta();
}
} else {
if (DrcvDelayFactor < 0) {
adjnc.setDelta(adjnc.getDelta() - DrcvDelayFactor);
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
adjc.setDelta(adjc.getDelta() - DrcvDelayFactor);
DsndDelayFactor = DsndDelayFactor0 - adjc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjc.getDelta();
}
}
} finally {
adjnc.getLock().unlock();
adjc.getLock().unlock();
}
if (DsndDelayFactor >= 0 && DrcvDelayFactor >= 0) {
@@ -436,7 +539,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
//pingInterval = monitor.getLatencyAvg()+2000000L;
//double load = 1 - monitor.getOutDelayMin() / (double) monitor.getOutDelay();
loadPercent =Math.max( 1.2,0.4);
//loadPercent =Math.max( 1.3,0.4);
}
LockSupport.unpark(tlock);
@@ -446,9 +549,12 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
if (bwi.getDownSpeed() >= congressSpeed) {
congressSpeed = bwi.getDownSpeed();
} else {
congressSpeed = (congressSpeed * 999 + bwi.getDownSpeed()) / 1000;
congressSpeed = (congressSpeed * 199 + bwi.getDownSpeed()) / 200;
}
congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * loadPercent)) );
bandwidthDistributer.setTotalBandwidth (congressSpeed );
congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * burstPercent)) );
//reallimit=(int) (congress.getLimitspeed()*monitor.getLatencyMin()/1000000000L);
reallimit=(int) (Math.max(MIN_SPEED,(long) (congressSpeed*windowPercent ))*Math.max(2000000L,RTTMin)/1000000000L);
// System.out.println(congressSpeed);
break;
case KLALBPacket.ADDRREQ:
@@ -460,7 +566,13 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
if(addressGroup==null) {
byte[]ab=peerAddress.getAddress().getAddress();
ab[15]=2;
Inet6AddressGroup ardg2=new Inet6AddressGroup((Inet6Address) InetAddress.getByAddress(ab),peerAddress.getPrefixLength());
Inet6AddressGroup ardg2=null;
try {
ardg2 = new Inet6AddressGroup((Inet6Address) InetAddress.getByAddress(ab),peerAddress.getPrefixLength());
} catch (UnknownHostException e) {
e.printStackTrace();
}
if(ardg2!=null)
addressGroup=ardg2;
}
break;
@@ -475,39 +587,124 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
if (klalbController != null) {
adjnc = klalbController.getAdjustedClockByVaddr(remoteVaddr.getAddress());
}
if (fst) {
if (fst.compareAndSet(true, false)) {
// coll.resetCoolingTime();
monitor.setState(MonitorData.ONLINE);
fst = false;
}
break;
case KLALBPacket.VADDRACK:
break;
case KLALBPacket.TEST:
case KLALBPacket.TESTN:
break;
case KLALBPacket.IPV6OVERKLALB:
if(ipv6con!=null) {
IPv6OverKLALBPacket ivk=(IPv6OverKLALBPacket) kpp;
IPv6Packet iv6= ivk.getIPv6Packet();
ivk.putTimePassport("unpacked");
ivk.printPassport();
iv6.putTimePassport("unpackFromLink");
IPSequence val=null;
IPv6SegmentRoutingHeader srh= iv6.getSRHHeader();
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) {
SEQSSegmentRoutingTLV seqs=(SEQSSegmentRoutingTLV) tlv;
// if(seqs.isPromise()) {
val=new IPSequence(seqs.getUUID(),seqs.isPromise());
//}
}else if(tlv instanceof ACKSEQSSegmentRoutingTLV) {
ACKSEQSSegmentRoutingTLV aseq=(ACKSEQSSegmentRoutingTLV) tlv;
l.remove(i);
i--;
SendItem ipv6;
if((ipv6=sendMap.remove(aseq.getIPSequence()))!=null) {
sendmapWindowUsed.addAndGet((int) -(ipv6.getPacket().getPayload().getLength()+HEADER_CALIBRATE));
long RTTC=System.nanoTime()-ipv6.getSendtime();
if(RTTC<=RTTMin) {
RTTMin=RTTC;
}else {
RTTMin= (RTTMin*99999+RTTC)/100000;
}
if(firstUpdate.compareAndSet(true, false)) {
RTTAvg=RTTC;
RTTVar=RTTC/2;
}else {
RTTVar=(RTTVar*3+Math.abs(RTTAvg-RTTC))/4;
RTTAvg= (RTTAvg*7+RTTC)/8;
}
RTO=RTTAvg+Math.max(MIN_RTTVAR, RTTVar*4);//RTTVar*4
//System.out.println("remove:"+aseq.getSequence()+" "+sendMap.size());
}else {
// System.out.println("miss:"+aseq.getSequence()+" "+sendMap.size());
}
}
}
}
if(val!=null)
ackIDs.add(val);
/*if(val!=null&&peerAddress!=null) {
UUID val2=val;
HighPerformanceExecutor.defaultExecutor.execute(()->{
IPv6Packet ipv=new IPv6Packet();
ipv.setVersion(6);
ipv.setTrafficClass(0);
ipv.setFlowLabel(0);
ipv.setHopLimit(255);
ipv.setSourceAddress(addressGroup.getAddress());
ipv.setDestinationAddress(peerAddress.getAddress());
ipv.setPriority(0);
ipv.enableECN();
IPv6SegmentRoutingHeader srh2=new IPv6SegmentRoutingHeader();
srh2.getAddresses().add(peerAddress.getAddress());
srh2.getTlvs().add(new ACKSEQSSegmentRoutingTLV(val2,true));
ipv.getHeaders().add(srh2);
ipv.setPayload(new IPv6EmptyPayload());
sendIPacket(new IPv6OverKLALBPacket( ipv));
//System.out.println("ack:"+val);
});
}*/
if(ipv6con!=null) {
if(iv6.getPayload()instanceof IPv6EmptyPayload) {
//iv6.dispose();
}else {
if(val!=null) {
Long l=recvedUIDMap.putIfAbsent(val.getUuid(), System.nanoTime());
if(l==null) {
ipv6con.accept(iv6);
}else {
//System.out.println("虚假重传:"+val.getUuid());
}
}else {
ipv6con.accept(iv6);
}
}
}
break;
default:
while (rec == null) {
Thread.sleep(1);
}
if(rec!=null)
rec.accept( kpp);
break;
}
});
Thread.yield();
}
}catch(StreamCorruptedException sce) {
sce.printStackTrace();
} catch (IOException | UnresolvedAddressException e) {
if (debug)
e.printStackTrace();
} catch (InterruptedException e) {
}catch(Exception e) {
e.printStackTrace();
} finally {
monitor.setState(MonitorData.OFFLINE);
@@ -518,17 +715,14 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
} catch (IOException e) {
e.printStackTrace();
}
/*KLALBPacket pack;
while((pack=sendDequeList.poll())!=null) {
try {
if(remoteVaddr!=null) {
klalbController.sendPacketToLinkAddress(remoteVaddr, pack);
if(debug)
System.out.println("RETRY:"+pack);
}
} catch (IOException e) {
Collection<SendItem>vals= sendMap.values();
SendItem[]packs= vals.toArray(new SendItem[0]);
for (SendItem iPv6Packet : packs) {
rerouteConsumer.accept(iPv6Packet.getPacket());
//System.out.println("重路由:"+iPv6Packet);
}
}*/
sendMap.clear();
sendmapWindowUsed.set(0);
}
if (closed) {
@@ -544,63 +738,98 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
}).start();
}
private ConcurrentLinkedQueue<IPSequence> ackIDs=new ConcurrentLinkedQueue<>();
private volatile long prevAckTime=System.nanoTime();
private volatile long ackInterval=1000000L;
private boolean checkACKTime() {
long cu = System.nanoTime();
if (cu - prevAckTime > ackInterval) {
prevAckTime = cu;
return true;
} else {
return false;
}
}
private void sendALLIPv6ACK() {
if(peerAddress!=null) {
while(true) {
int rez=sendIPv6ACK();
if(rez<=0)
break;
}
}
}
private int sendIPv6ACK() {
IPv6SegmentRoutingHeader srh2=new IPv6SegmentRoutingHeader();
int adds=addACKSEQToSRH(srh2,40);
if(adds<=0)
return adds;
//System.out.println(adds+"ACKS");
IPv6Packet ipv=new IPv6Packet();
ipv.setVersion(6);
ipv.setTrafficClass(0);
ipv.setFlowLabel(0);
ipv.setHopLimit(255);
ipv.setSourceAddress(addressGroup.getAddress());
ipv.setDestinationAddress(peerAddress.getAddress());
ipv.setPriority(0);
ipv.enableECN();
srh2.getAddresses().add(peerAddress.getAddress());
ipv.getHeaders().add(srh2);
ipv.setPayload(new IPv6EmptyPayload());
sendIPacket(new IPv6OverKLALBPacket( ipv));
//System.out.println("ack:"+val);
return adds;
}
private int addACKSEQToSRH(IPv6SegmentRoutingHeader srh,int maxAckCount){
int i = 0;
for (; i < maxAckCount; i++) {
IPSequence ackid= ackIDs.poll();
if(ackid!=null) {
srh.getTlvs().add(new ACKSEQSSegmentRoutingTLV(ackid, ackid.isPromise()));
}else {
prevAckTime=System.nanoTime();
return i;
}
}
return i;
}
private void flushKPL() throws IOException {
kplink.flush();
}
private KLALBPacket readPacketFromKPL() throws IOException {
KLALBPacket packet = kplink.readPacket();
if (showpacket) {
if (!(packet instanceof PINGPacket))
if (!(packet instanceof PONGPacket))
if (!(packet instanceof BWINFPacket))
System.out.println("RX:" + packet);
}
private KLALBPacket readKLALBPacketFromKPL() throws IOException {
KLALBPacket packet = kplink.readKLALBPacket();
debugShowPacket("RX",packet);
if (packet != null) {
packet.putTimePassport("received");
long length=packet.getLength();
monitor.getInTrafficAL().addAndGet(length);
monitor.getInPacketCounterAL().incrementAndGet();
if (klalbController != null)
klalbController.getLinkMonitor().getInTrafficAL().addAndGet(length);
klalbController.getLinkMonitor().getInPacketCounterAL().incrementAndGet();
}
return packet;
}
private void writePacketToKPL(KLALBPacket packet) throws IOException {
long length=packet.getLength();
monitor.getOutTrafficAL().addAndGet(length);
monitor.getOutPacketCounterAL().incrementAndGet();
if (klalbController != null)
klalbController.getLinkMonitor().getOutTrafficAL().addAndGet(length);
klalbController.getLinkMonitor().getOutPacketCounterAL().incrementAndGet();
kplink.writePacket(packet);
private void writeKLALBPacketToKPL(KLALBPacket packet) throws IOException {
kplink.writeKLALBPacket(packet);
packet.putTimePassport("sended");
packet.printPassport();
if (showpacket) {
if (!(packet instanceof PINGPacket))
if (!(packet instanceof PONGPacket))
if (!(packet instanceof BWINFPacket))
System.err.println("TX:" + packet);
}
debugShowPacket("TX",packet);
}
private void writePacketToKPL(KLALBPacket packet,long length) throws IOException {
monitor.getOutTrafficAL().addAndGet(length);
monitor.getOutPacketCounterAL().incrementAndGet();
if (klalbController != null)
klalbController.getLinkMonitor().getOutTrafficAL().addAndGet(length);
klalbController.getLinkMonitor().getOutPacketCounterAL().incrementAndGet();
kplink.writePacket(packet);
private void debugShowPacket(String label, KLALBPacket packet) {
if (showpacket) {
if (!(packet instanceof PINGPacket))
if (!(packet instanceof PONGPacket))
if (!(packet instanceof BWINFPacket))
System.err.println("TX:" + packet);
System.err.println(label+":" + packet);
}
}
@@ -622,7 +851,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
private volatile long time = System.nanoTime();
private volatile long pingInterval = 10000000L;
private volatile long pingIntervalSleep = 200000000L;
private volatile long pingIntervalSleep = 500000000L;
private boolean checkPingTime() {
long cu = System.nanoTime();
@@ -649,7 +878,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
private volatile long bwtime = System.nanoTime();
private volatile long bwpingInterval = 10000000L;
private volatile long bwpingIntervalSleep = 100000000L;
private volatile long bwpingIntervalSleep = 200000000L;
private boolean checkBandwidthReportTime(){
long cu = System.nanoTime();
if (cu - bwtime > bwpingIntervalSleep) {
@@ -667,16 +896,25 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
private ConcurrentLinkedQueue<KLALBPacket> IsendDequeList = new ConcurrentLinkedQueue<KLALBPacket>();
private PriorityBlockingQueue<KLALBPacket> sendDequeList = new PriorityBlockingQueue<KLALBPacket>();
private PriorityBlockingQueue<ByteBuffer> sendDequeList = new PriorityBlockingQueue<ByteBuffer>();
public PriorityBlockingQueue<KLALBPacket> getQueue() {
public PriorityBlockingQueue<ByteBuffer> getQueue() {
return sendDequeList;
}
protected void sendPacket(KLALBPacket blk) {
debugShowPacket("TX",blk);
blk.markJoinqueuetime();
sendDequeList.add(blk);
ByteBuffer buf=NetworkPacket.bufferAllocator.allocate((int) blk.getLength());
try {
KLALBPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel(buf), blk);
buf.flip();
sendDequeList.add(buf);
LockSupport.unpark(tlock);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
private void sendIPacket(KLALBPacket blk) {
@@ -688,21 +926,8 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
this.rec = rec;
}
/*public void remoeFromSendQueue(KLALBPacket klalbPacket) {
sendDequeList.remove(klalbPacket);
}*/
public long statLengthBefore(long l) {
AtomicLong al = new AtomicLong();
for (Iterator<KLALBPacket> iterator = sendDequeList.iterator(); iterator.hasNext();) {
KLALBPacket queue = iterator.next();
if (queue.getPriority() <= l) {
al.addAndGet(queue.getLength());
}
}
return al.get();
}
private volatile long predictTime;
@@ -744,7 +969,7 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
}
}
private static final TESTPacket testPacket = new TESTPacket(60000);
private static final TESTNPacket testPacket = new TESTNPacket(60000);
private volatile boolean pressure = false;
private SpeedLimiter pressureSpeed = new SpeedLimiter(32768);
@@ -774,46 +999,21 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
return predictTime;
}
private List<Double>ranks=new ArrayList<Double>();
private Consumer<IPv6Packet> ipv6con;
@Override
public void noticeRank(int rank) {
while(rank>=ranks.size()) {
ranks.add(0.5);
}
for (int i = 0; i < ranks.size(); i++) {
if(i==rank) {
ranks.set(i, (ranks.get(i)*99.0+1.0D)/100.0);
}else {
ranks.set(i, ranks.get(i)*99.0/100.0);
}
}
}
@Override
public double getWeightAtRank(int rank) {
while(rank>=ranks.size()) {
ranks.add(0.5);
}
return ranks.get(rank);
}
public List<Double> getRanks() {
return ranks;
}
@Override
public boolean isLoopBack() {
return false;
}
private BandwidthDistributer<Inet6Address> bandwidthDistributer=new BandwidthDistributer<Inet6Address>();
@Override
public List<Neighbor> getNeighborsInfo() {
List<Neighbor>hs=new ArrayList<>();
if(peerAddress!=null) {
hs.add(new Neighbor(peerAddress, remoteVaddr, monitor));
hs.add(new Neighbor(peerAddress, remoteVaddr, monitor,bandwidthDistributer));
//System.out.println(peerAddress+" "+addressGroup);
}
return hs;
@@ -821,26 +1021,77 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
private Map<IPSequence,SendItem> sendMap= new ConcurrentHashMap<>();
private AtomicInteger sendmapWindowUsed=new AtomicInteger(0);
private Map<UUID,Long>recvedUIDMap=new ConcurrentHashMap<UUID, Long>();
private volatile int inputchachesize = 8192 * 4000;
private volatile int outputchachesize = 8192 * 240;//500
private volatile int reallimit = 65536 ;
private Consumer<IPv6Packet> rerouteConsumer;
@Override
public void sendPacket(IPv6Packet pack, Inet6Address inet6Address) throws IOException {
pack.lockAll();
try {
if(pack.isSomeDisposed()) {
return;
//只有已连接的链路才能传输数据
if(monitor.getState()==MonitorData.ONLINE) {
//if(inet6Address.equals(remoteVaddr.getAddress())||inet6Address.equals(peerAddress.getAddress())) {
//获得数据包的SRv6扩展头部
IPv6SegmentRoutingHeader srh= pack.getSRHHeader();
IPSequence val=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) {
SEQSSegmentRoutingTLV seqs=(SEQSSegmentRoutingTLV) tlv;
//if(seqs.isPromise())
//获得数据包的序号
val=new IPSequence(seqs.getUUID(),seqs.isPromise());
break;
}
}
if(val!=null) {
//放入滑动窗口中并记录缓冲区大小占用
SendItem old= sendMap.put(val,new SendItem( pack));
if(old!=null) {
sendmapWindowUsed.addAndGet((int) -(old.getPacket().getPayload().getLength()+HEADER_CALIBRATE));
}
sendmapWindowUsed.addAndGet((int) (pack.getPayload().getLength()+HEADER_CALIBRATE));
//System.out.println("add: "+ val+" "+sendMap.size());
}
}
//捎带发送反方向的ACK给对方发送过来的数据包,减小设备性能开销
if(srh!=null) {
addACKSEQToSRH(srh,10);
}
//发送数据包
sendIPv6PacketToLink(pack);
//}
}else {
if(rerouteConsumer!=null) {
rerouteConsumer.accept(pack);
}
}
if(inet6Address.equals(remoteVaddr.getAddress())||inet6Address.equals(peerAddress.getAddress())) {
}
@Override
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
this.rerouteConsumer=rerouteConsumer;
}
private void sendIPv6PacketToLink(IPv6Packet pack) {
IPv6OverKLALBPacket kipv6=new IPv6OverKLALBPacket(pack);
kipv6.setPriority(pack.getPriority());
kipv6.setDisposeAfterSend(true);
pack.putTimePassport("packdInLink");
pack.printPassport();
sendPacketToLink(kipv6);
}
}finally {
pack.unlockAll();
}
}
private void sendPacketToLink(KLALBPacket packet) {
@@ -850,13 +1101,18 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
}
@Override
public boolean isCongress(IPv6Packet iPv6Packet) {
int size=getQueue().size();
if(size>30) {
public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
if(monitor.getInDelay()>3000000000L||monitor.getOutDelay()>3000000000L||monitor.getInSpeedAvg()<=0||monitor.getOutSpeedAvg()<=0)
return true;
}else {
return !congress.checkTransmit(iPv6Packet.getLength());
}
boolean congress=sendmapWindowUsed.get()>reallimit*scale;
return congress;
}
@Override
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
boolean xcongress=!congress.checkTransmit(iPv6Packet.getLength());
return xcongress;
}
@Override
@@ -879,6 +1135,30 @@ public class KLALBRemoteLine implements IPv6NetworkLink,Comparable<KLALBRemoteL
this.ipv6con=ipv6con;
}
@Override
public List<RouteItem> getRouteItems() {
List<RouteItem> rlist=new ArrayList<>();
Inet6AddressGroup adg=addressGroup;
if(adg!=null)
rlist.add(new RouteItem(new Inet6AddressGroup(adg.getAddress(), 128),
adg.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), 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);
}
return rlist;
}
}
+143 -3
View File
@@ -10,6 +10,8 @@ import java.net.UnknownHostException;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.kne.cloud.network.MultipurposeSocketAddress;
@@ -135,8 +137,28 @@ public class KLALBUtils {
Color col=new Color( r,g,0);
return col;
}
public static Color getColorByLoadPercentagex(float f) {
int r=0;
int g=200;
if(f<50f) {
r+=f/50f*200f;
}else {
r=200;
g-=(f-50f)/50f*200f;
}
if(r>200)
r=200;
if(r<0)
r=0;
if(g>200)
g=200;
if(g<0)
g=0;
Color col=new Color( r,g,0);
return col;
}
public static KLALBPacketLink createKLALBPacketLink(MultipurposeSocketAddress bindAddress, MultipurposeSocketAddress targetAddress)
public static KLALBPacketLink createKLALBPacketLink(MultipurposeSocketAddress bindAddress, MultipurposeSocketAddress targetAddress,boolean buffered)
throws IOException {
if (targetAddress.isStream()) {
if (targetAddress.supportNIO()) {
@@ -164,14 +186,23 @@ public class KLALBUtils {
}
}
public static KLALBPacketLink createKLALBPacketLink(MultipurposeSocketAddress bindAddress,
MultipurposeSocketAddress targetAddress, int timeout) throws UnknownHostException, IOException {
MultipurposeSocketAddress targetAddress,boolean buffered, int timeout) throws UnknownHostException, IOException {
if (targetAddress.isStream()) {
if (targetAddress.supportNIO()) {
if (bindAddress != null) {
if(buffered) {
return new StreamChannelKLALBPacketLink(targetAddress
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout));
}else {
return new StreamChannelKLALBPacketLink(targetAddress
.connectSocketChannel(InetAddress.getByName(bindAddress.getHost()), bindAddress.getPort(),timeout));
}
} else {
if(buffered) {
return new StreamChannelKLALBPacketLink(targetAddress.connectSocketChannel(timeout));
}else {
return new StreamChannelKLALBPacketLink(targetAddress.connectSocketChannel(timeout));
}
}
} else {
if (bindAddress != null) {
@@ -190,7 +221,116 @@ public class KLALBUtils {
}
}
}
public static final String IPv6Reg = "([\\da-fA-F]{1,4}:){7}[\\da-fA-F]{1,4}$"
+ "|^:((:[\\da-fA-F]{1,4}){1,6}|:)$"
+ "|^[\\da-fA-F]{1,4}:((:[\\da-fA-F]{1,4}){1,5}|:)$"
+ "|^([\\da-fA-F]{1,4}:){2}((:[\\da-fA-F]{1,4}){1,4}|:)$"
+ "|^([\\da-fA-F]{1,4}:){3}((:[\\da-fA-F]{1,4}){1,3}|:)$"
+ "|^([\\da-fA-F]{1,4}:){4}((:[\\da-fA-F]{1,4}){1,2}|:)$"
+ "|^([\\da-fA-F]{1,4}:){5}:([\\da-fA-F]{1,4})?$"
+ "|^([\\da-fA-F]{1,4}:){6}:"; // IPv6地址的格式
/**
* 将一个IPv6地址转为全写格式,全写中的前导0省略
* 例:将1ade:03da:0::转为1ade:3da:0:0:0:0:0:0
*
* @param IPv6Str
* @return fullIPv6
*/
public static String parseFullIPv6(String IPv6Str) {
// 判断IPv6地址的格式是否正确
if (!IPv6Str.matches(IPv6Reg)) {
return "";
}
String[] arr = new String[]{"0", "0", "0", "0", "0", "0", "0", "0"};
// 将IPv6地址用::分开
// 如果IPv6地址为::tempArr.length==0
// 如果不包含::或以::结尾,tempArr.length==1
// 如果以::开头或::在中间,tempArr.length==2
String[] tempArr = IPv6Str.split("::");
// tempArr[0]用:分开,填充到arr前半部分
if (tempArr.length > 0) {
// new String[0]为空数组,因为"".split(":")为{""},如果tempArr[0]=="",此时数组包含一个元素
String[] tempArr0 = tempArr[0].isEmpty() ? new String[0] : tempArr[0].split(":");
for (int i = 0; i < tempArr0.length; i++) {
// 如果是纯数字,用parseInt去除前导0,如果包含字母,用正则去除前导0
arr[i] = tempArr0[i].matches("\\d+")
? (Integer.parseInt(tempArr0[i]) + "")
: tempArr0[i].replaceAll("^(0+)", "");
}
}
// tempArr[1]用:分开,填充到arr后半部分
if (tempArr.length > 1) {
String[] tempArr1 = tempArr[1].isEmpty() ? new String[0] : tempArr[1].split(":");
for (int i = 0; i < tempArr1.length; i++) {
arr[i + arr.length - tempArr1.length] = tempArr1[i].matches("\\d+")
? (Integer.parseInt(tempArr1[i]) + "")
: tempArr1[i].replaceAll("^(0+)", "");
}
}
return join(arr, ":");
}
private static String join(String[] arr, String string) {
StringBuilder sb=new StringBuilder();
for (int i = 0; i < arr.length; i++) {
sb.append(arr[i]);
if(i+1<arr.length) {
sb.append(string);
}
}
return sb.toString();
}
/**
* 将一个IPv6地址转为简写格式
* 例:将1ade:03da:0::转为1ade:3da::
*
* @param IPv6Str
* @return AbbrIPv6
*/
public static String parseAbbrIPv6(String IPv6Str) {
// 将一个IPv6地址转为全写格式,全写中的前导0省略
String fullIPv6 = parseFullIPv6(IPv6Str);
if (fullIPv6.isEmpty()) { // 如果IPv6地址的格式不正确
return "";
}
// 将1ade:3da:0:0:0:0:0:99转为{"-","-","0","0","0","0","0","-"}
String[] arr = fullIPv6.split(":");
for (int i = 0, len = arr.length; i < len; i++) {
if (!"0".equals(arr[i])) {
arr[i] = "-";
}
}
// 找到最长的连续的0
Pattern pattern = Pattern.compile("0{2,}");
Matcher matcher = pattern.matcher(join(arr, ""));
String maxStr = "";
int start = -1;
int end = -1;
while (matcher.find()) {
if (maxStr.length() < matcher.group().length()) {
maxStr = matcher.group();
start = matcher.start();
end = matcher.end();
}
}
// 合并
arr = fullIPv6.split(":");
if (maxStr.length() > 0) {
for (int i = start; i < end; i++) {
arr[i] = ":";
}
}
return join(arr, ":").replaceAll(":{2,}", "::");
}
}
@@ -0,0 +1,24 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.SocketException;
import org.kne.cloud.network.RawSocket;
import org.kne.cloud.network.RawSocketImpl;
import org.kne.cloud.network.VirtualRawSocket;
import org.kne.cloud.network.srv6.SRv6Router;
public class KLALBVirtualRawSocket extends VirtualRawSocket {
public KLALBVirtualRawSocket(SRv6Router controller) {
super(new KLALBVirtualRawSocketImpl(controller));
}
public KLALBVirtualRawSocket(SRv6Router controller,Inet6Address bindAddress) throws SocketException {
super(new KLALBVirtualRawSocketImpl(controller),bindAddress);
}
public KLALBVirtualRawSocket(SRv6Router controller,Inet6Address bindAddress,int bindProtocol) throws SocketException {
super(new KLALBVirtualRawSocketImpl(controller),bindAddress,bindProtocol);
}
}
@@ -0,0 +1,272 @@
package org.kne.cloud.network.klalb;
import java.io.IOException;
import java.net.BindException;
import java.net.DatagramPacket;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import org.kne.cloud.network.ByteBufferAllocator;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.RawSocketImpl;
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.srv6.PacketConsumer;
import org.kne.cloud.network.srv6.SRv6Router;
import org.kne.concurrent.HighPerformanceExecutor;
import org.kne.io.KNEChannels;
public class KLALBVirtualRawSocketImpl extends VirtualRawSocketImpl implements PacketConsumer{
private boolean ipHeaderInclude=false;
private SRv6Router router;
protected volatile Inet6Address remoteaddr;
protected volatile Inet6Address localaddr;
private int bindProtocolNumber;
private volatile int inputchachesize = 1024*1024;
protected SRv6Router getRouter() {
return router;
}
public KLALBVirtualRawSocketImpl(SRv6Router router) {
super();
this.router = router;
}
@Override
public void setOption(int optID, Object value) throws SocketException {
// TODO 自动生成的方法存根
}
@Override
public Object getOption(int optID) throws SocketException {
// TODO 自动生成的方法存根
return null;
}
@Override
protected void create() throws IOException {
}
@Override
protected void setIPHeaderInclude(boolean ipHeaderInclude) throws IOException {
this.ipHeaderInclude=ipHeaderInclude;
}
@Override
protected boolean getIPHeaderInclude() throws IOException {
return ipHeaderInclude;
}
@Override
protected void setUseSelectTimeout(boolean useSelect) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected boolean getUseSelectTimeout() throws IOException {
// TODO 自动生成的方法存根
return false;
}
@Override
protected void setSendTimeout(int timeout) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected int getSendTimeout() throws IOException {
// TODO 自动生成的方法存根
return 0;
}
@Override
protected void setReceiveTimeout(int timeout) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected int getReceiveTimeout() throws IOException {
// TODO 自动生成的方法存根
return 0;
}
@Override
protected void close() {
router.getProtocolNumberRegister().remove(bindProtocolNumber);
}
@Override
protected void bind(InetAddress address,int protocolNumber) throws SocketException{
if(protocolNumber<0) {
throw new UnsupportedOperationException("unsupprted bind all protocols");
}
try {
if (address.equals(Inet4Address.getByName("0.0.0.0"))) {
address = Inet6Address.getByName("::0");
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
if (!(address instanceof Inet6Address)) {
throw new IllegalArgumentException("invalid address type, KLALB socket can only use IPV6 address");
}
if ((!address.isAnyLocalAddress()) && (!address.equals(router.getLocator().getAddress()))) {
throw new BindException("must bind to self");
}
localaddr=(Inet6Address) address;
this.bindProtocolNumber=protocolNumber;
if(router.getProtocolNumberRegister().putIfAbsent(protocolNumber, this)!=null) {
throw new BindException("protocol number already bind");
}
}
@Override
protected void join(InetAddress inetaddr) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void leave(InetAddress inetaddr) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void joinGroup(InetAddress mcastaddr, NetworkInterface netIf) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void leaveGroup(InetAddress mcastaddr, NetworkInterface netIf) throws IOException {
// TODO 自动生成的方法存根
}
@Override
protected void send(DatagramPacket p) throws IOException {
ByteBuffer buf= ByteBuffer.wrap(p.getData(), p.getOffset(), p.getLength());
if(ipHeaderInclude) {
}else {
HighPerformanceExecutor.defaultExecutor.execute(() -> {
IPv6Packet ipv=new IPv6Packet();
ipv.setVersion(6);
ipv.setTrafficClass(0);
ipv.setFlowLabel(0);
ipv.setHopLimit(255);
ipv.setSourceAddress(router.getLocator().getAddress());
InetAddress address= p.getAddress();
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.enableECN();
IPv6Payload pl=new IPv6Payload(bindProtocolNumber);
pl.getData().put(buf);
pl.getData().flip();
ipv.setPayload(pl);
router.insertSRHandRoutePacket(ipv);
});
}
}
@Override
protected InetAddress peek() throws IOException {
return peekNextPacket().getSourceAddress();
}
@Override
protected void peekData(DatagramPacket p) throws IOException {
IPv6Packet pack=peekNextPacket();
copyTo(pack, p);
}
private void copyTo(IPv6Packet pack, DatagramPacket p) throws IOException {
p.setAddress(pack.getSourceAddress());
ByteBuffer buffer= ByteBuffer.wrap(p.getData(),p.getOffset(),p.getLength());
if(ipHeaderInclude) {
}else {
try {
pack.getPayload().writeToChannel(KNEChannels.newWritableChannel(buffer));
}catch(BufferOverflowException e) {
}
}
buffer.flip();
p.setLength(buffer.limit());
}
@Override
protected void receive(DatagramPacket p) throws IOException {
IPv6Packet pack=pollNextPacket();
copyTo(pack, p);
}
private volatile Thread parkThread;
private IPv6Packet peekNextPacket() {
IPv6Packet pol=null;
while(true) {
pol=recvQueue.peek();
if(pol!=null) {
recvQueueUsed.addAndGet((int) -pol.getPayload().getLength());
return pol;
}
parkThread=Thread.currentThread();
LockSupport.parkNanos(1000000L);
}
}
private IPv6Packet pollNextPacket() {
IPv6Packet pol=null;
while(true) {
pol=recvQueue.poll();
if(pol!=null) {
recvQueueUsed.addAndGet((int) -pol.getPayload().getLength());
return pol;
}
parkThread=Thread.currentThread();
LockSupport.parkNanos(1000000L);
}
}
private Queue<IPv6Packet> recvQueue = new ConcurrentLinkedQueue<IPv6Packet>();
private AtomicInteger recvQueueUsed=new AtomicInteger(0);
@Override
public void accept(IPv6Packet packx) throws IOException {
if(recvQueueUsed.get()<=inputchachesize) {
if(recvQueue.offer(packx)) {
recvQueueUsed.addAndGet((int) packx.getPayload().getLength());
LockSupport.unpark(parkThread);
}
}
}
}
@@ -14,16 +14,16 @@ public class KLALBVirtualSocket extends VirtualSocket {
return (KLALBVirtualSocketImpl) super.getVirtualImpl();
}
private KLALBController controler;
private KLALBController controller;
protected SocketChannel channel;
public KLALBVirtualSocket(KLALBController controler) throws SocketException {
super(controler.createVirtualImpl());
this.controler = controler;
this.controller = controler;
}
protected KLALBController getControler() {
return controler;
protected KLALBController getController() {
return controller;
}
public KLALBVirtualSocket(KLALBController controler,String host, int port) throws UnknownHostException, IOException {
@@ -115,8 +115,7 @@ public class KLALBVirtualSocketChannel extends SocketChannel{
@Override
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
// TODO 自动生成的方法存根
return 0;
return ((KVSIInputStream)socket.getInputStream()).read(dsts,offset,length);
}
@Override
@@ -126,8 +125,7 @@ public class KLALBVirtualSocketChannel extends SocketChannel{
@Override
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
// TODO 自动生成的方法存根
return 0;
return ((KVSIOutputStream)socket.getOutputStream()).write(srcs,offset,length);
}
@Override
@@ -151,4 +149,10 @@ public class KLALBVirtualSocketChannel extends SocketChannel{
socket.associateSocketChannel(b);
}
public boolean isAutoFlush() throws IOException {
return ((KVSIOutputStream)socket.getOutputStream()).isAutoFlush();
}
public void setAutoFlush(boolean b) throws IOException {
((KVSIOutputStream)socket.getOutputStream()).setAutoFlush(b);
}
}
File diff suppressed because it is too large Load Diff
@@ -34,11 +34,11 @@ public class PortBinder {
this.controller = controller;
}
private ReentrantReadWriteLock bindMaplock=new ReentrantReadWriteLock();
private Map<InetSocketAddress,BindableKLALBPacketConsumer>bindMap=new ConcurrentHashMap<>();
private Map<InetSocketAddress,BindableKLALBPacketConsumer>bindMap=new ConcurrentHashMap<>(65536*16);
private ReentrantReadWriteLock listenMaplock=new ReentrantReadWriteLock();
private Map<InetSocketAddress,BindableKLALBPacketConsumer>listenMap=new ConcurrentHashMap<>();
private Map<InetSocketAddress,BindableKLALBPacketConsumer>listenMap=new ConcurrentHashMap<>(65536*16);
private ReentrantReadWriteLock connectMaplock=new ReentrantReadWriteLock();
private Map<Pair<InetSocketAddress,InetSocketAddress>,BindableKLALBPacketConsumer>connectMap=new ConcurrentHashMap<>();
private Map<Pair<InetSocketAddress,InetSocketAddress>,BindableKLALBPacketConsumer>connectMap=new ConcurrentHashMap<>(65536*16);
private volatile int portn=65535;
public void bind(BindableKLALBPacketConsumer ks) throws BindException {
bindMaplock.writeLock().lock();
@@ -205,7 +205,7 @@ public class PortBinder {
return b;
}*/
public boolean distributePacketToConsumer(Inet6Address srcAddr,PortPacket packet) {
InetSocketAddress local=new InetSocketAddress(controller.getSelf(), packet.getDport());
InetSocketAddress local=new InetSocketAddress(controller.getSelf().getAddress(), packet.getDport());
InetSocketAddress remote=new InetSocketAddress(srcAddr, packet.getSport());
BindableKLALBPacketConsumer bkc=connectMap.get(new Pair<InetSocketAddress, InetSocketAddress>(local, remote));
if(bkc!=null) {
@@ -0,0 +1,22 @@
package org.kne.cloud.network.klalb;
import org.kne.cloud.network.ipv6.IPv6Packet;
public class SendItem {
private IPv6Packet packet;
private long sendtime=System.nanoTime();
public SendItem(IPv6Packet packet) {
this.packet=packet;
}
public IPv6Packet getPacket() {
return packet;
}
public long getSendtime() {
return sendtime;
}
}
@@ -129,18 +129,20 @@ import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.DatagramServerSocket;
import org.kne.cloud.network.DatagramServerSocket.SubDatagramSocket;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.PacketRebuilder;
import org.kne.cloud.network.PacketSpliter;
import org.kne.cloud.network.SpeedLimiter;
import org.kne.debug.TimeDebugger;
public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink {
private PacketSpliter pslr=new PacketSpliter(65535);
private PacketRebuilder pbdr=new PacketRebuilder(1000000000);
public class SplitedDatagramKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
private PacketSpliter pslr;
private PacketRebuilder pbdr;
@Override
public String toString() {
@@ -151,13 +153,60 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink {
public SplitedDatagramKLALBPacketLink(DatagramSocket connectDatagramSocket) throws IOException {
this.ds=connectDatagramSocket;
bibf.limit(0);
pslr=new PacketSpliter(new WritableByteChannel() {
@Override
public boolean isOpen() {
return !ds.isClosed();
}
@Override
public void close() throws IOException {
}
@Override
public int write(ByteBuffer src) throws IOException {
int rem=src.remaining();
byte[]bt=src.array();
DatagramPacket dp=new DatagramPacket(bt,src.position(),src.limit());
//System.out.println("SendDatagram:"+src.remaining());
ds.send(dp);
return rem;
}
},1350);
pbdr=new PacketRebuilder(new ReadableByteChannel() {
@Override
public boolean isOpen() {
return !ds.isClosed();
}
@Override
public void close() throws IOException {
}
@Override
public int read(ByteBuffer dst) throws IOException {DatagramPacket dp;
if(ds instanceof SubDatagramSocket) {
dp=((SubDatagramSocket) ds).receive();
dst.put(dp.getData(), 0, dp.getLength());
}else {
dp=new DatagramPacket(bc, bc.length);
ds.receive(dp);
dst.put(dp.getData(), 0, dp.getLength());
}
//System.out.println("RecvDatagram:"+dp.getLength());
return dp.getLength();
}
},1000000000);
}
private ByteBuffer bbf=ByteBuffer.allocate(65535);
//private ByteBuffer bbf=ByteBuffer.allocate(65535);
@Override
public void writePacket(KLALBPacket kp) throws IOException {
/*@Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
//System.out.println(" TX:"+kp);
//KLALBPacket.writeKLALBPacketToStream(dos, kp);
KLALBPacket.writeKLALBPacketToChannel(new WritableByteChannel() {
@@ -184,47 +233,21 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink {
}
}, kp);
}
}*/
private byte[]bc=new byte[65535];
private ByteBuffer bibf=ByteBuffer.allocate(65535);
//private ByteBuffer bibf=ByteBuffer.allocate(65535);
@Override
public KLALBPacket readPacket() throws IOException {
/*@Override
public KLALBPacket readKLALBPacket() throws IOException {
KLALBPacket kp=null;
do {
if(bibf.remaining()<=0) {
bibf.clear();
/*DatagramPacket dp=new DatagramPacket(bc, bc.length);
ds.receive(dp);
bibf.put(dp.getData(), 0, dp.getLength());*/
pbdr.read(bibf,new ReadableByteChannel() {
@Override
public boolean isOpen() {
return true;
}
@Override
public void close() throws IOException {
}
@Override
public int read(ByteBuffer dst) throws IOException {DatagramPacket dp;
if(ds instanceof SubDatagramSocket) {
dp=((SubDatagramSocket) ds).receive();
dst.put(dp.getData(), 0, dp.getLength());
}else {
dp=new DatagramPacket(bc, bc.length);
ds.receive(dp);
dst.put(dp.getData(), 0, dp.getLength());
}
return dp.getLength();
}
} );
pbdr.read(bibf );
bibf.flip();
}
@@ -259,7 +282,7 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink {
}while(true);
return kp;
}
*/
@Override
public void close() throws IOException {
ds.close();
@@ -280,7 +303,7 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink {
return ds.getSoTimeout();
}
@Override
/*@Override
public void flush() throws IOException {
bbf.flip();
//TimeDebugger tdb=new TimeDebugger();
@@ -307,16 +330,34 @@ public class SplitedDatagramKLALBPacketLink implements KLALBPacketLink {
});
//tdb.putTime("flushEnd");
//tdb.print();
/*byte[]bt=bbf.array();
DatagramPacket dp=new DatagramPacket(bt,bbf.limit());
ds.send(dp);*/
bbf.clear();
}
}*/
@Override
public boolean isStream() {
return false;
}
@Override
public void writePacket(ByteBuffer kp) throws IOException {
incOutput(kp.remaining());
pslr.write(kp);
}
@Override
public ByteBuffer readPacket() throws IOException {
ByteBuffer bbf=NetworkPacket.bufferAllocator.allocate(65535);
pbdr.read(bbf );
bbf.flip();
incInput(bbf.remaining());
return bbf;
}
@Override
public void flush() throws IOException {
// TODO 自动生成的方法存根
}
}
@@ -1,6 +1,7 @@
package org.kne.cloud.network.klalb;
import java.io.BufferedOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
@@ -19,14 +20,19 @@ import java.nio.channels.Channels;
import java.nio.channels.SocketChannel;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicLong;
import org.kne.cloud.network.ByteBufferAllocator;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ThreadTool;
import org.kne.cloud.network.TimeoutTimer;
import org.kne.io.KNEChannels;
public class StreamChannelKLALBPacketLink implements KLALBPacketLink {
public class StreamChannelKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
private volatile long timeoutTimer;
private volatile boolean timerenabled=false;
private Thread timeouter=new Thread() {
private Runnable timeouter=new Runnable() {
public void run() {
timeoutTimer=System.nanoTime();
while(connectSocket.isOpen()) {
@@ -38,7 +44,7 @@ public class StreamChannelKLALBPacketLink implements KLALBPacketLink {
}
}
try {
Thread.sleep(1);
Thread.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -59,29 +65,13 @@ public class StreamChannelKLALBPacketLink implements KLALBPacketLink {
public StreamChannelKLALBPacketLink(SocketChannel connectSocket) throws IOException {
this.connectSocket=connectSocket;
connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true);
timeouter.start();
ThreadTool.makeVDaemonThread("连接超时计时线程", timeouter);
new KLALBOutputStream(Channels.newOutputStream(connectSocket));
new KLALBInputStream(Channels.newInputStream(connectSocket));
}
@Override
public void writePacket(KLALBPacket kp) throws IOException {
KLALBPacket.writeKLALBPacketToChannel(connectSocket, kp);
}
@Override
public KLALBPacket readPacket() throws IOException {
timeoutTimer=System.nanoTime();
timerenabled=true;
KLALBPacket res;
try {
res=KLALBPacket.readKLALBPacketFromChannel(connectSocket);
}finally {
timerenabled=false;
}
return res;
}
@Override
public void close() throws IOException {
@@ -113,5 +103,136 @@ public class StreamChannelKLALBPacketLink implements KLALBPacketLink {
public boolean isStream() {
return true;
}
@Override
public void writePacket(ByteBuffer kp) throws IOException {
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
szeWrite.limit(4);
//szeWrite.clear();
incOutput(kp.limit());
szeWrite.putInt(kp.limit());
szeWrite.flip();
KLALBVirtualSocketChannel obj = null;
connectSocket.write(new ByteBuffer[] {szeWrite,kp});
/*
if(connectSocket instanceof KLALBVirtualSocketChannel) {
obj=(KLALBVirtualSocketChannel) connectSocket;
}
boolean isaflush=false;
if(obj!=null) {
isaflush=obj.isAutoFlush();
obj.setAutoFlush(false);
}
//connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,false);
connectSocket.write(szeWrite);
//connectSocket.setOption(StandardSocketOptions.TCP_NODELAY,true);
if(obj!=null) {
obj.setAutoFlush(true);
}
connectSocket.write(kp);
if(obj!=null) {
obj.setAutoFlush(isaflush);
}*/
}
@Override
public void writePackets(ByteBuffer[] kpp,int off,int len) throws IOException {
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*2]=szeWrite;
bbfw[i*2+1]=kpp[i];
}
connectSocket.write(bbfw);
}
@Override
public ByteBuffer readPacket() throws IOException {
timeoutTimer=System.nanoTime();
timerenabled=true;
ByteBuffer kp;
ByteBuffer szeRead=NetworkPacket.bufferAllocator.allocate(4);
szeRead.limit(4);
//szeRead.clear();
try {
KNEChannels.readFully(connectSocket,szeRead);
szeRead.flip();
int size=szeRead.getInt(0);
kp=NetworkPacket.bufferAllocator.allocate(size);
incInput(size);
kp.limit(size);
KNEChannels.readFully(connectSocket, kp);
kp.flip();
return kp;
}finally {
timerenabled=false;
}
}
/* @Override
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
szeWrite.limit(4);
//szeWrite.clear();
int length=(int) kp.getLength();
incOutput(length);
szeWrite.putInt(length);
szeWrite.flip();
KLALBVirtualSocketChannel obj = null;
if(connectSocket instanceof KLALBVirtualSocketChannel) {
obj=(KLALBVirtualSocketChannel) connectSocket;
}
boolean isaflush=false;
if(obj!=null) {
isaflush=obj.isAutoFlush();
obj.setAutoFlush(false);
}
connectSocket.write(szeWrite);
if(obj!=null) {
obj.setAutoFlush(true);
}
KLALBPacket.writeKLALBPacketToChannel(connectSocket, kp);
if(obj!=null) {
obj.setAutoFlush(isaflush);
}
}
@Override
public KLALBPacket readKLALBPacket() throws IOException {
ByteBuffer szeWrite=NetworkPacket.bufferAllocator.allocate(4);
szeWrite.limit(4);
KNEChannels.readFully(connectSocket, szeWrite);
szeWrite.flip();
int readSize=szeWrite.getInt();
incInput(readSize);
return KLALBPacket.readKLALBPacketFromChannel(connectSocket);
}*/
}
@@ -7,10 +7,11 @@ import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import org.kne.cloud.network.MultipurposeSocketAddress;
public class StreamKLALBPacketLink implements KLALBPacketLink {
public class StreamKLALBPacketLink extends AbstractKLALBPacketLink implements KLALBPacketLink {
@Override
public String toString() {
@@ -30,13 +31,13 @@ public class StreamKLALBPacketLink implements KLALBPacketLink {
}
@Override
public void writePacket(KLALBPacket kp) throws IOException {
out.writePacket(kp);
public void writeKLALBPacket(KLALBPacket kp) throws IOException {
out.writeKLALBPacket(kp);
}
@Override
public KLALBPacket readPacket() throws IOException {
return in.readPacket();
public KLALBPacket readKLALBPacket() throws IOException {
return in.readKLALBPacket();
}
@Override
@@ -68,5 +69,15 @@ public class StreamKLALBPacketLink implements KLALBPacketLink {
public boolean isStream() {
return true;
}
@Override
public void writePacket(ByteBuffer kp) throws IOException {
out.writePacket(kp);
}
@Override
public ByteBuffer readPacket() throws IOException {
return in.readPacket();
}
}
@@ -1,73 +0,0 @@
package org.kne.cloud.network.klalb;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import org.kne.cloud.network.NetworkPacket;
public class TESTPacket extends KLALBPacket {
private static final int HEADER_LENGTH=3;
private ByteBuffer dataBuffer;//=NetworkPacket.databufferpool_65535.borrow();
@Override
public long getLength() {
return HEADER_LENGTH+dataBuffer.limit();
}
public TESTPacket(int limit) {
super(TEST,HEADER_LENGTH);
//dataBuffer.limit(limit);
dataBuffer=ByteBuffer.allocate(limit);
}
public ByteBuffer getDataBuffer() {
return dataBuffer;
}
@Override
protected void writeToChannel(WritableByteChannel dto) throws IOException {
klalbHeader.putChar(1, (char) dataBuffer.limit());
super.writeToChannel(dto);
//System.out.println(dataBuffer);
dto.write(dataBuffer.slice(0, dataBuffer.limit()));
}
@Override
protected void readFromChannel(ReadableByteChannel din) throws IOException {
super.readFromChannel(din);
int limit=klalbHeader.getChar(1);
//dataBuffer.clear();
//dataBuffer.limit(limit);
dataBuffer=ByteBuffer.allocate(limit);
while(dataBuffer.hasRemaining()){
if(din.read(dataBuffer)==-1) {
throw new EOFException();
}
}
dataBuffer.flip();
}
public TESTPacket(ByteBuffer bb) {
super(bb,HEADER_LENGTH);
}
@Override
public String toString() {
return "TEST["+dataBuffer.limit()+"]";
}
}
@@ -0,0 +1,512 @@
package org.kne.cloud.network.klalb.ui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import javax.swing.JPanel;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
public class GraphPanel extends JPanel {
private Map<Inet6Address,GraphNode> nodes=new ConcurrentHashMap<Inet6Address,GraphNode>();
private List<GraphEdgeGroup> edgeGroups=new ArrayList<GraphEdgeGroup>();
public Map<Inet6Address, GraphNode> getNodes() {
return nodes;
}
public List<GraphEdgeGroup> getEdgeGroups() {
return edgeGroups;
}
private double borderGap=250;
private double translateX,translateY;
private double scale=1;
public double getTranslateX() {
return translateX;
}
public double getTranslateY() {
return translateY;
}
public double getScale() {
return scale;
}
public void setScale(double scale) {
this.scale = scale;
}
@Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d=(Graphics2D)g;
recalcTranslate();
g2d.scale(scale, scale);
g2d.translate(translateX,translateY);
double w=xmax-xmin;
double h=ymax-ymin;
if(w>=0&&h>=0) {
g2d.drawRect((int)(xmin-borderGap), (int)(ymin-borderGap), (int)(w+borderGap*2), (int)(h+borderGap*2));
}
synchronized (edgeGroups) {
for( GraphEdgeGroup graphNode :edgeGroups) {
graphNode.paint(g2d);
}
}
for(GraphNode graphNode :nodes.values()) {
graphNode.paint(g2d);
}
}
public class GraphNode{
private String text;
private Color color;
private double nodesize=40;
private double x;
private double y;
private boolean ismarked;
private Vector2 delta=new Vector2(0, 0);
public GraphNode(String text, Color color, double x, double y,boolean ismarked) {
super();
this.text = text;
this.color = color;
this.x = x;
this.y = y;
this.ismarked=ismarked;
}
public double getNodesize() {
return nodesize;
}
public void setNodesize(double nodesize) {
this.nodesize = nodesize;
}
public boolean isIsmarked() {
return ismarked;
}
public void setIsmarked(boolean ismarked) {
this.ismarked = ismarked;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public double getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public GraphNode() {
super();
}
public double getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(2.0f));
g.drawOval((int)(x-nodesize/2), (int)(y-nodesize/2), (int)(nodesize), (int)(nodesize));
g.setFont(UIEnv.getFont().deriveFont(10.0f));
g.drawString(text, (int)(x+nodesize/2), (int)(y-nodesize/3));
if(ismarked) {
Vector2 pos=new Vector2(x, y);
Vector2 v2a=new Vector2(0, -1).multi(nodesize/4);
Vector2 v2b=new Vector2(Math.sqrt(3)/2.0, 0.5).multi(nodesize/4);
Vector2 v2c=new Vector2(-Math.sqrt(3)/2.0, 0.5).multi(nodesize/4);
v2a=v2a.add(pos);
v2b=v2b.add(pos);
v2c=v2c.add(pos);
g.drawPolygon(new int[] {(int) v2a.x,(int) v2b.x,(int) v2c.x}, new int[] {(int) v2a.y,(int) v2b.y,(int) v2c.y}, 3);
}
}
public Vector2 getPositionVec2() {
return new Vector2(x, y);
}
public void commitDelta() {
x+=delta.x;
y+=delta.y;
delta=new Vector2(0, 0);
}
public void clearDelta() {
delta=new Vector2(0, 0);
}
}
public class GraphEdge{
private GraphNode from;
private GraphNode to;
LinkDirection linkPath;
public GraphEdge(GraphNode nfrom, GraphNode nto,LinkDirection lp) {
this.from=nfrom;
this.to=nto;
this.linkPath=lp;
}
}
public class GraphEdgeGroup{
private double length=100;
private double gap=12;
private boolean isShortest=false;
private GraphNode nodeA,nodeB;
private List<GraphEdge> edges=new ArrayList<>();
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getGap() {
return gap;
}
public void setGap(double gap) {
this.gap = gap;
}
public boolean match(GraphNode a,GraphNode b) {
if(a.equals( nodeA)&&b.equals( nodeB))
return true;
if(b.equals( nodeA)&&a.equals( nodeB))
return true;
return false;
}
public GraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) {
super();
this.nodeA = nodeA;
this.nodeB = nodeB;
}
public boolean isShortest() {
return isShortest;
}
public void setShortest(boolean isShortest) {
this.isShortest = isShortest;
}
public List<GraphEdge> getPaths() {
return getEdges();
}
public void paint(Graphics2D g) {
Vector2 nodeAv=new Vector2(nodeA.getX(), nodeA.getY());
Vector2 nodeBv=new Vector2(nodeB.getX(), nodeB.getY());
Vector2 vecDir=nodeBv.subtract(nodeAv);
Vector2 vecDirnor=vecDir.normalize();
Vector2 vecRA=vecDirnor.multi(nodeA.getNodesize()/2);
Vector2 vecRB=vecDirnor.multi(nodeB.getNodesize()/2);
Vector2 vec90nor=new Vector2( -vecDir.y, vecDir.x).normalize();
//所有线路完整显示
/*
double width=gap*(edges.size()-1);
//System.out.println(width);
Vector2 startPoint=nodeAv.add(vecR).add(vec90nor.multi(width/2));
Vector2 endPoint=nodeBv.subtract(vecR).add(vec90nor.multi(width/2));
for (Iterator<GraphEdge> iterator = edges.iterator(); iterator.hasNext();) {
GraphEdge graphEdge = (GraphEdge) iterator.next();
//System.out.println(vec90nor);
g.setColor(KLALBUtils.getColorByLoadPercentage(graphEdge.linkPath.getSpeed()*100f/graphEdge.linkPath.getBandwidth()));
if(graphEdge.from.equals( nodeA)&&graphEdge.to.equals(nodeB) )
drawAL((int)startPoint.x, (int)startPoint.y, (int)endPoint.x, (int)endPoint.y,g);
if(graphEdge.to.equals( nodeA)&&graphEdge.from.equals(nodeB) )
drawAL((int)endPoint.x, (int)endPoint.y, (int)startPoint.x, (int)startPoint.y,g);
startPoint=startPoint.subtract(vec90nor.multi(gap));
endPoint=endPoint.subtract(vec90nor.multi(gap));
}
*/
long totalupspeed=0;
long usedupspeed=0;
long totaldownspeed=0;
long useddownspeed=0;
for(GraphEdge graphEdge :getEdges()) {
if(graphEdge.from.equals( nodeA)&&graphEdge.to.equals(nodeB) ) {
totalupspeed+=graphEdge.linkPath.getBandwidth();
usedupspeed+=graphEdge.linkPath.getSpeed();
}
if(graphEdge.to.equals( nodeA)&&graphEdge.from.equals(nodeB) ) {
totaldownspeed+=graphEdge.linkPath.getBandwidth();
useddownspeed+=graphEdge.linkPath.getSpeed();
}
}
g.setStroke(new BasicStroke((float) Math.max(2.0, Math.log10(totalupspeed/10.0/1024.0))));
double width=gap*1;
Vector2 startPoint=nodeAv.add(vecRA).add(vec90nor.multi(width/2));
Vector2 endPoint=nodeBv.subtract(vecRB).add(vec90nor.multi(width/2));
g.setColor(KLALBUtils.getColorByLoadPercentagex(usedupspeed*100f/totalupspeed));
drawAL((int)startPoint.x, (int)startPoint.y, (int)endPoint.x, (int)endPoint.y,g);
startPoint=startPoint.subtract(vec90nor.multi(gap));
endPoint=endPoint.subtract(vec90nor.multi(gap));
g.setStroke(new BasicStroke((float) Math.max(2.0, Math.log10(totaldownspeed/10.0/1024.0))));
g.setColor(KLALBUtils.getColorByLoadPercentagex(useddownspeed*100f/totaldownspeed));
drawAL((int)endPoint.x, (int)endPoint.y, (int)startPoint.x, (int)startPoint.y,g);
startPoint=startPoint.subtract(vec90nor.multi(gap));
endPoint=endPoint.subtract(vec90nor.multi(gap));
if(isShortest) {
BasicStroke dotted = new BasicStroke(2, BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND, 0, new float[]{0,3,0,3}, 0);
g.setStroke(dotted);
g.setColor(Color.BLUE);
g.drawLine((int)nodeA.getX(), (int)nodeA.getY(), (int)nodeB.getX(), (int)nodeB.getY());
}
}
public List<GraphEdge> getEdges() {
return edges;
}
}
// 计算
public static double[] rotateVec(int px, int py, double ang,
boolean isChLen, double newLen) {
double mathstr[] = new double[2];
// 矢量旋转函数参数含义分别是x分量y分量旋转角是否改变长度新长度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
public static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2)
{
double H = 13; // 箭头高度
double L = 8; // 底边的一半
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // 箭头角度
double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
// 画线
g2.drawLine(sx, sy, ex, ey);
//
GeneralPath triangle = new GeneralPath();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.closePath();
//实心箭头
g2.fill(triangle);
//非实心箭头
//g2.draw(triangle);
}
protected void loadNodes() {
updateBounds();
}
private void recalcTranslate() {
double xmin=Double.MAX_VALUE,xmax=Double.MIN_VALUE;
double ymin=Double.MAX_VALUE,ymax=Double.MIN_VALUE;
for(GraphNode graphNode:nodes.values()) {
xmin=Math.min(xmin, graphNode.x);
xmax=Math.max(xmax, graphNode.x);
ymin=Math.min(ymin, graphNode.y);
ymax=Math.max(ymax, graphNode.y);
}
this.xmin=xmin;
this.xmax=xmax;
this.ymin=ymin;
this.ymax=ymax;
if(xmin!=Double.MAX_VALUE) {
translateX=-xmin+borderGap;
translateY= -ymin+borderGap;
}
}
private double xmin=Double.MAX_VALUE,xmax=Double.MIN_VALUE;
private double ymin=Double.MAX_VALUE,ymax=Double.MIN_VALUE;
public void updateBounds() {
recalcTranslate();
if(xmin!=Double.MAX_VALUE) {
Dimension d=new Dimension((int)(((xmax-xmin)+borderGap*2)*scale),(int)(((ymax-ymin)+borderGap*2)*scale) );
setPreferredSize(d);
setSize(d);
}
}
public void runPhy() {
for( GraphNode graphEdgeGroup :nodes.values()) {
Vector2 vecpos=graphEdgeGroup.getPositionVec2();
Vector2 vec=new Vector2(0, 0);
for (Iterator<GraphNode> iteratorx =nodes.values().iterator(); iteratorx.hasNext();) {
GraphNode graphEdgeGroup2 = (GraphNode) iteratorx.next();
if(graphEdgeGroup2!=graphEdgeGroup) {
Vector2 vecpos2=graphEdgeGroup2.getPositionVec2();
Vector2 sub=vecpos.subtract(vecpos2);
double distance=sub.Length();
Vector2 dic=sub.normalize();
vec=vec.add(dic.multi(Math.min(10.0/distance,10.0)));
}
}
graphEdgeGroup.delta=graphEdgeGroup.delta.add(vec);
}
synchronized (edgeGroups) {
for(GraphEdgeGroup graphEdgeGroup :edgeGroups) {
GraphNode na=graphEdgeGroup.nodeA;
GraphNode nb=graphEdgeGroup.nodeB;
Vector2 veca=na.getPositionVec2();
Vector2 vecb=nb.getPositionVec2();
Vector2 sub=veca.subtract(vecb);
double distance=sub.Length();
double length=graphEdgeGroup.getLength()+na.getNodesize()/2+nb.getNodesize()/2;
//System.out.println(length);
if(distance>length) {
Vector2 dicb=sub.normalize().multi((distance-length)/3);
Vector2 dica=dicb.opposite();
na.delta=na.delta.add(dica);
nb.delta=nb.delta.add(dicb);
}
}
}
for( GraphNode graphEdgeGroup:nodes.values()) {
graphEdgeGroup.commitDelta();
}
}
private Random r=new Random();
public Vector2 getRandomPos() {
double x,y;
if(xmin>=xmax) {
x=r.nextDouble();
}else {
x=r.nextDouble(xmin, xmax);
}
if(ymin>=ymax) {
y=r.nextDouble();
}else {
y=r.nextDouble(ymin, ymax);
}
return new Vector2(x, y);
}
}
@@ -5,9 +5,12 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.MenuItem;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.Rectangle;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
@@ -18,7 +21,14 @@ import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;
@@ -32,7 +42,9 @@ import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JViewport;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.border.LineBorder;
import org.jfree.chart.ChartPanel;
@@ -45,11 +57,14 @@ import org.jfree.chart.plot.dial.StandardDialRange;
import org.jfree.chart.plot.dial.StandardDialScale;
import org.jfree.chart.ui.RectangleEdge;
import org.jfree.data.general.DefaultValueDataset;
import org.kne.cloud.klalb.uitool.SettingItem;
import org.kne.cloud.klalb.uitool.TextSettingItem;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.klalb.CONST;
import org.kne.cloud.network.klalb.KLALBController;
import org.kne.cloud.network.klalb.KLALBRemoteLine;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.klalb.ui.GraphPanel.GraphNode;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.ui.XFrame;
import org.kne.ui.YScrollPane;
@@ -63,8 +78,6 @@ public class KLALBStateGUI2 extends XFrame {
private TrayIcon ti;
private long rate=200;
private Timer t,t2,t3;
private JCheckBoxMenuItem showoffline;
@@ -103,13 +116,16 @@ public class KLALBStateGUI2 extends XFrame {
private DefaultValueDataset downEfficiency;*/
private YScrollPane ysp;
private YScrollPane ysp,yspc;
private JTextField devicesOnline;
private JTextField textField;
private JTextField addressField;
private JTextField addressField2;
private JTextField asnField;
private NetworkGraphPanel graph;
private JTextField textFieldLocate;
/**
@@ -771,11 +787,135 @@ public class KLALBStateGUI2 extends XFrame {
JPanel panel_4 = new JPanel();
panel_3.add(panel_4, BorderLayout.NORTH);
panel_4.setLayout(new BorderLayout(0, 0));
textFieldLocate = new JTextField();
panel_4.add(textFieldLocate, BorderLayout.CENTER);
textFieldLocate.setColumns(10);
graph = new NetworkGraphPanel(kc.getIpv6Router().getKlalbRouteProtol());
graph.setOpaque(false);
JScrollPane jsp=new JScrollPane(graph);
JScrollPane jsp=new JScrollPane();jsp.setWheelScrollingEnabled(false);
jsp.setViewportView(graph);
MouseAdapter ma = new MouseAdapter() {
private Point origin;
@Override
public void mousePressed(MouseEvent e) {
origin = new Point(e.getPoint());
//System.out.println(e);
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseDragged(MouseEvent e) {
if (origin != null) {
//System.out.println(e);
//JViewport viewPort = (JViewport) SwingUtilities.getAncestorOfClass(JViewport.class, jsp);
//if (viewPort != null) {
int deltaX = origin.x - e.getX();
int deltaY = origin.y - e.getY();
Rectangle view = jsp.getViewport().getVisibleRect();
view.x += deltaX;
view.y += deltaY;
jsp.getViewport().scrollRectToVisible(view);
// }
}
}
};
graph.addMouseWheelListener(new MouseWheelListener() {
private double scaleidx=1;
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
int val= e.getWheelRotation();
double scaleidxold=scaleidx;
scaleidx*=Math.pow(1.1, val);
if(scaleidx>5) {
scaleidx=5;
}
if(scaleidx<0.1) {
scaleidx=0.1;
}
double pow=scaleidx/scaleidxold;
Point pos = jsp.getViewport().getViewPosition();
double canvasX=e.getX();
double canvasY=e.getY();
double w=graph.getWidth();
double h=graph.getHeight();
double percentX=canvasX/w;
double percentY=canvasY/h;
graph.setScale(scaleidx);
graph.updateBounds();
double newcanvasX=percentX*w*pow;
double newcanvasY=percentY*h*pow;
double dx= newcanvasX-canvasX;
double dy=newcanvasY-canvasY;
//System.out.println(dx+" "+dy);
pos.x+=dx;
pos.y+=dy ;
jsp.getViewport().setViewPosition(pos);
}
});
JButton btnLocate = new JButton("Locate");
btnLocate.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String text= textFieldLocate.getText();
try {
Inet6Address addr=(Inet6Address) Inet6Address.getByName(text);
GraphNode node= graph.getNodes().get(addr);
if(node==null) {
JOptionPane.showMessageDialog(KLALBStateGUI2.this, "Address not found", "Warning", JOptionPane.WARNING_MESSAGE);
}else {
Point pos = new Point();
graph.updateBounds();
Dimension dim= jsp.getViewport().getExtentSize();
// System.out.println(dim);
pos.x =(int) ((node.getX()+graph.getTranslateX())*graph.getScale()-dim.width/2);
pos.y =(int) ((node.getY()+graph.getTranslateY())*graph.getScale()-dim.height/2);
jsp.getViewport().setViewPosition(pos);
}
} catch (UnknownHostException e1) {
JOptionPane.showMessageDialog(KLALBStateGUI2.this, "Input format error", "Error", JOptionPane.ERROR_MESSAGE);
e1.printStackTrace();
}
}
});
panel_4.add(btnLocate, BorderLayout.EAST);
JButton btnHome = new JButton("Home");
btnHome.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textFieldLocate.setText(addressField.getText());
btnLocate.doClick();
}
});
panel_4.add(btnHome, BorderLayout.WEST);
graph.addMouseListener(ma);
graph.addMouseMotionListener(ma);
panel_3.add(jsp, BorderLayout.CENTER);
yspc = new YScrollPane(730);
yspc.setOpaque(false);
JPanel configsPanel = new JPanel();
configsPanel.setLayout(new BorderLayout(0, 0));
configsPanel.add(yspc);
addSettingItems(yspc);
JButton btnSave = new JButton("Save settings");
yspc.add(btnSave, BorderLayout.NORTH);
tabbedPane.addTab("Settings", null, configsPanel, null);
configsPanel.setOpaque(false);
textField.addKeyListener(new KeyListener() {
@Override
@@ -795,7 +935,43 @@ public class KLALBStateGUI2 extends XFrame {
}
}
});
textFieldLocate.addKeyListener(new KeyListener() {
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
// TODO 自动生成的方法存根
if(e.getKeyCode()==KeyEvent.VK_ENTER) {
btnLocate.doClick();
}
}
});
}
private void addSettingItems(YScrollPane settings) {
SettingItem si=new SettingItem("Basic settings",UIEnv.getFont().deriveFont(20.0f).deriveFont(Font.BOLD),CONST.itemwidth,CONST.settingheight);
settings.getView().add(si);
TextSettingItem addr6=new TextSettingItem("IPv6 address",CONST.itemwidth,CONST.settingheight);
addressField2=addr6.getTextField();
settings.getView().add(addr6);
TextSettingItem asn=new TextSettingItem("AS number",CONST.itemwidth,CONST.settingheight);
asnField=asn.getTextField();
settings.getView().add(asn);
settings.updateScrool();
}
private void createRefreshTask(KLALBController kc, YScrollPane ysp) {
if(tsk!=null) {
tsk.cancel();
@@ -920,13 +1096,22 @@ public class KLALBStateGUI2 extends XFrame {
if(!contt.equals(devicesOnline.getText())) {
devicesOnline.setText(contt);
}
String address=kc.getSelf().getHostAddress();
String address=kc.getSelf().getAddress().getHostAddress();
if(!address.equals(addressField.getText())) {
addressField.setText(address);
}
if(!address.equals(addressField2.getText())) {
addressField2.setText(address);
}
String asnstr=Long.toString( kc.getIpv6Router().getASN());
if(!asnstr.equals(asnField.getText())) {
asnField.setText(asnstr);
}
}
};
t2.scheduleAtFixedRate(tsk2, 200, 50);
t2.scheduleAtFixedRate(tsk2, 200, 100);
if(tsk3!=null) {
tsk3.cancel();
@@ -970,7 +1155,7 @@ public class KLALBStateGUI2 extends XFrame {
}
}
};
t3.scheduleAtFixedRate(tsk4, 200, 10);
t3.scheduleAtFixedRate(tsk4, 200, 20);
if(tsk5!=null) {
tsk5.cancel();
}
@@ -978,11 +1163,15 @@ public class KLALBStateGUI2 extends XFrame {
@Override
public void run() {
if(graph.isVisible())
graph.loadNodes();
graph.runPhy();
if(graph.isVisible()) {
graph.repaint();
graph.revalidate();
}
}
};
t.scheduleAtFixedRate(tsk5, 200, 2000);
t.scheduleAtFixedRate(tsk5, 200, 100);
//setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
@@ -2,6 +2,7 @@ package org.kne.cloud.network.klalb.ui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
@@ -14,6 +15,7 @@ import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.image.ImageObserver;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.text.AttributedCharacterIterator;
import java.util.ArrayList;
import java.util.HashMap;
@@ -26,240 +28,80 @@ import java.util.Set;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
public class NetworkGraphPanel extends JPanel {
public class NetworkGraphPanel extends GraphPanel {
private KLALBRoutingProtocol routingProtocol;
private Map<Inet6Address,GraphNode> nodes=new HashMap<Inet6Address,GraphNode>();
private List<GraphEdgeGroup> edgeGroups=new ArrayList<GraphEdgeGroup>();
private static final int nodesize=80;
private class GraphNode{
private String text;
private Color color;
private int x;
private int y;
public GraphNode(String text, Color color, int x, int y) {
super();
this.text = text;
this.color = color;
this.x = x;
this.y = y;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public GraphNode() {
super();
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(2.0f));
g.drawOval(x-nodesize/2, y-nodesize/2, nodesize, nodesize);
g.setFont(UIEnv.getFont().deriveFont(10.0f));
g.drawString(text, x+nodesize/2, y-nodesize/3);
}
}
private class GraphEdge{
private GraphNode from;
private GraphNode to;
private LinkDirection linkPath;
public GraphEdge(GraphNode nfrom, GraphNode nto,LinkDirection lp) {
this.from=nfrom;
this.to=nto;
this.linkPath=lp;
}
}
private class GraphEdgeGroup{
private static final double gap=3;
private GraphNode nodeA,nodeB;
private List<GraphEdge> edges=new ArrayList<>();
private boolean match(GraphNode a,GraphNode b) {
if(a.equals( nodeA)&&b.equals( nodeB))
return true;
if(b.equals( nodeA)&&a.equals( nodeB))
return true;
return false;
}
public GraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) {
super();
this.nodeA = nodeA;
this.nodeB = nodeB;
}
public List<GraphEdge> getPaths() {
return edges;
}
public void paint(Graphics2D g) {
g.setStroke(new BasicStroke(1.0f));
Vector2 nodeAv=new Vector2(nodeA.getX(), nodeA.getY());
Vector2 nodeBv=new Vector2(nodeB.getX(), nodeB.getY());
Vector2 vecDir=nodeBv.subtract(nodeAv);
Vector2 vecDirnor=vecDir.normalize();
Vector2 vecR=vecDirnor.multi(nodesize/2);
Vector2 vec90nor=new Vector2( -vecDir.y, vecDir.x).normalize();
double width=gap*(edges.size()-1);
Vector2 startPoint=nodeAv.add(vecR).add(vec90nor.multi(width/2));
Vector2 endPoint=nodeBv.subtract(vecR).add(vec90nor.multi(width/2));
//System.out.println(width);
for (Iterator<GraphEdge> iterator = edges.iterator(); iterator.hasNext();) {
GraphEdge graphEdge = (GraphEdge) iterator.next();
//System.out.println(vec90nor);
g.setColor(KLALBUtils.getColorByLoadPercentage(graphEdge.linkPath.getSpeed()*100f/graphEdge.linkPath.getBandwidth()));
if(graphEdge.from.equals( nodeA)&&graphEdge.to.equals(nodeB) )
drawAL((int)startPoint.x, (int)startPoint.y, (int)endPoint.x, (int)endPoint.y,g);
if(graphEdge.to.equals( nodeA)&&graphEdge.from.equals(nodeB) )
drawAL((int)endPoint.x, (int)endPoint.y, (int)startPoint.x, (int)startPoint.y,g);
startPoint=startPoint.subtract(vec90nor.multi(gap));
endPoint=endPoint.subtract(vec90nor.multi(gap));
}
//g.drawLine(nodeA.getX(), nodeA.getY(), nodeB.getX(), nodeB.getY());
}
public static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2)
{
double H = 5; // 箭头高度
double L = 2; // 底边的一半
int x3 = 0;
int y3 = 0;
int x4 = 0;
int y4 = 0;
double awrad = Math.atan(L / H); // 箭头角度
double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
double y_3 = ey - arrXY_1[1];
double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
double y_4 = ey - arrXY_2[1];
Double X3 = new Double(x_3);
x3 = X3.intValue();
Double Y3 = new Double(y_3);
y3 = Y3.intValue();
Double X4 = new Double(x_4);
x4 = X4.intValue();
Double Y4 = new Double(y_4);
y4 = Y4.intValue();
// 画线
g2.drawLine(sx, sy, ex, ey);
//
GeneralPath triangle = new GeneralPath();
triangle.moveTo(ex, ey);
triangle.lineTo(x3, y3);
triangle.lineTo(x4, y4);
triangle.closePath();
//实心箭头
g2.fill(triangle);
//非实心箭头
//g2.draw(triangle);
}
// 计算
public static double[] rotateVec(int px, int py, double ang,
boolean isChLen, double newLen) {
double mathstr[] = new double[2];
// 矢量旋转函数参数含义分别是x分量y分量旋转角是否改变长度新长度
double vx = px * Math.cos(ang) - py * Math.sin(ang);
double vy = px * Math.sin(ang) + py * Math.cos(ang);
if (isChLen) {
double d = Math.sqrt(vx * vx + vy * vy);
vx = vx / d * newLen;
vy = vy / d * newLen;
mathstr[0] = vx;
mathstr[1] = vy;
}
return mathstr;
}
}
public NetworkGraphPanel(KLALBRoutingProtocol routingProtocol) {
super();
this.routingProtocol = routingProtocol;
//setSize(10000, 10000);
//setPreferredSize(getSize());
}
@Override
public void paint(Graphics g) {
super.paint(g);
loadNodes();
Graphics2D g2d=(Graphics2D)g;
for (Iterator<GraphEdgeGroup> iterator = edgeGroups.iterator(); iterator.hasNext();) {
GraphEdgeGroup graphNode = (GraphEdgeGroup) iterator.next();
graphNode.paint(g2d);
private class InetGraphNode extends GraphNode{
private InetAddress address;
public InetGraphNode() {
super();
}
public InetGraphNode(InetAddress address, Color color, double x, double y, boolean ismarked) {
super(getText(address), color, x, y, ismarked);
this.address=address;
}
private static String getText(InetAddress address2) {
String text;
if(address2 instanceof Inet6Address) {
text=KLALBUtils.parseAbbrIPv6(address2.getHostAddress());
}else {
text=address2.getHostAddress();
}
return text;
}
public InetAddress getAddress() {
return address;
}
public void setAddress(InetAddress address) {
this.address = address;
super.setText(getText(address));
}
for (Iterator<GraphNode> iterator = nodes.values().iterator(); iterator.hasNext();) {
GraphNode graphNode = (GraphNode) iterator.next();
graphNode.paint(g2d);
}
}
Random r=new Random();
private void loadNodes() {
private double nsPerPixel=1000L;
private class InetGraphEdgeGroup extends GraphEdgeGroup{
public InetGraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) {
super(nodeA, nodeB);
}
public void updateLength() {
long mindelay=Long.MAX_VALUE>>2;
for (Iterator<GraphEdge> iterator = getEdges().iterator(); iterator.hasNext();) {
GraphEdge graphEdge = (GraphEdge) iterator.next();
mindelay=Math.min(mindelay, graphEdge.linkPath.getDelay());
}
setLength(mindelay/nsPerPixel);
}
}
protected void loadNodes() {
Map<Inet6Address, Long> addr= routingProtocol.getAddresses();
Set<Inet6Address> ks=addr.keySet();
for (Iterator<Inet6Address> iterator = ks.iterator(); iterator.hasNext();) {
Inet6Address inet6Address = (Inet6Address) iterator.next();
if(!nodes.containsKey(inet6Address))
nodes.put(inet6Address,new GraphNode(inet6Address.getHostAddress(),Color.BLACK,r.nextInt(50,getWidth()-100),r.nextInt(50,getHeight()-50)));
}
Set<Inet6Address> kns=nodes.keySet();
if(!getNodes().containsKey(inet6Address)) {
Vector2 v2pos=super.getRandomPos();
getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(routingProtocol.getRouter().getLocator().getAddress())));
}
}
Set<Inet6Address> kns=getNodes().keySet();
for (Iterator<Inet6Address> iterator = kns.iterator(); iterator.hasNext();) {
Inet6Address inet6Address = (Inet6Address) iterator.next();
if(!addr.containsKey(inet6Address)) {
@@ -267,32 +109,53 @@ public class NetworkGraphPanel extends JPanel {
}
}
//System.out.println("------------------------------------");
edgeGroups.clear();
Map<Inet6Address, Set<LinkDirection>> addr1= routingProtocol.getPaths();
Set<Entry<Inet6Address, Set<LinkDirection>>> salink=addr1.entrySet();
for (Iterator<Entry<Inet6Address, Set<LinkDirection>>> iterator = salink.iterator(); iterator.hasNext();) {
Entry<Inet6Address, Set<LinkDirection>> entry = (Entry<Inet6Address, Set<LinkDirection>>) iterator.next();
Set<LinkDirection>lps=entry.getValue();
synchronized (getEdgeGroups()) {
getEdgeGroups().clear();
Map<Inet6Address, List<LinkDirection>> addr1= routingProtocol.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();
List<LinkDirection>lps=entry.getValue();
for (Iterator<LinkDirection> iterator2 = lps.iterator(); iterator2.hasNext();) {
LinkDirection linkPath = (LinkDirection) iterator2.next();
//System.out.println(linkPath);
GraphNode nfrom=nodes.get(linkPath.getFromLocator());
GraphNode nto=nodes.get(linkPath.getToLocator());
InetGraphNode nfrom=(InetGraphNode) getNodes().get(linkPath.getFromLocator());
InetGraphNode nto=(InetGraphNode) getNodes().get(linkPath.getToLocator());
if(nfrom!=null&&nto!=null) {
GraphEdgeGroup group=getGroup(nfrom, nto);
group.getPaths().add(new GraphEdge(nfrom,nto,linkPath));
GraphEdge ge=new GraphEdge(nfrom,nto,linkPath);
group.getPaths().add(ge);
}
}
}
for (Iterator iterator = getEdgeGroups().iterator(); iterator.hasNext();) {
GraphEdgeGroup graphEdgeGroup = (GraphEdgeGroup) iterator.next();
((InetGraphEdgeGroup) graphEdgeGroup).updateLength();
}
}
super.loadNodes();
}
private GraphEdgeGroup getGroup(GraphNode a,GraphNode b) {
for (Iterator iterator = edgeGroups.iterator(); iterator.hasNext();) {
private GraphEdgeGroup getGroup(InetGraphNode a,InetGraphNode b) {
for (Iterator iterator = getEdgeGroups().iterator(); iterator.hasNext();) {
GraphEdgeGroup graphEdgeGroup = (GraphEdgeGroup) iterator.next();
if(graphEdgeGroup.match(a,b)) {
return graphEdgeGroup;
}
}
GraphEdgeGroup ng=new GraphEdgeGroup(a, b);
edgeGroups.add(ng);
GraphEdgeGroup ng=new InetGraphEdgeGroup(a, b);
Inet6Address aprev= routingProtocol.getDijkstraPrevNode((Inet6Address) a.getAddress());
Inet6Address bprev= routingProtocol.getDijkstraPrevNode((Inet6Address) b.getAddress());
if( b.getAddress().equals(aprev)||a.getAddress().equals(bprev)) {
ng.setShortest(true);
}
getEdgeGroups().add(ng);
return ng;
}
}
@@ -10,6 +10,7 @@ import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.klalb.CONST;
import org.kne.cloud.network.klalb.KLALBController;
import org.kne.cloud.network.klalb.KLALBRemoteLine;
import org.kne.cloud.network.klalb.KLALBUtils;
@@ -93,7 +94,7 @@ public class TPanel2 extends JPanel {
targup.setHorizontalTextPosition(SwingConstants.LEFT);
setBorder(new LineBorder(Color.LIGHT_GRAY));
setSize(720, 45);
setSize(CONST.itemwidth, CONST.linepanelheight);
setPreferredSize(getSize());
JPanel panel = new JPanel();