754 lines
23 KiB
Java
754 lines
23 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.ByteBuffer;
|
||
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.io.KNEChannels;
|
||
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<>();
|
||
|
||
public Map<IPv6Address, RouterInfo> getNetmap() {
|
||
return netmap;
|
||
}
|
||
|
||
|
||
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 {
|
||
KLALBRoutingProtocolPacket kp=receivePacket();
|
||
|
||
switch(kp.getType()) {
|
||
case KLALBRoutingProtocolPacket.RINFO_REQ:
|
||
RouterInfo rifr=netmap.get(router.getLocator().getAddress());
|
||
if(debug)
|
||
System.out.println("get Request from:"+kp.getFrom());
|
||
if(rifr!=null) {
|
||
writePacket( new RouterInfoPacket( rifr,false,-1), kp.getFrom());
|
||
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( kp.getFrom(), rifp);
|
||
|
||
}
|
||
|
||
}else {
|
||
|
||
if(debug)
|
||
System.out.println("dispose RouterInfo");
|
||
}
|
||
computeShortestPathIfUpdated();
|
||
break;
|
||
case KLALBRoutingProtocolPacket.JSON_DATA:
|
||
JsonDataPacket data=(JsonDataPacket) kp;
|
||
receivers.forEach((v)->{v.accept(kp.getFrom(),data);});
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
} catch (IOException e) {
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
} catch (SocketException e2) {
|
||
e2.printStackTrace();
|
||
}finally {
|
||
if(ds!=null) {
|
||
ds.close();
|
||
}
|
||
}
|
||
}
|
||
private static final ThreadLocal<ByteBuffer> LSDB_RX_BUFFER =
|
||
ThreadLocal.withInitial(() -> ByteBuffer.allocate(65535));
|
||
|
||
private KLALBRoutingProtocolPacket receivePacket() throws IOException {
|
||
// 2. 获取并重置缓冲区
|
||
ByteBuffer bbf = LSDB_RX_BUFFER.get();
|
||
bbf.clear();
|
||
|
||
// 3. 构造 DatagramPacket(注意这里要传底层 array 和 capacity)
|
||
DatagramPacket dgp = new DatagramPacket(bbf.array(), bbf.capacity());
|
||
|
||
// 4. 阻塞接收
|
||
ds.receive(dgp);
|
||
|
||
// 5. 限制缓冲区范围到实际收到的长度
|
||
bbf.limit(dgp.getLength());
|
||
bbf.position(0);
|
||
|
||
// 6. 直接用 KNEChannels 包装 ByteBuffer,避免 ByteArrayInputStream
|
||
KLALBRoutingProtocolPacket kp = KLALBRoutingProtocolPacket.readKLALBPacketFromChannel(
|
||
KNEChannels.newReadableChannel(bbf)
|
||
);
|
||
if(kp!=null)
|
||
kp.setFrom(dgp.getSocketAddress());
|
||
return kp;
|
||
}
|
||
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);
|
||
}
|
||
// 1. 在类成员变量处定义一个 64KB 的 ThreadLocal 缓冲区
|
||
// 注意:这里依然使用 65535,因为你说 LSDB 同步可能需要这么大
|
||
private static final ThreadLocal<ByteBuffer> LSDB_TX_BUFFER =
|
||
ThreadLocal.withInitial(() -> ByteBuffer.allocate(65535));
|
||
|
||
private void writePacket(KLALBRoutingProtocolPacket pkt, SocketAddress dest) throws IOException {
|
||
// 2. 从 ThreadLocal 获取,并清空状态
|
||
ByteBuffer bbf = LSDB_TX_BUFFER.get();
|
||
bbf.clear();
|
||
|
||
// 3. 使用 KNEChannels 绑定到 ByteBuffer,直接写入
|
||
// 这避免了 ByteArrayOutputStream 内部的动态扩容和拷贝
|
||
KLALBRoutingProtocolPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel(bbf), pkt);
|
||
|
||
// 4. 翻转,准备读取数据
|
||
bbf.flip();
|
||
|
||
// 5. 直接拿底层的 byte[] 和真实的 limit 发送
|
||
DatagramPacket dgpx = new DatagramPacket(bbf.array(), bbf.limit());
|
||
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);
|
||
}
|
||
|
||
}
|