forked from KNEMC/KLALB
- 设置页新增设备名称(单行)、设备描述(多行)、额外路由(CIDR列表)设置项 - RouterInfo 广播携带 deviceName,并在拓扑图节点与节点概览中展示;deviceDescription 保持本地概览显示 - 拓扑图节点标签支持多行文本绘制 - 节点概览面板新增 IP 地址及设备详情展示 - 支持将 TUNName 设为 null/"null"/空字符串时完全跳过 Wintun 虚拟网卡创建 - .classpath 容器改为标准 JavaSE-25 执行环境以同时兼容 JDK 25 与 26 - 新增 AGENTS.md 与 VS Code 调试及运行配置 BREAKING CHANGE: RouterInfo 在序列化末尾追加了 deviceName 字段(writeUTF),新旧版本节点混连时路由协议解析异常,需同步升级
714 lines
22 KiB
Java
714 lines
22 KiB
Java
package org.kne.cloud.network.srv6;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.net.BindException;
|
|
import java.net.DatagramPacket;
|
|
import java.net.Inet6Address;
|
|
import java.net.InetSocketAddress;
|
|
import java.net.SocketAddress;
|
|
import java.net.SocketException;
|
|
import java.nio.channels.Channels;
|
|
import java.util.ArrayList;
|
|
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.Objects;
|
|
import java.util.Set;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import java.util.concurrent.CopyOnWriteArraySet;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
import java.util.function.BiConsumer;
|
|
|
|
import org.kne.cloud.network.ipv6.IPv6Address;
|
|
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
|
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader;
|
|
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
|
import org.kne.cloud.network.ipv6.Neighbor;
|
|
import org.kne.cloud.network.klalb.KLALBVirtualRawSocket;
|
|
import org.kne.cloud.network.monitor.DelayMonitorData;
|
|
import org.kne.cloud.network.monitor.MonitorData;
|
|
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
|
|
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorData;
|
|
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
|
|
import org.kne.membandboost.MembandBoost;
|
|
|
|
public class KLALBRoutingProtocol extends Thread{
|
|
|
|
private static final boolean debug = false;
|
|
|
|
private RouterInfo selfRouterInfo;
|
|
private Map<IPv6Address, RouterInfo> netmap=new ConcurrentHashMap<>();
|
|
|
|
|
|
private volatile Map<IPv6Address,Long>addresses;
|
|
|
|
private volatile Map<IPv6Address, List<LinkDirection>> paths;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static final int DEFAULT_PORT=1001;
|
|
|
|
public static final int DEFAULT_PROTOCOL_NUMBER=252;
|
|
|
|
public static final long HOTSOPT_TIMEOUT = 1000000000;
|
|
|
|
public static final int HOTSOPT_REPORT_INTERVAL = 1000000;
|
|
private SRv6Router router;
|
|
public SRv6Router getRouter() {
|
|
return router;
|
|
}
|
|
public KLALBRoutingProtocol(SRv6Router router) {
|
|
this.router=router;
|
|
}
|
|
|
|
//private ReentrantLock sendlock=new ReentrantLock();
|
|
|
|
private long floodTimer=System.nanoTime();
|
|
private long floodTimer2=System.nanoTime();
|
|
private long requestTimer=System.nanoTime();
|
|
private KLALBVirtualRawSocket ds = null;
|
|
private ReentrantLock sendLock=new ReentrantLock();
|
|
|
|
private Set<BiConsumer<SocketAddress,JsonDataPacket>>receivers=new CopyOnWriteArraySet<BiConsumer<SocketAddress,JsonDataPacket>>();
|
|
|
|
public void addReceiver(BiConsumer<SocketAddress,JsonDataPacket> rec) {
|
|
receivers.add(rec);
|
|
}
|
|
|
|
public void removeReceiver(BiConsumer<SocketAddress,JsonDataPacket> rec) {
|
|
receivers.remove(rec);
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
Thread.currentThread().setName("KLALB路由协议接收线程");
|
|
getSelfRouterInfo();
|
|
try{
|
|
ds=new KLALBVirtualRawSocket(router.getinLoopback(),router.getLocator().getAddress().toInet6Address(), DEFAULT_PROTOCOL_NUMBER);
|
|
new Thread(()->{
|
|
Thread.currentThread().setName("KLALB路由协议发送线程");
|
|
|
|
while(true) {
|
|
try {
|
|
selfRouterInfo = getSelfRouterInfo();
|
|
RouterInfo oslf=netmap.put(selfRouterInfo.getLocator().getAddress(), selfRouterInfo);
|
|
noticeUpdate();
|
|
/*if(oslf==null||(!selfRouterInfo.equals(oslf))) {
|
|
long cur=System.nanoTime();
|
|
if(cur-floodTimer2>5000000000L) {
|
|
//System.out.println("update10");
|
|
floodTimer2=cur;
|
|
floodPacket(ds2, null, new RouterInfoPacket(selfRouterInfo,true));
|
|
}
|
|
}else {
|
|
long cur=System.nanoTime();
|
|
if(cur-floodTimer>60000000000L) {
|
|
//System.out.println("update60");
|
|
floodTimer=cur;
|
|
floodPacket(ds2, null, new RouterInfoPacket(selfRouterInfo,true));
|
|
}
|
|
}*/
|
|
|
|
long cur=System.nanoTime();
|
|
if(cur-floodTimer>20000000000L) {
|
|
if(debug)
|
|
System.out.println("update60");
|
|
floodTimer=cur;
|
|
floodPacket( null, new RouterInfoPacket(selfRouterInfo,true,-1));
|
|
}
|
|
|
|
if(cur-floodTimer2>2000000000L) {
|
|
if(debug)
|
|
System.out.println("update1");
|
|
floodTimer2=cur;
|
|
floodPacket(null, new RouterInfoPacket(selfRouterInfo,true,router.getASN()));
|
|
}
|
|
|
|
//Set<Inet6Address> requestSet=new HashSet<>();
|
|
for (Iterator<Entry<IPv6Address, RouterInfo>> iterator = netmap.entrySet().iterator(); iterator.hasNext();) {
|
|
Entry<IPv6Address, RouterInfo> type = (Entry<IPv6Address, RouterInfo>) iterator.next();
|
|
RouterInfo val=type.getValue();
|
|
long timeout=30000000000L;
|
|
if(val.getAsn()==router.getASN()) {
|
|
timeout=2000000000L;
|
|
}
|
|
if(val.checkTimeOut(timeout)) {
|
|
iterator.remove();
|
|
noticeUpdate();
|
|
}
|
|
/*List<NeighborInfo> ads=val.getNeighborAddresses();
|
|
for (Iterator<NeighborInfo> iterator2 = ads.iterator(); iterator2.hasNext();) {
|
|
Inet6Address address=iterator2.next().getLocator().getAddress();
|
|
//System.out.println(address);
|
|
if(!netmap.containsKey(address)) {
|
|
requestSet.add(address);
|
|
}
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
computeShortestPathIfUpdated();
|
|
|
|
|
|
|
|
/*long cur2=System.nanoTime();
|
|
if(cur2-requestTimer>1000000000L) {
|
|
requestTimer=cur2;
|
|
|
|
for (Iterator<Inet6Address> iterator = requestSet.iterator(); iterator.hasNext();) {
|
|
Inet6Address inet6Address = (Inet6Address) iterator.next();
|
|
|
|
writePacket(ds2, new RouterInfoRequestPacket( ), new InetSocketAddress(inet6Address, DEFAULT_PORT));
|
|
|
|
if(debug)
|
|
System.out.println("Request:"+inet6Address);
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
for (Iterator<Entry<IPv6Address, HotspotAddressTimer>> iterator = hotspots.entrySet().iterator(); iterator.hasNext();) {
|
|
Entry<IPv6Address, HotspotAddressTimer> type = (Entry<IPv6Address, HotspotAddressTimer>) iterator.next();
|
|
//if(type.getValue().checkReportTime()) {
|
|
//System.out.println("hotspot address:"+type.getKey());
|
|
//writePacket(ds2, new RouterInfoPacket( netmap.get(router.getLocator().getAddress()),false,-1), new InetSocketAddress(type.getKey(), DEFAULT_PORT));
|
|
//}
|
|
if(type.getValue().checkTimeOut()) {
|
|
iterator.remove();
|
|
}
|
|
|
|
}
|
|
|
|
Thread.sleep(20);
|
|
|
|
|
|
} catch (InterruptedException e) {
|
|
e.printStackTrace();
|
|
}catch (IOException e1) {
|
|
// TODO 自动生成的 catch 块
|
|
e1.printStackTrace();
|
|
}
|
|
}
|
|
}).start();
|
|
while(true) {
|
|
|
|
try {
|
|
byte[]ca=MembandBoost.allocateUninitializedArray(65535);
|
|
DatagramPacket dgp=new DatagramPacket(ca, ca.length);
|
|
ds.receive(dgp);
|
|
//System.out.println(Arrays.toString( Arrays.copyOf( dgp.getData(),dgp.getLength())));
|
|
ByteArrayInputStream bi=new ByteArrayInputStream(dgp.getData(),0,dgp.getLength());
|
|
KLALBRoutingProtocolPacket kp=KLALBRoutingProtocolPacket.readKLALBPacketFromChannel(Channels.newChannel(bi));
|
|
|
|
switch(kp.getType()) {
|
|
case KLALBRoutingProtocolPacket.RINFO_REQ:
|
|
RouterInfo rifr=netmap.get(router.getLocator().getAddress());
|
|
if(debug)
|
|
System.out.println("get Request from:"+dgp.getSocketAddress());
|
|
if(rifr!=null) {
|
|
writePacket( new RouterInfoPacket( rifr,false,-1), dgp.getSocketAddress());
|
|
if(debug)
|
|
System.out.println("response router info:"+rifr);
|
|
}else {
|
|
if(debug)
|
|
System.out.println("router info is null!");
|
|
}
|
|
break;
|
|
case KLALBRoutingProtocolPacket.RINFO:
|
|
|
|
RouterInfoPacket rifp=(RouterInfoPacket) kp;
|
|
RouterInfo rif=rifp.getRinfo();
|
|
RouterInfo oldrif=netmap.get(rif.getLocator().getAddress());
|
|
|
|
if(debug)
|
|
System.out.println(rif);
|
|
if(oldrif==null||oldrif.getCreateTime()<rif.getCreateTime()) {
|
|
if(debug)
|
|
System.out.println("update RouterInfo");
|
|
netmap.put(rif.getLocator().getAddress(), rif);
|
|
noticeUpdate();
|
|
if(rifp.isFlood()) {
|
|
floodPacket( dgp.getSocketAddress(), rifp);
|
|
|
|
}
|
|
|
|
}else {
|
|
|
|
if(debug)
|
|
System.out.println("dispose RouterInfo");
|
|
}
|
|
computeShortestPathIfUpdated();
|
|
break;
|
|
case KLALBRoutingProtocolPacket.JSON_DATA:
|
|
JsonDataPacket data=(JsonDataPacket) kp;
|
|
receivers.forEach((v)->{v.accept(dgp.getSocketAddress(),data);});
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
} catch (SocketException e2) {
|
|
e2.printStackTrace();
|
|
}finally {
|
|
if(ds!=null) {
|
|
ds.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void floodPacket(SocketAddress except,RouterInfoPacket rifp) throws IOException {
|
|
long asn=rifp.getASN();
|
|
List<Neighbor>ln= router.getNeighbors();
|
|
Set<InetSocketAddress>ist=new HashSet<InetSocketAddress>();
|
|
for(Neighbor addresses :ln) {
|
|
if(addresses.getLocator()==null)
|
|
continue;
|
|
InetSocketAddress isa=new InetSocketAddress(addresses.getLocator().getAddress().toInet6Address(),DEFAULT_PORT);
|
|
if(!ist.add(isa)) {
|
|
continue;
|
|
}
|
|
if(!isa.equals(except)) {
|
|
if(asn==-1) {
|
|
writePacket( rifp, isa);
|
|
}else{
|
|
RouterInfo nif= netmap.get( IPv6Address.valueOf( isa.getAddress()));
|
|
if(nif!=null&&nif.getAsn()==asn) {
|
|
writePacket( rifp, isa);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void sendJsonPacketToAddress(JsonDataPacket pkt,SocketAddress dest) throws IOException {
|
|
writePacket(pkt,dest);
|
|
}
|
|
|
|
private void writePacket(KLALBRoutingProtocolPacket pkt,SocketAddress dest) throws IOException {
|
|
ByteArrayOutputStream bos=new ByteArrayOutputStream(65535);
|
|
KLALBRoutingProtocolPacket.writeKLALBPacketToChannel(Channels.newChannel(bos),pkt);
|
|
byte[]to=bos.toByteArray();
|
|
DatagramPacket dgpx=new DatagramPacket(to,to.length);
|
|
dgpx.setSocketAddress(dest);
|
|
sendLock.lock();
|
|
try {
|
|
ds.send(dgpx);
|
|
}catch(BindException e) {
|
|
e.printStackTrace();
|
|
System.err.println("Cannot assign:"+dest);
|
|
}finally {
|
|
sendLock.unlock();
|
|
}
|
|
}
|
|
|
|
private DijkstraAlgorithm algorithm=new SingleDijkstraAlgorithm();
|
|
|
|
private ReentrantLock directionLock=new ReentrantLock();
|
|
|
|
private volatile NetmapDirections directions;
|
|
|
|
private static class NetmapDirections{
|
|
|
|
public NetmapDirections(long[] direction, List<IPv6Address> rias,
|
|
Map<IPv6Address, Long> direction_airs) {
|
|
super();
|
|
this.direction = direction;
|
|
this.direction_rias = rias;
|
|
this.direction_airs = direction_airs;
|
|
}
|
|
|
|
public NetmapDirections(long[] direction, List<Inet6Address> rias, Map<Inet6Address, Long> airs,Object obj) {
|
|
this.direction = direction;
|
|
this.direction_rias=new ArrayList<IPv6Address>();
|
|
rias.forEach((addr)->{
|
|
direction_rias.add(new IPv6Address(addr));
|
|
});
|
|
this.direction_airs=new HashMap<>();
|
|
airs.forEach((k,v)->{
|
|
direction_airs.put(new IPv6Address(k), v);
|
|
});
|
|
}
|
|
|
|
private long[] direction;
|
|
|
|
private List<IPv6Address> direction_rias;
|
|
|
|
private Map<IPv6Address, Long> direction_airs;
|
|
|
|
public long[] getDirection() {
|
|
return direction;
|
|
}
|
|
|
|
public List<IPv6Address> getDirection_rias() {
|
|
return direction_rias;
|
|
}
|
|
|
|
public Map<IPv6Address, Long> getDirection_airs() {
|
|
return direction_airs;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private volatile boolean updated=false;
|
|
public void noticeUpdate() {
|
|
updated=true;
|
|
}
|
|
private void computeShortestPathIfUpdated() {
|
|
if(updated) {
|
|
computeShortestPath();
|
|
updated=false;
|
|
}
|
|
}
|
|
|
|
private void computeShortestPath() {
|
|
|
|
directionLock.lock();
|
|
try {
|
|
if(netmap.get(router.getLocator().getAddress())==null) {
|
|
return;
|
|
}
|
|
Set<Entry<IPv6Address, RouterInfo>> s=netmap.entrySet();
|
|
Map<IPv6Address,Long>airs=new HashMap<>(netmap.size()*2,0.4f);
|
|
|
|
List<IPv6Address>rias=new ArrayList<>(netmap.size()+1);
|
|
|
|
Map<IPv6Address,List< LinkDirection>>paths=new HashMap<>();
|
|
long number=0;
|
|
for(Entry<IPv6Address, RouterInfo> entry:s) {
|
|
if(!airs.containsKey(entry.getKey())) {
|
|
airs.put(entry.getKey(),number);
|
|
rias.add( entry.getKey());
|
|
number++;
|
|
}
|
|
List<NeighborInfo> ni= entry.getValue().getNeighborAddresses();
|
|
for(NeighborInfo neighborInfo :ni) {
|
|
IPv6Address ias2=neighborInfo.getLocator().getAddress();
|
|
if(!airs.containsKey(ias2)) {
|
|
airs.put(ias2,number);
|
|
rias.add( ias2);
|
|
number++;
|
|
}
|
|
List<LinkDirection>lp1=paths.get(entry.getKey());
|
|
if(lp1==null) {
|
|
paths.put(entry.getKey(), lp1=new ArrayList<>());
|
|
}
|
|
lp1.add(new LinkDirection(neighborInfo.getLocal(),neighborInfo.getNeighbor(),entry.getKey(), ias2, neighborInfo.getUploadDelay(),neighborInfo.getUploadDelayMin(),neighborInfo.getUploadSpeed(),neighborInfo.getUploadSpeedMax()));
|
|
|
|
/*Set<LinkDirection>lp2=paths.get(ias2);
|
|
if(lp2==null) {
|
|
paths.put(ias2, lp2=new HashSet<>());
|
|
}
|
|
lp2.add( new LinkDirection(neighborInfo.getNeighbor(),neighborInfo.getLocal(),ias2,entry.getKey() , neighborInfo.getDownloadDelay(),neighborInfo.getDownloadDelayMin(),neighborInfo.getDownloadSpeed(),neighborInfo.getDownloadSpeedMax()));
|
|
*/
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
long[][]pointers=new long[(int) airs.size()][2];
|
|
long heappos=0;
|
|
long linknumber=0;
|
|
for(Entry<IPv6Address, List<LinkDirection>> entry:paths.entrySet()) {
|
|
/*for (Iterator<Entry<Inet6Address, Set<LinkDirection>>> iterator = paths.entrySet().iterator(); iterator.hasNext();) {
|
|
Entry<Inet6Address, Set<LinkDirection>> entry = (Entry<Inet6Address, Set<LinkDirection>>) iterator.next();*/
|
|
linknumber+=entry.getValue().size();
|
|
}
|
|
long[][]heap=new long[(int) (linknumber)][2];
|
|
for (long i = 0; i < number; i++) {
|
|
long heapindex=0;
|
|
pointers[(int) i][0]=heappos;
|
|
IPv6Address ia=rias.get((int) i);
|
|
List<LinkDirection>lks=paths.get(ia);
|
|
if(lks!=null)
|
|
for(LinkDirection linkPath:lks) {
|
|
/*
|
|
for (Iterator<LinkDirection> iterator = lks.iterator(); iterator.hasNext();) {
|
|
LinkDirection linkPath=iterator.next();*/
|
|
heap[(int)(heappos+ heapindex)][0]=airs.get(linkPath.getToLocator());
|
|
heap[(int) (heappos+heapindex)][1]=linkPath.getWeight();
|
|
//heap[(int) (heappos+heapindex)][2]=linkPath.get
|
|
// heap[(int) (heappos+heapindex)][3]=0;
|
|
heapindex++;
|
|
|
|
}
|
|
|
|
heappos+=heapindex;
|
|
pointers[(int) i][1]=heapindex;
|
|
}
|
|
|
|
|
|
|
|
algorithm.setGraph(pointers,heap,airs.get(router.getLocator().getAddress()));
|
|
algorithm.run();
|
|
directions=new NetmapDirections(algorithm.getDirection(), rias, airs);
|
|
addresses=airs;
|
|
this.paths=paths;
|
|
}finally {
|
|
directionLock.unlock();
|
|
}
|
|
//System.out.println(Arrays.toString( algorithm.getDirection()));
|
|
}
|
|
public static class LinkDirection{
|
|
private IPv6AddressGroup fromAddress;
|
|
private IPv6AddressGroup toAddress;
|
|
private IPv6Address fromLocator;
|
|
private IPv6Address toLocator;
|
|
private long delay;
|
|
private long delayMin;
|
|
private long speed;
|
|
public long getSpeed() {
|
|
return speed;
|
|
}
|
|
private long bandwidth;
|
|
public IPv6AddressGroup getFromAddress() {
|
|
return fromAddress;
|
|
}
|
|
public IPv6AddressGroup getToAddress() {
|
|
return toAddress;
|
|
}
|
|
public long getDelay() {
|
|
return delay;
|
|
}
|
|
public long getBandwidth() {
|
|
return bandwidth;
|
|
}
|
|
|
|
public long getDelayMin() {
|
|
return delayMin;
|
|
}
|
|
|
|
public LinkDirection(IPv6AddressGroup fromAddress, IPv6AddressGroup toAddress, IPv6Address fromLocator,
|
|
IPv6Address toLocator, long delay, long delayMin, long speed, long bandwidth) {
|
|
super();
|
|
this.fromAddress = fromAddress;
|
|
this.toAddress = toAddress;
|
|
this.fromLocator = fromLocator;
|
|
this.toLocator = toLocator;
|
|
this.delay = delay;
|
|
this.delayMin = delayMin;
|
|
this.speed = speed;
|
|
this.bandwidth = bandwidth;
|
|
}
|
|
@Override
|
|
public String toString() {
|
|
return "LinkDirection [fromAddress=" + fromAddress + ", toAddress=" + toAddress + ", fromLocator="
|
|
+ fromLocator + ", toLocator=" + toLocator + ", delay=" + delay + ", delayMin=" + delayMin
|
|
+ ", speed=" + speed + ", bandwidth=" + bandwidth + "]";
|
|
}
|
|
public IPv6Address getFromLocator() {
|
|
return fromLocator;
|
|
}
|
|
@Override
|
|
public int hashCode() {
|
|
return Objects.hash(fromAddress, toAddress);
|
|
}
|
|
@Override
|
|
public boolean equals(Object obj) {
|
|
if (this == obj)
|
|
return true;
|
|
if (obj == null)
|
|
return false;
|
|
if (getClass() != obj.getClass())
|
|
return false;
|
|
LinkDirection other = (LinkDirection) obj;
|
|
return Objects.equals(fromAddress, other.fromAddress) && Objects.equals(toAddress, other.toAddress);
|
|
}
|
|
public IPv6Address getToLocator() {
|
|
return toLocator;
|
|
}
|
|
public long getWeight() {
|
|
return delay;
|
|
}
|
|
}
|
|
private RouterInfo getSelfRouterInfo() {
|
|
List<IPv6NetworkLink>links=router.getLinkTabel();
|
|
Object[] nls=links.toArray();
|
|
RouterInfo ri=new RouterInfo(System.currentTimeMillis(),router.getLocator(),router.getASN());
|
|
ri.setDeviceName(router.getDeviceName());
|
|
for(int i=0;i<nls.length;i++) {
|
|
IPv6NetworkLink nl=(IPv6NetworkLink) nls[i];
|
|
if((!nl.isLoopBack())&&nl.isUp()) {
|
|
List<Neighbor>neis=nl.getNeighborsInfo();
|
|
for (Iterator<Neighbor> iteratorx = neis.iterator(); iteratorx.hasNext();) {
|
|
Neighbor addresses = (Neighbor) iteratorx.next();
|
|
long updelay=10000000000L;
|
|
long downdelay=10000000000L;
|
|
long updelayMin=10000000000L;
|
|
long downdelayMin=10000000000L;
|
|
long uploadspeed=1024L*1024;
|
|
long downloadspeed=1024L*1024;
|
|
long uploadspeedmax=1024L*1024;
|
|
long downloadspeedmax=1024L*1024;
|
|
MonitorData md=addresses.getMonitor();
|
|
if(md!=null) {
|
|
if(md instanceof DelayMonitorData) {
|
|
updelay=((DelayMonitorData) md).getOutDelay();
|
|
downdelay=((DelayMonitorData) md).getInDelay();
|
|
|
|
if(md instanceof SpeedAndTrafficAndDelayMonitorDataImpl) {
|
|
updelayMin=((SpeedAndTrafficAndDelayMonitorDataImpl) md).getOutDelayMin();
|
|
downdelayMin=((SpeedAndTrafficAndDelayMonitorDataImpl) md).getInDelayMin();
|
|
}
|
|
}
|
|
if(md instanceof SpeedAndTrafficMonitorData) {
|
|
uploadspeed=((SpeedAndTrafficMonitorData) md).getOutSpeed();
|
|
downloadspeed=((SpeedAndTrafficMonitorData) md).getInSpeed();
|
|
if(md instanceof SpeedAndTrafficMonitorDataImpl) {
|
|
SpeedAndTrafficMonitorDataImpl smd=(SpeedAndTrafficMonitorDataImpl) md;
|
|
uploadspeedmax=smd.getOutSpeedMax();
|
|
downloadspeedmax=smd.getInSpeedMax();
|
|
}
|
|
}
|
|
}
|
|
NeighborInfo ni=new NeighborInfo(nl.getAddressGroups().get(0),addresses.getAddress(),addresses.getLocator(),updelay ,downdelay,updelayMin ,downdelayMin ,uploadspeed ,downloadspeed,uploadspeedmax ,downloadspeedmax);
|
|
ni.setContext(addresses);
|
|
ri.getNeighborAddresses().add(ni);
|
|
|
|
}
|
|
}
|
|
}
|
|
//if(debug)
|
|
//System.out.println(ri);
|
|
return ri;
|
|
}
|
|
|
|
public Map<IPv6Address, Long> getAddresses() {
|
|
return addresses;
|
|
}
|
|
|
|
/**
|
|
* 查询某地址广播的设备名称(未知返回null)
|
|
*/
|
|
public String getDeviceName(IPv6Address address) {
|
|
RouterInfo ri=netmap.get(address);
|
|
if(ri!=null) {
|
|
String dn=ri.getDeviceName();
|
|
if(dn!=null&&!dn.isEmpty())
|
|
return dn;
|
|
}
|
|
return null;
|
|
}
|
|
public Map<IPv6Address, List<LinkDirection>> getPaths() {
|
|
return paths;
|
|
}
|
|
public IPv6SegmentRoutingHeader createSegmentList(IPv6Address dest) {
|
|
NetmapDirections directionsx=directions;
|
|
if(directionsx==null) {
|
|
return null;
|
|
}
|
|
Long dn=directionsx.getDirection_airs().get(dest);
|
|
if(dn==null) {
|
|
return null;
|
|
}
|
|
IPv6SegmentRoutingHeader segs=new IPv6SegmentRoutingHeader();
|
|
List<IPv6Address>segments=segs.getAddresses();
|
|
while(true) {
|
|
long idx=directionsx.getDirection()[(int) dn.longValue()];
|
|
if(idx==-1) {
|
|
return null;
|
|
}
|
|
if(idx==dn) {
|
|
segs. resetSegmentPos();
|
|
return segs;
|
|
}
|
|
segments.add(directionsx.getDirection_rias().get(dn.intValue()));
|
|
dn=idx;
|
|
}
|
|
}
|
|
public long getDevicesFound() {
|
|
return netmap.size();
|
|
}
|
|
|
|
private static class HotspotAddressTimer{
|
|
private long putTime=System.nanoTime();
|
|
private long reportTime =System.nanoTime();
|
|
public boolean checkTimeOut() {
|
|
return System.nanoTime()-putTime>HOTSOPT_TIMEOUT;
|
|
}
|
|
public boolean checkReportTime() {
|
|
long cu = System.nanoTime();
|
|
if (cu - reportTime > HOTSOPT_REPORT_INTERVAL) {
|
|
reportTime = cu;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
public void refreshTimeout() {
|
|
putTime=System.nanoTime();
|
|
}
|
|
}
|
|
|
|
private Map<IPv6Address, HotspotAddressTimer> hotspots=new ConcurrentHashMap<>();
|
|
public void putHotspotAddress(IPv6Address iPv6Address) {
|
|
if(true) {
|
|
HotspotAddressTimer hat=hotspots.get(iPv6Address);
|
|
if(hat==null) {
|
|
hotspots.put(iPv6Address,hat= new HotspotAddressTimer());
|
|
}else {
|
|
hat.refreshTimeout();
|
|
}
|
|
if(hat.checkReportTime()) {
|
|
//System.out.println("hotspot address:"+sourceAddress);
|
|
/* try {
|
|
writePacket( new RouterInfoPacket( netmap.get(router.getLocator().getAddress()),false,-1), new InetSocketAddress(iPv6Address.toInet6Address(), DEFAULT_PORT));
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}*/
|
|
}
|
|
}
|
|
}
|
|
private Map<IPv6Address,Long> toIpBandwidth=new ConcurrentHashMap<IPv6Address,Long>();
|
|
|
|
public void updateTotalRequestBandwidth(IPv6Address targetaAddress, Long treq) {
|
|
Objects.requireNonNull(targetaAddress);
|
|
//System.out.println("到"+targetaAddress.getHostAddress()+"请求带宽更新:"+treq);
|
|
if(treq<=0) {
|
|
if(toIpBandwidth.remove(targetaAddress)!=null) {
|
|
noticeUpdate();
|
|
}
|
|
}else {
|
|
Long old=toIpBandwidth.put(targetaAddress, treq);
|
|
if(old==null||old.longValue()!=treq.longValue()) {
|
|
noticeUpdate();
|
|
}
|
|
}
|
|
}
|
|
public IPv6Address getDijkstraPrevNode(IPv6Address text) {
|
|
NetmapDirections directionsx=directions;
|
|
if(directionsx==null)
|
|
return null;
|
|
Long l=directionsx.getDirection_airs().get(text);
|
|
if(l==null)
|
|
return null;
|
|
long number= l;
|
|
long prev= directionsx.getDirection()[(int)number];
|
|
if(prev==-1) {
|
|
return null;
|
|
}
|
|
return directionsx.getDirection_rias().get((int) prev);
|
|
}
|
|
|
|
}
|