forked from KNEMC/KLALB
优化代码,性能暴涨
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
public interface DijkstraAlgorithm extends Runnable{
|
||||
public void setGraph(long[][]pointers,long[][]heap,long startPoint) ;
|
||||
public void run();
|
||||
public long[] getDirection();
|
||||
public long[] getShortest();
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
public class DijstraAlgorithm {
|
||||
//不能设置为Integer.MAX_VALUE,否则两个Integer.MAX_VALUE相加会溢出导致出现负权
|
||||
public static int M = 100000;
|
||||
//定义七个顶点
|
||||
private static char[] vertex = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
//初始化邻接矩阵
|
||||
int[][] matrix = new int[vertex.length][vertex.length];
|
||||
matrix[0] = new int[]{M, 5, 7, M, M, M, 2};
|
||||
matrix[1] = new int[]{5, M, M, 9, M, M, 3};
|
||||
matrix[2] = new int[]{7, M, M, M, 8, M, M};
|
||||
matrix[3] = new int[]{M, 9, M, M, M, 4, M};
|
||||
matrix[4] = new int[]{M, M, 8, M, M, 5, 4};
|
||||
matrix[5] = new int[]{M, M, M, 4, 5, M, 6};
|
||||
matrix[6] = new int[]{2, 3, M, M, 4, 6, M};
|
||||
|
||||
//调用dijstra算法计算最短路径
|
||||
dijstra(matrix, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param matrix:邻接矩阵
|
||||
* @param source:起点
|
||||
*/
|
||||
public static void dijstra(int[][] matrix, int source) {
|
||||
//最短路径长度
|
||||
int[] shortest = new int[matrix.length];
|
||||
//判断该点的最短路径是否求出
|
||||
int[] visited = new int[matrix.length];
|
||||
//存储输出路径
|
||||
String[] path = new String[matrix.length];
|
||||
|
||||
//初始化输出路径
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
path[i] = vertex[source] + "->" + vertex[i];
|
||||
}
|
||||
|
||||
//初始化起点,将起点放入S
|
||||
shortest[source] = 0;
|
||||
visited[source] = 1;
|
||||
|
||||
for (int i = 1; i < matrix.length; i++) { //i从1开始,因为起点已经加入S了
|
||||
int min = M;
|
||||
int index = -1;
|
||||
|
||||
//找出某节点到起点路径最短
|
||||
for (int j = 0; j < matrix.length; j++) {
|
||||
//已经求出最短路径的节点不需要再加入计算并判断加入节点后是否存在更短路径
|
||||
if (visited[j] == 0 && matrix[source][j] < min) {
|
||||
min = matrix[source][j];
|
||||
index = j;
|
||||
}
|
||||
}
|
||||
|
||||
//更新最短路径,标记起点到该节点的最短路径已经求出
|
||||
shortest[index] = min;
|
||||
visited[index] = 1;
|
||||
|
||||
//更新从index跳到其它节点的较短路径
|
||||
for (int m = 0; m < matrix.length; m++) {
|
||||
if (visited[m] == 0 && matrix[source][index] + matrix[index][m] < matrix[source][m]) {
|
||||
matrix[source][m] = matrix[source][index] + matrix[index][m];
|
||||
path[m] = path[index] + "->" + vertex[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//打印最短路径
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
if (i != source) {
|
||||
if (shortest[i] == M) {
|
||||
System.out.println(vertex[source] + "到" + vertex[i] + "不可达");
|
||||
} else {
|
||||
System.out.println(vertex[source] + "到" + vertex[i] + "的最短路径为:" + path[i] + ",最短距离是:" + shortest[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
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;
|
||||
import org.kne.cloud.network.klalb.KLALBPacket;
|
||||
|
||||
public class IPv6SegmentRoutingTLV extends NetworkPacket {
|
||||
public static final int PAD1=0;
|
||||
public static final int PADN=4;
|
||||
public static final int HMAC=5;
|
||||
public static final int SEQS=7;
|
||||
|
||||
private boolean isDefault;
|
||||
|
||||
protected volatile ByteBuffer header;
|
||||
|
||||
private ByteBuffer data;
|
||||
|
||||
public IPv6SegmentRoutingTLV(ByteBuffer header ) {
|
||||
this(header,true);
|
||||
}
|
||||
|
||||
public ByteBuffer getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public IPv6SegmentRoutingTLV(ByteBuffer header ,boolean isDefault ) {
|
||||
super();
|
||||
this.header = header;
|
||||
if(isDefault&&(getType()!=PAD1)) {
|
||||
data=ByteBuffer.allocate(512);
|
||||
}
|
||||
}
|
||||
public IPv6SegmentRoutingTLV(int type) {
|
||||
this(type,true);
|
||||
}
|
||||
public IPv6SegmentRoutingTLV(int type,boolean isDefault) {
|
||||
super();
|
||||
this.header=ByteBuffer.allocate(2);
|
||||
header.put((byte) type);
|
||||
if(isDefault&&(type!=PAD1)) {
|
||||
data=ByteBuffer.allocate(512);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLength() {
|
||||
if(getType()==PAD1)
|
||||
return 1;
|
||||
return header.limit()+(isDefault?data.limit():0);
|
||||
}
|
||||
|
||||
public static IPv6SegmentRoutingTLV readIPv6SegmentRoutingTLVFromChannel(ReadableByteChannel din) throws IOException {
|
||||
ByteBuffer bbf= ByteBuffer.allocate(2);
|
||||
bbf.limit(1);
|
||||
while (bbf.hasRemaining()) {
|
||||
if (din.read(bbf) == -1) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
int type=bbf.get(0)&0xff;
|
||||
IPv6SegmentRoutingTLV rtlv;
|
||||
switch(type) {
|
||||
case PAD1:
|
||||
rtlv=new PAD1SegmentRoutingTLV(bbf);
|
||||
rtlv.readFromChannel(din);
|
||||
return rtlv;
|
||||
case PADN:
|
||||
rtlv=new PADNSegmentRoutingTLV(bbf);
|
||||
rtlv.readFromChannel(din);
|
||||
return rtlv;
|
||||
default:
|
||||
rtlv=new IPv6SegmentRoutingTLV(bbf);
|
||||
rtlv.readFromChannel(din);
|
||||
return rtlv;
|
||||
}
|
||||
}
|
||||
public static void writeIPv6SegmentRoutingTLVToChannel(WritableByteChannel dto,IPv6SegmentRoutingTLV tlv) throws IOException {
|
||||
tlv.writeToChannel(dto);
|
||||
}
|
||||
@Override
|
||||
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
if(isDefault&&(getType()!=PAD1)) {
|
||||
setDataLength(data.limit());
|
||||
}
|
||||
dto.write(header.slice(0,header.limit()));
|
||||
if(isDefault&&(getType()!=PAD1)) {
|
||||
dto.write(data.slice(0, data.limit()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
header.limit(1);
|
||||
while (header.hasRemaining()) {
|
||||
if (din.read(header) == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
int type=getType();
|
||||
if(type!=PAD1) {
|
||||
header.limit(2);
|
||||
while (header.hasRemaining()) {
|
||||
if (din.read(header) == -1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
}
|
||||
header.flip();
|
||||
|
||||
if(isDefault&&(getType()!=PAD1)) {
|
||||
data.clear();
|
||||
data.limit(getDataLength());
|
||||
while(data.hasRemaining()){
|
||||
if(din.read(data)==-1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
data.flip();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needEndPosition() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return header.get(0)&0xff;
|
||||
}
|
||||
public void setType(int type) {
|
||||
header.put(0,(byte) type);
|
||||
}
|
||||
|
||||
public int getDataLength() {
|
||||
return header.get(1)&0xff;
|
||||
}
|
||||
|
||||
public void setDataLength(int dataLength) {
|
||||
header.put(1,(byte) dataLength);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import static org.pcap4j.util.ByteArrays.*;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.pcap4j.packet.IllegalRawDataException;
|
||||
import org.pcap4j.packet.IpV6ExtRoutingPacket.IpV6RoutingData;
|
||||
import org.pcap4j.util.ByteArrays;
|
||||
|
||||
|
||||
public final class IpV6RoutingSRHData implements IpV6RoutingData {
|
||||
|
||||
/** */
|
||||
private static final long serialVersionUID = -7972526977248222954L;
|
||||
|
||||
private final int lastEntry;
|
||||
private final int flags;
|
||||
private final int tag;
|
||||
private final List<Inet6Address> addresses;
|
||||
private final List<SRv6TLV> tlvs;
|
||||
|
||||
/**
|
||||
* A static factory method. This method validates the arguments by {@link
|
||||
* ByteArrays#validateBounds(byte[], int, int)}, which may throw exceptions undocumented here.
|
||||
*
|
||||
* @param rawData rawData
|
||||
* @param offset offset
|
||||
* @param length length
|
||||
* @return a new IpV6RoutingSourceRouteData object.
|
||||
* @throws IllegalRawDataException if parsing the raw data fails.
|
||||
*/
|
||||
public static IpV6RoutingSRHData newInstance(byte[] rawData, int offset, int length)
|
||||
throws IllegalRawDataException {
|
||||
return new IpV6RoutingSRHData(rawData, offset, length);
|
||||
}
|
||||
|
||||
private IpV6RoutingSRHData(byte[] rawData, int offset, int length)
|
||||
throws IllegalRawDataException {
|
||||
|
||||
this.lastEntry = rawData[ offset]&0xff;
|
||||
this.flags=rawData[offset+1]&0xff;
|
||||
this.tag=ByteArrays.getShort(rawData, offset+2);
|
||||
this.addresses = new ArrayList<Inet6Address>();
|
||||
this.tlvs=new ArrayList<>();
|
||||
|
||||
int endv=INT_SIZE_IN_BYTES+(lastEntry+1)*INET6_ADDRESS_SIZE_IN_BYTES;
|
||||
for (int i = INT_SIZE_IN_BYTES; i < endv; i += INET6_ADDRESS_SIZE_IN_BYTES) {
|
||||
addresses.add(ByteArrays.getInet6Address(rawData, i + offset));
|
||||
}
|
||||
for(int itlv=endv;itlv<length;) {
|
||||
int type=rawData[itlv+offset]&0xff;
|
||||
switch(type) {
|
||||
case SRv6TLV.PAD1:
|
||||
itlv++;
|
||||
tlvs.add(new SRv6Pad1TLV());
|
||||
break;
|
||||
case SRv6TLV.PADN:
|
||||
itlv++;
|
||||
int lengthPN=rawData[itlv+offset]&0xff;
|
||||
tlvs.add(new SRv6PadNTLV(lengthPN));
|
||||
itlv+=1+lengthPN;
|
||||
break;
|
||||
case SRv6TLV.SEQS:
|
||||
itlv++;
|
||||
int lengthQTLV=rawData[itlv+offset]&0xff;
|
||||
byte[]rawQTLV=new byte[lengthQTLV];
|
||||
System.arraycopy(rawData, itlv+offset+1, rawQTLV, 0, lengthQTLV);
|
||||
tlvs.add(new SRv6StreamSequenceTLV( lengthQTLV, rawQTLV));
|
||||
itlv+=1+lengthQTLV;
|
||||
break;
|
||||
default:
|
||||
itlv++;
|
||||
int lengthTLV=rawData[itlv+offset]&0xff;
|
||||
byte[]rawTLV=new byte[lengthTLV];
|
||||
System.arraycopy(rawData, itlv+offset+1, rawTLV, 0, lengthTLV);
|
||||
tlvs.add(new SRv6TLV(type, lengthTLV, rawTLV));
|
||||
itlv+=1+lengthTLV;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<SRv6TLV> getTlvs() {
|
||||
return tlvs;
|
||||
}
|
||||
|
||||
public int getLastEntry() {
|
||||
return lastEntry;
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public int getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public List<Inet6Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public IpV6RoutingSRHData(List<Inet6Address> addresses) {
|
||||
this(0,0,addresses,new ArrayList<>());
|
||||
}
|
||||
public IpV6RoutingSRHData(List<Inet6Address> addresses,List<SRv6TLV>tlvs) {
|
||||
this(0,0,addresses,tlvs);
|
||||
}
|
||||
/**
|
||||
* @param reserved reserved
|
||||
* @param addresses addresses
|
||||
*/
|
||||
public IpV6RoutingSRHData(int flags,int tag, List<Inet6Address> addresses,List<SRv6TLV>tlvs) {
|
||||
if (addresses == null) {
|
||||
throw new NullPointerException("addresses must not be null");
|
||||
}
|
||||
this.lastEntry = addresses.size()-1;
|
||||
this.flags=flags;
|
||||
this.tag=tag;
|
||||
this.addresses = new ArrayList<Inet6Address>(addresses);
|
||||
this.tlvs=tlvs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
int tlvsize=0;
|
||||
for (int i = 0; i < tlvs.size(); i++) {
|
||||
tlvsize+=tlvs.get(i).getTotalLength();
|
||||
}
|
||||
return INT_SIZE_IN_BYTES+addresses.size() * INET6_ADDRESS_SIZE_IN_BYTES + tlvsize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getRawData() {
|
||||
byte[] rawData = new byte[length()];
|
||||
rawData[0]=(byte) lastEntry;
|
||||
rawData[1]=(byte) flags;
|
||||
rawData[2]=(byte) (tag>>8);
|
||||
rawData[3]=(byte) tag;
|
||||
;
|
||||
int i = INT_SIZE_IN_BYTES;
|
||||
for ( Iterator<Inet6Address> iter = addresses.iterator(); iter.hasNext(); i += INET6_ADDRESS_SIZE_IN_BYTES) {
|
||||
System.arraycopy(
|
||||
ByteArrays.toByteArray(iter.next()), 0, rawData, i, INET6_ADDRESS_SIZE_IN_BYTES);
|
||||
}
|
||||
for (int j = 0; j < tlvs.size(); j++) {
|
||||
SRv6TLV srt=tlvs.get(j);
|
||||
switch(srt.getType()) {
|
||||
case SRv6TLV.PAD1:
|
||||
rawData[i++]=(byte) srt.getType();
|
||||
break;
|
||||
case SRv6TLV.PADN:
|
||||
rawData[i++]=(byte) srt.getType();
|
||||
int plth=srt.getLength();
|
||||
rawData[i++]=(byte) plth;
|
||||
i+=plth;
|
||||
break;
|
||||
default:
|
||||
rawData[i++]=(byte) srt.getType();
|
||||
int dlth=srt.getLength();
|
||||
rawData[i++]=(byte) dlth;
|
||||
System.arraycopy(srt.getValue(), 0, rawData, i, dlth);
|
||||
i+=dlth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rawData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[lastentry: ").append(lastEntry).append("][flags: ").append(flags).append("][tag: ").append(tag).append("] [addresses:");
|
||||
for (Inet6Address addr : addresses) {
|
||||
sb.append(" ").append(addr);
|
||||
}
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (!this.getClass().isInstance(obj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IpV6RoutingSRHData other = (IpV6RoutingSRHData) obj;
|
||||
return lastEntry == other.lastEntry&&flags==other.flags&&tag==other.tag && addresses.equals(other.addresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
result = 31 * result + lastEntry;
|
||||
result = 31 * result + flags;
|
||||
result = 31 * result + tag;
|
||||
result = 31 * result + addresses.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,575 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.BindException;
|
||||
import java.net.DatagramPacket;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.Channels;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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.locks.ReentrantLock;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
import org.kne.cloud.network.ipv6.Neighbor;
|
||||
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.cloud.network.scanner.InetAddressRange;
|
||||
|
||||
public class KLALBRoutingProtocol extends Thread{
|
||||
|
||||
private static final boolean debug = false;
|
||||
|
||||
private Map<Inet6Address, RouterInfo> netmap=new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
private volatile Map<Inet6Address,Long>addresses;
|
||||
|
||||
private volatile Map<Inet6Address, Set<LinkDirection>> paths;
|
||||
|
||||
public static final int DEFAULT_PORT=1001;
|
||||
|
||||
public static final long HOTSOPT_TIMEOUT = 1000000000;
|
||||
|
||||
public static final int HOTSOPT_REPORT_INTERVAL = 100000000;
|
||||
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();
|
||||
@Override
|
||||
public void run() {
|
||||
Thread.currentThread().setName("KLALB路由协议接收线程");
|
||||
getSelfRouterInfo();
|
||||
DatagramSocket ds = null;
|
||||
try{
|
||||
ds=new DatagramSocket(new InetSocketAddress(router.getLocator().getAddress(), DEFAULT_PORT) );
|
||||
DatagramSocket ds2=ds;
|
||||
new Thread(()->{
|
||||
Thread.currentThread().setName("KLALB路由协议接收线程");
|
||||
|
||||
while(true) {
|
||||
try {
|
||||
/*List<NetworkLink>links=router.getLinkTabel();
|
||||
Object[] nls=links.toArray();
|
||||
byte[]to=createLinkStatePacket(nls);
|
||||
DatagramPacket dgp=new DatagramPacket(to,to.length);
|
||||
|
||||
for(int i=0;i<nls.length;i++) {
|
||||
NetworkLink nl=(NetworkLink) nls[i];
|
||||
if(!nl.isLoopBack()) {
|
||||
Set<Inet6Address>neis=nl.discoverNeighbors();
|
||||
for (Iterator<Inet6Address> iteratorx = neis.iterator(); iteratorx.hasNext();) {
|
||||
Inet6Address addresses = (Inet6Address) iteratorx.next();
|
||||
dgp.setAddress(addresses);
|
||||
dgp.setPort(DEFAULT_PORT);
|
||||
ds2.send(dgp);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
RouterInfo slf= getSelfRouterInfo();
|
||||
RouterInfo oslf=netmap.put(slf.getLocator().getAddress(), slf);
|
||||
noticeUpdate();
|
||||
if(oslf==null||(!slf.equals(oslf))) {
|
||||
//System.out.println("change:"+oslf+"\n"+slf);
|
||||
long cur=System.nanoTime();
|
||||
if(cur-floodTimer2>5000000000L) {
|
||||
//System.out.println("update10");
|
||||
floodTimer2=cur;
|
||||
floodPacket(ds2, null, new RouterInfoPacket(slf,true));
|
||||
}
|
||||
}else {
|
||||
long cur=System.nanoTime();
|
||||
if(cur-floodTimer>60000000000L) {
|
||||
//System.out.println("update60");
|
||||
floodTimer=cur;
|
||||
floodPacket(ds2, null, new RouterInfoPacket(slf,true));
|
||||
}
|
||||
}
|
||||
Set<Inet6Address> requestSet=new HashSet<>();
|
||||
for (Iterator<Entry<Inet6Address, RouterInfo>> iterator = netmap.entrySet().iterator(); iterator.hasNext();) {
|
||||
Entry<Inet6Address, RouterInfo> type = (Entry<Inet6Address, RouterInfo>) iterator.next();
|
||||
RouterInfo val=type.getValue();
|
||||
if(val.checkTimeOut()) {
|
||||
iterator.remove();
|
||||
noticeUpdate();
|
||||
}
|
||||
Set<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();
|
||||
|
||||
for (Iterator<Inet6Address> iterator = requestSet.iterator(); iterator.hasNext();) {
|
||||
Inet6Address inet6Address = (Inet6Address) iterator.next();
|
||||
byte[]to=new byte[] {0};
|
||||
DatagramPacket dgp=new DatagramPacket(to,to.length);
|
||||
dgp.setAddress(inet6Address);
|
||||
dgp.setPort(DEFAULT_PORT);
|
||||
if(debug)
|
||||
System.out.println("Request:"+inet6Address);
|
||||
sendlock.lock();
|
||||
try {
|
||||
ds2.send(dgp);
|
||||
}catch(SocketException e) {
|
||||
System.out.println("Send failed:"+dgp.getAddress());
|
||||
}finally {
|
||||
sendlock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Iterator<Entry<Inet6Address, HotspotAddressTimer>> iterator = hotspots.entrySet().iterator(); iterator.hasNext();) {
|
||||
Entry<Inet6Address, HotspotAddressTimer> type = (Entry<Inet6Address, HotspotAddressTimer>) iterator.next();
|
||||
if(type.getValue().checkReportTime()) {
|
||||
//System.out.println("hotspot address:"+type.getKey());
|
||||
writePacket(ds2, new RouterInfoPacket( netmap.get(router.getLocator().getAddress()),false), new InetSocketAddress(type.getKey(), DEFAULT_PORT));
|
||||
}
|
||||
if(type.getValue().checkTimeOut()) {
|
||||
iterator.remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Thread.sleep(1);
|
||||
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}catch (IOException e1) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
while(true) {
|
||||
|
||||
try {
|
||||
byte[]ca=new byte[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));
|
||||
|
||||
//System.out.println(kp);
|
||||
switch(kp.getType()) {
|
||||
case KLALBRoutingProtocolPacket.RINFO_REQ:
|
||||
RouterInfo rifr=netmap.get(router.getLocator().getAddress());
|
||||
if(rifr!=null)
|
||||
writePacket(ds, new RouterInfoPacket( rifr,false), dgp.getSocketAddress());
|
||||
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(ds, dgp.getSocketAddress(), rifp);
|
||||
|
||||
}
|
||||
|
||||
}else {
|
||||
|
||||
if(debug)
|
||||
System.out.println("dispose RouterInfo");
|
||||
}
|
||||
computeShortestPathIfUpdated();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
} catch (SocketException e2) {
|
||||
e2.printStackTrace();
|
||||
}finally {
|
||||
if(ds!=null) {
|
||||
ds.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void floodPacket(DatagramSocket ds,SocketAddress except,KLALBRoutingProtocolPacket rifp) throws IOException {
|
||||
List<IPv6NetworkLink>links=router.getLinkTabel();
|
||||
Object[] nls=links.toArray();
|
||||
for(int i=0;i<nls.length;i++) {
|
||||
IPv6NetworkLink nl=(IPv6NetworkLink) nls[i];
|
||||
if(!nl.isLoopBack()) {
|
||||
List<Neighbor>neis=nl.getNeighborsInfo();
|
||||
for (Iterator<Neighbor> iteratorx = neis.iterator(); iteratorx.hasNext();) {
|
||||
Neighbor addresses = (Neighbor) iteratorx.next();
|
||||
InetSocketAddress isa=new InetSocketAddress(addresses.getLocator().getAddress(),DEFAULT_PORT);
|
||||
if(!isa.equals(except)) {
|
||||
writePacket(ds, rifp, isa);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void writePacket(DatagramSocket ds,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<Inet6Address> rias,
|
||||
Map<Inet6Address, Long> direction_airs) {
|
||||
super();
|
||||
this.direction = direction;
|
||||
this.direction_rias = rias;
|
||||
this.direction_airs = direction_airs;
|
||||
}
|
||||
|
||||
private long[] direction;
|
||||
|
||||
private List<Inet6Address> direction_rias;
|
||||
|
||||
private Map<Inet6Address, Long> direction_airs;
|
||||
|
||||
public long[] getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
public List<Inet6Address> getDirection_rias() {
|
||||
return direction_rias;
|
||||
}
|
||||
|
||||
public Map<Inet6Address, 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<Inet6Address, RouterInfo>> s=netmap.entrySet();
|
||||
Map<Inet6Address,Long>airs=new HashMap<>();
|
||||
|
||||
List<Inet6Address>rias=new ArrayList<>();
|
||||
|
||||
Map<Inet6Address,Set< LinkDirection>>paths=new HashMap<>();
|
||||
long number=0;
|
||||
for (Iterator<Entry<Inet6Address, RouterInfo>> iterator = s.iterator(); iterator.hasNext();) {
|
||||
Entry<Inet6Address, RouterInfo> entry = (Entry<Inet6Address, RouterInfo>) iterator.next();
|
||||
if(!airs.containsKey(entry.getKey())) {
|
||||
airs.put(entry.getKey(),number);
|
||||
rias.add( entry.getKey());
|
||||
number++;
|
||||
}
|
||||
Set<NeighborInfo> ni= entry.getValue().getNeighborAddresses();
|
||||
for (Iterator<NeighborInfo> iterator2 = ni.iterator(); iterator2.hasNext();) {
|
||||
NeighborInfo neighborInfo = (NeighborInfo) iterator2.next();
|
||||
Inet6Address ias2=neighborInfo.getLocator().getAddress();
|
||||
if(!airs.containsKey(ias2)) {
|
||||
airs.put(ias2,number);
|
||||
rias.add( ias2);
|
||||
number++;
|
||||
}
|
||||
Set<LinkDirection>lp1=paths.get(entry.getKey());
|
||||
if(lp1==null) {
|
||||
paths.put(entry.getKey(), lp1=new HashSet<>());
|
||||
}
|
||||
lp1.add(new LinkDirection(neighborInfo.getLocal(),neighborInfo.getNeighbor(),entry.getKey(), ias2, neighborInfo.getUploadDelay(),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.getDownloadSpeed(),neighborInfo.getDownloadSpeedMax()));
|
||||
}
|
||||
}
|
||||
|
||||
long[][]pointers=new long[(int) airs.size()][2];
|
||||
long heappos=0;
|
||||
long linknumber=0;
|
||||
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;
|
||||
InetAddress ia=rias.get((int) i);
|
||||
Set<LinkDirection>lks=paths.get(ia);
|
||||
if(lks!=null)
|
||||
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();
|
||||
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 Inet6AddressGroup fromAddress;
|
||||
private Inet6AddressGroup toAddress;
|
||||
private Inet6Address fromLocator;
|
||||
private Inet6Address toLocator;
|
||||
private long delay;
|
||||
private long speed;
|
||||
public long getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
private long bandwidth;
|
||||
private long usedBandwidth=0;
|
||||
public Inet6AddressGroup getFromAddress() {
|
||||
return fromAddress;
|
||||
}
|
||||
public Inet6AddressGroup getToAddress() {
|
||||
return toAddress;
|
||||
}
|
||||
public long getDelay() {
|
||||
return delay;
|
||||
}
|
||||
public long getBandwidth() {
|
||||
return bandwidth;
|
||||
}
|
||||
public LinkDirection(Inet6AddressGroup fromAddress, Inet6AddressGroup toAddress, Inet6Address fromLocator,
|
||||
Inet6Address toLocator,long delay,long speed, long bandwidth) {
|
||||
super();
|
||||
this.fromAddress = fromAddress;
|
||||
this.toAddress = toAddress;
|
||||
this.fromLocator = fromLocator;
|
||||
this.toLocator = toLocator;
|
||||
this.delay = delay;
|
||||
this.speed=speed;
|
||||
this.bandwidth = bandwidth;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LinkDirection [fromAddress=" + fromAddress + ", toAddress=" + toAddress + ", fromLocator="
|
||||
+ fromLocator + ", toLocator=" + toLocator + ", delay=" + delay + ", speed=" + speed
|
||||
+ ", bandwidth=" + bandwidth + ", usedBandwidth=" + usedBandwidth + "]";
|
||||
}
|
||||
public Inet6Address 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 Inet6Address 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());
|
||||
ri.setLocator(router.getLocator());
|
||||
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 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 SpeedAndTrafficMonitorData) {
|
||||
uploadspeed=((SpeedAndTrafficMonitorData) md).getOutSpeed();
|
||||
downloadspeed=((SpeedAndTrafficMonitorData) md).getInSpeed();
|
||||
if(md instanceof SpeedAndTrafficMonitorDataImpl) {
|
||||
SpeedAndTrafficMonitorDataImpl smd=(SpeedAndTrafficMonitorDataImpl) md;
|
||||
uploadspeedmax=smd.getOutSpeedMax2();
|
||||
downloadspeedmax=smd.getInSpeedMax2();
|
||||
}
|
||||
}
|
||||
}
|
||||
ri.getNeighborAddresses().add(new NeighborInfo(nl.getAddressGroup(),addresses.getAddress(),addresses.getLocator(),updelay ,downdelay ,uploadspeed ,downloadspeed,uploadspeedmax ,downloadspeedmax));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
//if(debug)
|
||||
//System.out.println(ri);
|
||||
return ri;
|
||||
}
|
||||
|
||||
public Map<Inet6Address, Long> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
public Map<Inet6Address, Set<LinkDirection>> getPaths() {
|
||||
return paths;
|
||||
}
|
||||
public List<Inet6Address> createSegmentList(Inet6Address dest) {
|
||||
NetmapDirections directionsx=directions;
|
||||
if(directionsx==null) {
|
||||
return null;
|
||||
}
|
||||
Long dn=directionsx.getDirection_airs().get(dest);
|
||||
if(dn==null) {
|
||||
return null;
|
||||
}
|
||||
List<Inet6Address>segments=new ArrayList<>();
|
||||
while(true) {
|
||||
long idx=directionsx.getDirection()[(int) dn.longValue()];
|
||||
if(idx==-1) {
|
||||
return null;
|
||||
}
|
||||
if(idx==dn) {
|
||||
return segments;
|
||||
}
|
||||
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<Inet6Address, HotspotAddressTimer> hotspots=new ConcurrentHashMap<>();
|
||||
public void putHotspotAddress(Inet6Address sourceAddress) {
|
||||
HotspotAddressTimer hat=hotspots.get(sourceAddress);
|
||||
if(hat==null) {
|
||||
hotspots.put(sourceAddress, new HotspotAddressTimer());
|
||||
}else {
|
||||
hat.refreshTimeout();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
|
||||
public abstract class KLALBRoutingProtocolPacket extends NetworkPacket {
|
||||
public static final int RINFO_REQ=0;
|
||||
public static final int RINFO=1;
|
||||
|
||||
private static final int HEADER_CAPACITY = 32;
|
||||
|
||||
|
||||
//public static final ByteArrayPool dataarraypool=new ByteArrayPool(5000, 8192);
|
||||
|
||||
protected volatile ByteBuffer header;
|
||||
|
||||
|
||||
|
||||
protected KLALBRoutingProtocolPacket(ByteBuffer header) {
|
||||
super();
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public KLALBRoutingProtocolPacket(int type) {
|
||||
super();
|
||||
header=NetworkPacket.databufferpool_40.borrow();
|
||||
header.put((byte) type);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLALBRoutingProtocolPacket [type=" + getType() + "]";
|
||||
}
|
||||
public int getType() {
|
||||
return header.get(0)&0xff;
|
||||
}
|
||||
|
||||
private long sndtime,rcvtime;
|
||||
|
||||
|
||||
|
||||
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
sndtime=System.nanoTime();
|
||||
dto.write(header.slice(0, (int) getHeaderSize()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needEndPosition() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void readFromChannel(ReadableByteChannel din,long length) throws IOException {
|
||||
rcvtime=System.nanoTime();
|
||||
//System.out.println(this+" "+getHeaderSize());
|
||||
header.limit((int) getHeaderSize());
|
||||
while(header.hasRemaining()){
|
||||
if(din.read(header)==-1) {
|
||||
throw new EOFException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected long getHeaderSize() {
|
||||
return 1;
|
||||
}
|
||||
public long getSndtime() {
|
||||
return sndtime;
|
||||
}
|
||||
public long getRcvtime() {
|
||||
return rcvtime;
|
||||
}
|
||||
public long getLength() {
|
||||
return getHeaderSize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected ByteBuffer getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
super.dispose();
|
||||
/* ByteBuffer headerx=header;
|
||||
header=null;
|
||||
KLALBRoutingProtocolPacket.databufferpool_40.back(headerx);*/
|
||||
}
|
||||
|
||||
public static KLALBRoutingProtocolPacket readKLALBPacketFromStream(DataInputStream in) throws IOException {
|
||||
return readKLALBPacketFromChannel(Channels.newChannel(in));
|
||||
}
|
||||
|
||||
public static KLALBRoutingProtocolPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException {
|
||||
while(true) {
|
||||
ByteBuffer bb=databufferpool_40.borrow();
|
||||
bb.limit(1);
|
||||
while(bb.hasRemaining()){
|
||||
if(in.read(bb)==-1) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
int type=bb.get(0);
|
||||
bb.limit(bb.capacity());
|
||||
|
||||
KLALBRoutingProtocolPacket klp;
|
||||
switch(type) {
|
||||
case RINFO_REQ:
|
||||
klp=new RouterInfoRequestPacket(bb);
|
||||
klp.readFromChannel(in);
|
||||
return klp;
|
||||
case RINFO:
|
||||
klp=new RouterInfoPacket(bb);
|
||||
klp.readFromChannel(in);
|
||||
return klp;
|
||||
}
|
||||
//throw new StreamCorruptedException("unknown package type:"+type);
|
||||
System.err.println("ignore unknown KLALBRoutingProtocolPacket type:"+type);
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeKLALBPacketToStream(DataOutputStream out,KLALBRoutingProtocolPacket klb) throws IOException {
|
||||
writeKLALBPacketToChannel(Channels.newChannel(out),klb);
|
||||
}
|
||||
public static void writeKLALBPacketToChannel(WritableByteChannel writableByteChannel,KLALBRoutingProtocolPacket klb) throws IOException {
|
||||
klb.writeToChannel(writableByteChannel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.Serializable;
|
||||
import java.net.Inet6Address;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
|
||||
public class NeighborInfo implements Serializable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NeighborInfo [local=" + local + ", neighbor=" + neighbor + ", locator=" + locator + ", uploadDelay="
|
||||
+ uploadDelay + ", downloadDelay=" + downloadDelay + ", uploadSpeed=" + uploadSpeed + ", downloadSpeed="
|
||||
+ downloadSpeed + ", uploadSpeedMax=" + uploadSpeedMax + ", downloadSpeedMax=" + downloadSpeedMax + "]";
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Inet6AddressGroup local;
|
||||
private Inet6AddressGroup neighbor;
|
||||
private Inet6AddressGroup locator;
|
||||
public NeighborInfo(Inet6AddressGroup local,Inet6AddressGroup neighbor,Inet6AddressGroup locator, long uploadDelay, long downloadDelay, long uploadSpeed, long downloadSpeed, long uploadspeedmax, long downloadspeedmax) {
|
||||
super();
|
||||
this.local=local;
|
||||
this.neighbor = neighbor;
|
||||
this.locator=locator;
|
||||
this.uploadDelay = uploadDelay;
|
||||
this.downloadDelay = downloadDelay;
|
||||
this.uploadSpeed = uploadSpeed;
|
||||
this.downloadSpeed = downloadSpeed;
|
||||
this.uploadSpeedMax=uploadspeedmax;
|
||||
this.downloadSpeedMax=downloadspeedmax;
|
||||
}
|
||||
public NeighborInfo() {
|
||||
}
|
||||
private long uploadDelay;
|
||||
private long downloadDelay;
|
||||
private long uploadSpeed;
|
||||
private long downloadSpeed;
|
||||
private long uploadSpeedMax;
|
||||
private long downloadSpeedMax;
|
||||
public Inet6AddressGroup getNeighbor() {
|
||||
return neighbor;
|
||||
}
|
||||
public void setNeighbor(Inet6AddressGroup neighbor) {
|
||||
this.neighbor = neighbor;
|
||||
}
|
||||
public long getUploadDelay() {
|
||||
return uploadDelay;
|
||||
}
|
||||
public void setUploadDelay(long uploadDelay) {
|
||||
this.uploadDelay = uploadDelay;
|
||||
}
|
||||
public long getDownloadDelay() {
|
||||
return downloadDelay;
|
||||
}
|
||||
public void setDownloadDelay(long downloadDelay) {
|
||||
this.downloadDelay = downloadDelay;
|
||||
}
|
||||
public long getUploadSpeed() {
|
||||
return uploadSpeed;
|
||||
}
|
||||
public void setUploadSpeed(long uploadSpeed) {
|
||||
this.uploadSpeed = uploadSpeed;
|
||||
}
|
||||
public long getDownloadSpeed() {
|
||||
return downloadSpeed;
|
||||
}
|
||||
public long getUploadSpeedMax() {
|
||||
return uploadSpeedMax;
|
||||
}
|
||||
public void setUploadSpeedMax(long uploadSpeedMax) {
|
||||
this.uploadSpeedMax = uploadSpeedMax;
|
||||
}
|
||||
public long getDownloadSpeedMax() {
|
||||
return downloadSpeedMax;
|
||||
}
|
||||
public void setDownloadSpeedMax(long downloadSpeedMax) {
|
||||
this.downloadSpeedMax = downloadSpeedMax;
|
||||
}
|
||||
public void setDownloadSpeed(long downloadSpeed) {
|
||||
this.downloadSpeed = downloadSpeed;
|
||||
}
|
||||
public Inet6AddressGroup getLocal() {
|
||||
return local;
|
||||
}
|
||||
public void setLocal(Inet6AddressGroup local) {
|
||||
this.local = local;
|
||||
}
|
||||
public Inet6AddressGroup getLocator() {
|
||||
return locator;
|
||||
}
|
||||
public void setLocator(Inet6AddressGroup locator) {
|
||||
this.locator = locator;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(local, locator, neighbor);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
NeighborInfo other = (NeighborInfo) obj;
|
||||
return Objects.equals(local, other.local) && Objects.equals(locator, other.locator)
|
||||
&& Objects.equals(neighbor, other.neighbor);
|
||||
}
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
local.writeToStream(out);
|
||||
neighbor.writeToStream(out);
|
||||
locator.writeToStream(out);
|
||||
out.writeLong(uploadDelay);
|
||||
out.writeLong(downloadDelay);
|
||||
out.writeLong(uploadSpeed);
|
||||
out.writeLong(downloadSpeed);
|
||||
out.writeLong(uploadSpeedMax);
|
||||
out.writeLong(downloadSpeedMax);
|
||||
}
|
||||
|
||||
public void readFromStream(DataInputStream in) throws IOException {
|
||||
local=new Inet6AddressGroup(in);
|
||||
neighbor=new Inet6AddressGroup( in);
|
||||
locator=new Inet6AddressGroup(in);
|
||||
uploadDelay=in.readLong();
|
||||
downloadDelay=in.readLong();
|
||||
uploadSpeed=in.readLong();
|
||||
downloadSpeed=in.readLong();
|
||||
uploadSpeedMax=in.readLong();
|
||||
downloadSpeedMax=in.readLong();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class PAD1SegmentRoutingTLV extends IPv6SegmentRoutingTLV {
|
||||
|
||||
public PAD1SegmentRoutingTLV(int type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
public PAD1SegmentRoutingTLV(ByteBuffer klalbHeader) {
|
||||
super(klalbHeader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PAD1SegmentRoutingTLV []";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
|
||||
public class PADNSegmentRoutingTLV extends IPv6SegmentRoutingTLV {
|
||||
public PADNSegmentRoutingTLV(ByteBuffer klalbHeader) {
|
||||
super(klalbHeader);
|
||||
}
|
||||
|
||||
public PADNSegmentRoutingTLV(int type) {
|
||||
super(type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
|
||||
super.writeToChannel(dto);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
super.readFromChannel(din, length);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.pcap4j.packet.IpV6Packet;
|
||||
|
||||
public interface PacketConsumer {
|
||||
public void accept(IPv6Packet packx)throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.pcap4j.packet.IpV6Packet;
|
||||
import org.pcap4j.packet.TcpPacket;
|
||||
|
||||
public class PacketReorder {
|
||||
public PacketReorder(long sequenceNumber) {
|
||||
this.sequenceNumber =sequenceNumber;
|
||||
}
|
||||
private ReentrantLock rlock=new ReentrantLock();
|
||||
private List<TcpPacketEntry> tcps=new ArrayList<>();
|
||||
private volatile long sequenceNumber;
|
||||
public List<TcpPacketEntry> getTcps() {
|
||||
return tcps;
|
||||
}
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
public static class TcpPacketEntry{
|
||||
private IPv6Packet packet;
|
||||
private long sequenceNumber;
|
||||
private long addtime=System.nanoTime();
|
||||
|
||||
public TcpPacketEntry(IPv6Packet packet, long sequenceNumber) {
|
||||
super();
|
||||
this.packet = packet;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
}
|
||||
public IPv6Packet getPacket() {
|
||||
return packet;
|
||||
}
|
||||
public long getAddtime() {
|
||||
return addtime;
|
||||
}
|
||||
public boolean checkTimeOut() {
|
||||
return System.nanoTime()-addtime>10000000L;
|
||||
}
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
|
||||
}
|
||||
public void sortPackets(IPv6Packet pack,long seq, PacketConsumer packconsumer) throws IOException {
|
||||
rlock.lock();
|
||||
try {
|
||||
//System.out.println("包序号:"+seq);
|
||||
//System.out.println("当前序号:"+sequenceNumber);
|
||||
if(seq<sequenceNumber) {
|
||||
packconsumer.accept(pack);
|
||||
}else {
|
||||
loop: do {
|
||||
for(int i=0;i<tcps.size();i++) {
|
||||
TcpPacketEntry tpe=tcps.get(i);
|
||||
if(seq<tpe.getSequenceNumber()) {
|
||||
tcps.add(i, new TcpPacketEntry(pack, seq));
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
tcps.add(new TcpPacketEntry(pack, seq));
|
||||
}while(false);
|
||||
}
|
||||
for (Iterator<TcpPacketEntry> iterator = tcps.iterator(); iterator.hasNext();) {
|
||||
TcpPacketEntry tcpPacketEntry = (TcpPacketEntry) iterator.next();
|
||||
if(tcpPacketEntry.getSequenceNumber()==sequenceNumber) {
|
||||
//System.out.println(" 排序:"+tcpPacketEntry.getSequenceNumber());
|
||||
iterator.remove();
|
||||
sequenceNumber++;
|
||||
packconsumer.accept(pack);
|
||||
}else if(tcpPacketEntry.getSequenceNumber()<sequenceNumber) {
|
||||
iterator.remove();
|
||||
packconsumer.accept(pack);
|
||||
}else if(tcpPacketEntry.checkTimeOut()){
|
||||
//System.out.println(" 超时:"+tcpPacketEntry.getSequenceNumber());
|
||||
iterator.remove();
|
||||
sequenceNumber=tcpPacketEntry.getSequenceNumber()+1;
|
||||
packconsumer.accept(pack);
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
rlock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.Serializable;
|
||||
import java.net.Inet6Address;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
|
||||
public class RouterInfo implements Serializable{
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Inet6AddressGroup locator;
|
||||
public Inet6AddressGroup getLocator() {
|
||||
return locator;
|
||||
}
|
||||
public void setLocator(Inet6AddressGroup locator) {
|
||||
this.locator = locator;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(locator, neighborAddresses);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
RouterInfo other = (RouterInfo) obj;
|
||||
return Objects.equals(locator, other.locator) && Objects.equals(neighborAddresses, other.neighborAddresses);
|
||||
}
|
||||
private Set<NeighborInfo> neighborAddresses=new HashSet<>();
|
||||
private long createTime;
|
||||
|
||||
|
||||
public long getCreateTime() {
|
||||
return createTime;
|
||||
}
|
||||
private static final long INFO_UPDATETIME=10000000000L;
|
||||
private static final long INFO_TIMEOUT=20000000000L;
|
||||
private long putTime=System.nanoTime();
|
||||
public boolean checkUpdateTime() {
|
||||
return System.nanoTime()-putTime>INFO_UPDATETIME;
|
||||
}
|
||||
|
||||
public boolean checkTimeOut() {
|
||||
return System.nanoTime()-putTime>INFO_TIMEOUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RINFO [locator=" + locator + ", neighborAddresses=" + neighborAddresses + ", putTime=" + putTime
|
||||
+ "]";
|
||||
}
|
||||
public Set<NeighborInfo> getNeighborAddresses() {
|
||||
return neighborAddresses;
|
||||
}
|
||||
|
||||
public RouterInfo( long createTime) {
|
||||
this.createTime = createTime;
|
||||
}
|
||||
public RouterInfo() {
|
||||
}
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
locator.writeToStream(out);
|
||||
out.writeLong(createTime);
|
||||
out.writeInt(neighborAddresses.size());
|
||||
for (Iterator iterator = neighborAddresses.iterator(); iterator.hasNext();) {
|
||||
NeighborInfo neighborInfo = (NeighborInfo) iterator.next();
|
||||
neighborInfo.writeToStream(out);
|
||||
}
|
||||
}
|
||||
|
||||
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
writeToStream(new DataOutputStream( Channels.newOutputStream(dto)));
|
||||
}
|
||||
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
readFromStream(new DataInputStream(Channels.newInputStream(din)));
|
||||
}
|
||||
public void readFromStream(DataInputStream in) throws IOException {
|
||||
locator=new Inet6AddressGroup(in);
|
||||
createTime=in.readLong();
|
||||
int size=in.readInt();
|
||||
neighborAddresses=new HashSet<>(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
NeighborInfo nif=new NeighborInfo();
|
||||
nif.readFromStream(in);
|
||||
neighborAddresses.add(nif);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.Externalizable;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInput;
|
||||
import java.io.ObjectOutput;
|
||||
import java.io.Serializable;
|
||||
import java.net.Inet6Address;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
|
||||
public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Serializable{
|
||||
|
||||
public RouterInfoPacket(RouterInfo routerInfo, boolean flood) {
|
||||
super(RINFO);
|
||||
getHeader().put(1,(byte) (flood?1:0));
|
||||
this.rinfo=routerInfo;
|
||||
}
|
||||
protected RouterInfoPacket(ByteBuffer bb) {
|
||||
super(bb);
|
||||
}
|
||||
|
||||
private RouterInfo rinfo;
|
||||
|
||||
public boolean isFlood() {
|
||||
return (getHeader().get(1)&1)==1;
|
||||
}
|
||||
|
||||
public RouterInfo getRinfo() {
|
||||
return rinfo;
|
||||
}
|
||||
@Override
|
||||
protected long getHeaderSize() {
|
||||
return super.getHeaderSize()+1;
|
||||
}
|
||||
@Override
|
||||
public long getLength() {
|
||||
return super.getLength();
|
||||
}
|
||||
public void setRinfo(RouterInfo rinfo) {
|
||||
this.rinfo = rinfo;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return rinfo.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
super.writeToChannel(dto);
|
||||
rinfo.writeToChannel(dto);
|
||||
}
|
||||
@Override
|
||||
protected void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
super.readFromChannel(din, length);
|
||||
rinfo=new RouterInfo();
|
||||
rinfo.readFromChannel(din, length);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class RouterInfoRequestPacket extends KLALBRoutingProtocolPacket {
|
||||
|
||||
protected RouterInfoRequestPacket(ByteBuffer header) {
|
||||
super(header);
|
||||
}
|
||||
|
||||
public RouterInfoRequestPacket() {
|
||||
super(RINFO_REQ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RINFO_REQ";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
public class SRv6Pad1TLV extends SRv6TLV {
|
||||
|
||||
public SRv6Pad1TLV() {
|
||||
super(SRv6TLV.PAD1, 0, null);
|
||||
|
||||
}
|
||||
public String toString() {
|
||||
return "PAD1";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
public class SRv6PadNTLV extends SRv6TLV {
|
||||
|
||||
public SRv6PadNTLV(int length) {
|
||||
super(SRv6TLV.PADN, length, null);
|
||||
|
||||
}
|
||||
public String toString() {
|
||||
return "PADN:"+getLength();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,569 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
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.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.acclerate.FastLib;
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.ipv6.FlowSession;
|
||||
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6DestinationHeader;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6ExtHeader;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6Payload;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6RoutingHeader;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader;
|
||||
import org.kne.cloud.network.ipv6.IPv6TUNLoopbackNetworkLink;
|
||||
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.klalb.BindableKLALBPacketConsumer;
|
||||
import org.kne.cloud.network.klalb.KLALBController;
|
||||
import org.kne.cloud.network.klalb.KLALBRemoteLine;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
|
||||
import org.kne.cloud.network.tun.TUNNetworkDevice;
|
||||
import org.kne.concurrent.HighPerformanceExecutor;
|
||||
import org.kne.io.KNEChannels;
|
||||
import org.pcap4j.packet.IcmpV6CommonPacket;
|
||||
import org.pcap4j.packet.IcmpV6TimeExceededPacket;
|
||||
import org.pcap4j.packet.IllegalRawDataException;
|
||||
import org.pcap4j.packet.IpV6ExtRoutingPacket;
|
||||
import org.pcap4j.packet.IpV6ExtRoutingPacket.IpV6ExtRoutingHeader;
|
||||
import org.pcap4j.packet.IpV6Packet;
|
||||
import org.pcap4j.packet.IpV6Packet.Builder;
|
||||
import org.pcap4j.packet.IpV6RoutingSourceRouteData;
|
||||
import org.pcap4j.packet.IpV6SimpleFlowLabel;
|
||||
import org.pcap4j.packet.IpV6SimpleTrafficClass;
|
||||
import org.pcap4j.packet.Packet;
|
||||
import org.pcap4j.packet.Packet.Header;
|
||||
import org.pcap4j.packet.TcpPacket;
|
||||
import org.pcap4j.packet.TcpPacket.TcpHeader;
|
||||
import org.pcap4j.packet.UnknownPacket;
|
||||
import org.pcap4j.packet.namednumber.IcmpV6Code;
|
||||
import org.pcap4j.packet.namednumber.IcmpV6Type;
|
||||
import org.pcap4j.packet.namednumber.IpNumber;
|
||||
import org.pcap4j.packet.namednumber.IpV6RoutingType;
|
||||
import org.pcap4j.packet.namednumber.IpVersion;
|
||||
|
||||
import com.google.gson.internal.Pair;
|
||||
|
||||
public class SRv6Router {
|
||||
private static final boolean debug = false;
|
||||
|
||||
public static final int MTU = 9000;
|
||||
|
||||
public static final IpV6RoutingType SRH_HEADER = new IpV6RoutingType((byte) 4, "SRH Header");
|
||||
// private List<NetworkLink>links=new ArrayList<>();
|
||||
|
||||
private List<RouteItem> routeTabel = new ArrayList<>();
|
||||
|
||||
private List<IPv6NetworkLink> linkTabel = new CopyOnWriteArrayList<>();
|
||||
|
||||
public List<IPv6NetworkLink> getLinkTabel() {
|
||||
return linkTabel;
|
||||
}
|
||||
|
||||
// private ConcurrentHashMap<FlowSession,SlidingWindowInformation>swis=new
|
||||
// ConcurrentHashMap<>();
|
||||
|
||||
private final LoopbackIPv6NetworkLink inLoopBack = new LoopbackIPv6NetworkLink();
|
||||
//private final LoopbackIPv6NetworkLink inLoopBackSRv6;
|
||||
private final LoopbackIPv6NetworkLink hostLoopBack ;
|
||||
|
||||
private class LoopbackIPv6NetworkLink implements IPv6NetworkLink {
|
||||
private Inet6AddressGroup loopbackAddress;
|
||||
|
||||
public LoopbackIPv6NetworkLink() {
|
||||
super();
|
||||
try {
|
||||
this.loopbackAddress=new Inet6AddressGroup( (Inet6Address) Inet6Address.getByName("::1"),128);
|
||||
} catch (UnknownHostException e) {
|
||||
// TODO 自动生成的 catch 块
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public LoopbackIPv6NetworkLink(Inet6Address loopbackAddress) {
|
||||
super();
|
||||
this.loopbackAddress = new Inet6AddressGroup(loopbackAddress,128);
|
||||
}
|
||||
|
||||
public Consumer<IPv6Packet> getReceiveConsumer() {
|
||||
return receiveConsumer;
|
||||
}
|
||||
|
||||
private Consumer<IPv6Packet> receiveConsumer;
|
||||
|
||||
@Override
|
||||
public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException {
|
||||
PacketConsumer pcm;
|
||||
if ((pcm = protocolNumberRegister.get(pack.getPayload().getProtocolNumber())) != null) {
|
||||
pcm.accept(pack);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLoopBack() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Neighbor> getNeighborsInfo() {
|
||||
List<Neighbor> hs = new ArrayList<>();
|
||||
return hs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCongress(IPv6Packet iPv6Packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "inLoopBack";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isUp() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSend(IPv6Packet iPv6Packet) {
|
||||
//System.out.println(iPv6Packet.getPayload().getProtocolNumber());
|
||||
return protocolNumberRegister.containsKey(iPv6Packet.getPayload().getProtocolNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReceiveConsumer(Consumer<IPv6Packet> con) {
|
||||
this.receiveConsumer = con;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Inet6AddressGroup getAddressGroup() {
|
||||
return loopbackAddress;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public List<RouteItem> getRouteTabel() {
|
||||
return routeTabel;
|
||||
}
|
||||
|
||||
public List<RouteItem> getCurrentRouteTabel() {
|
||||
return routeTabel0;
|
||||
}
|
||||
|
||||
private Consumer<IPv6Packet> defaultReceive = new Consumer<IPv6Packet>() {
|
||||
|
||||
@Override
|
||||
public void accept(IPv6Packet t) {
|
||||
HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
||||
routePacket(t);
|
||||
t.putTimePassport("routed");
|
||||
});
|
||||
}
|
||||
};
|
||||
private Consumer<IPv6Packet> srhReceive = new Consumer<IPv6Packet>() {
|
||||
|
||||
@Override
|
||||
public void accept(IPv6Packet t) {
|
||||
HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
||||
insertSRHandRoutePacket(t);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
public void updateRouteTabel() {
|
||||
List<RouteItem> routeTabel0x = new ArrayList<>();
|
||||
|
||||
for (Iterator<IPv6NetworkLink> iterator = linkTabel.iterator(); iterator.hasNext();) {
|
||||
IPv6NetworkLink nlink = (IPv6NetworkLink) iterator.next();
|
||||
if (nlink.isLoopBack()) {
|
||||
if (nlink instanceof IPv6TUNLoopbackNetworkLink) {
|
||||
routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128),
|
||||
nlink.getAddressGroup().getAddress(), nlink, "Direct", 0, 1, null, "D"));
|
||||
|
||||
} else {
|
||||
routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128),
|
||||
nlink.getAddressGroup().getAddress(), nlink, "Direct", 0, 0, null, "D"));
|
||||
|
||||
}
|
||||
}/*else {
|
||||
routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128),
|
||||
nlink.getAddressGroup().getAddress(), inLoopBack, "Direct", 0, 0, null, "D"));
|
||||
}*/
|
||||
for (Iterator<Neighbor> iteratorx = nlink.getNeighborsInfo()
|
||||
.iterator(); iteratorx.hasNext();) {
|
||||
Neighbor addresses = (Neighbor) iteratorx.next();
|
||||
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(),
|
||||
nlink, "Direct", 0, 128, addresses.getMonitor(), "D");
|
||||
routeTabel0x.add(ri);
|
||||
|
||||
RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(),
|
||||
nlink, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D");
|
||||
routeTabel0x.add(ris);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (nlink instanceof IPv6TUNLoopbackNetworkLink) {
|
||||
|
||||
nlink.setReceiveConsumer(srhReceive);
|
||||
} else {
|
||||
nlink.setReceiveConsumer(defaultReceive);
|
||||
}
|
||||
}
|
||||
|
||||
routeTabel0x.addAll(routeTabel);
|
||||
Collections.sort(routeTabel0x);
|
||||
routeTabel0 = routeTabel0x;
|
||||
}
|
||||
|
||||
private Inet6AddressGroup locator;
|
||||
/*
|
||||
* public List<NetworkLink> getLinks() { return links; }
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
public Inet6AddressGroup getLocator() {
|
||||
return locator;
|
||||
}
|
||||
|
||||
public void setLocator(Inet6AddressGroup locator) {
|
||||
this.locator = locator;
|
||||
updateRouteTabel();
|
||||
}
|
||||
|
||||
|
||||
private ConcurrentHashMap<FlowSession, TCPTransimitAgent> swist = new ConcurrentHashMap<>();
|
||||
|
||||
// private AtomicLong qsn=new AtomicLong();
|
||||
public void insertSRHandRoutePacket(IPv6Packet ipp) {
|
||||
insertSRH(ipp);
|
||||
ipp.putTimePassport("SRH inserted");
|
||||
routePacket(ipp);
|
||||
ipp.putTimePassport("routed");
|
||||
}
|
||||
|
||||
public void insertSRH(IPv6Packet ipp) {
|
||||
if (klalbRouteProtol != null) {
|
||||
List<Inet6Address> segs = klalbRouteProtol.createSegmentList(ipp.getDestinationAddress());
|
||||
// System.out.println(segs);
|
||||
if (segs != null && (!segs.isEmpty())) {
|
||||
/*
|
||||
* List<SRv6TLV>tlvs=new ArrayList<>(1); if(ipp.getPayload().getType()==6) {
|
||||
* SRv6StreamSequenceTLV sers= new SRv6StreamSequenceTLV();
|
||||
* sers.setSequence(qsn.getAndIncrement()); tlvs.add(sers); }
|
||||
*/
|
||||
|
||||
//IpV6RoutingSRHData srh = new IpV6RoutingSRHData(segs);
|
||||
|
||||
IPv6SegmentRoutingHeader irh = new IPv6SegmentRoutingHeader(segs);
|
||||
ipp.getHeaders().add(irh);
|
||||
|
||||
ipp.setDestinationAddress(segs.get(segs.size() - 1));
|
||||
/*
|
||||
* if(ipp.getPayload().getType()==6) System.out.println(ipp);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private volatile List<RouteItem> routeTabel0 = new ArrayList<>();
|
||||
|
||||
// private ReentrantReadWriteLock routelock=new ReentrantReadWriteLock();
|
||||
public void routePacket(IPv6Packet iPv6Packet) {
|
||||
// routelock.readLock().lock();
|
||||
// try {
|
||||
// System.out.println("路由表:"+routeTabel0);
|
||||
StringBuilder dbg=null;
|
||||
if (debug) {
|
||||
dbg=new StringBuilder();
|
||||
}
|
||||
iPv6Packet.lockAll();
|
||||
try {
|
||||
if(iPv6Packet.isSomeDisposed())
|
||||
return;
|
||||
int hop = iPv6Packet.getHopLimit();
|
||||
if (hop > 0) {
|
||||
// List<RouteItem> mached=new ArrayList<>();
|
||||
// RouteItem pri=null;
|
||||
|
||||
Inet6Address ia = iPv6Packet.getDestinationAddress();
|
||||
if (debug) {
|
||||
dbg.append("----------------------------------------\n");
|
||||
dbg.append("packet:" + iPv6Packet.getSourceAddress().getHostAddress() + "->"
|
||||
+ iPv6Packet.getDestinationAddress().getHostAddress()+"\n");
|
||||
}
|
||||
for (int i = 0; i < routeTabel0.size(); i++) {
|
||||
RouteItem tri = routeTabel0.get(i);
|
||||
if (!tri.checkMatch(ia)) {
|
||||
if (debug) {
|
||||
dbg.append(tri+"\n");
|
||||
dbg.append("unmatched.\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!tri.getDestlink().isUp()) {
|
||||
if (debug) {
|
||||
dbg.append(tri+"\n");
|
||||
dbg.append("linkdown.\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (tri.getDestlink().isCongress(iPv6Packet)) {
|
||||
if (debug) {
|
||||
dbg.append(tri+"\n");
|
||||
dbg.append("congress.\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!tri.getDestlink().canSend(iPv6Packet)) {
|
||||
if (debug) {
|
||||
dbg.append(tri+"\n");
|
||||
dbg.append("linkrefused.\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (debug) {
|
||||
dbg.append(tri+"\n");
|
||||
dbg.append("matched.\n");
|
||||
}
|
||||
processPacket(iPv6Packet, tri);
|
||||
return;
|
||||
/*
|
||||
* if(pri==null||pri.equals(tri)) { mached.add(tri); pri=tri; }else { break; }
|
||||
*/
|
||||
}
|
||||
if (debug) {
|
||||
dbg.append("miss.\n");
|
||||
}
|
||||
if (iPv6Packet.isEnableECN()) {
|
||||
iPv6Packet.markCE();
|
||||
for (int i = 0; i < routeTabel0.size(); i++) {
|
||||
RouteItem tri = routeTabel0.get(i);
|
||||
if (tri.checkMatch(ia)) {
|
||||
if (!tri.getDestlink().isUp()) {
|
||||
continue;
|
||||
}
|
||||
processPacket(iPv6Packet, tri);
|
||||
return;
|
||||
/*
|
||||
* if(pri==null||pri.equals(tri)) { mached.add(tri); pri=tri; }else { break; }
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
if (debug)
|
||||
dbg.append("congress\n");
|
||||
// System.out.println(ia.getAddress()+" match "+ri);
|
||||
/*
|
||||
* for (Iterator iterator = mached.iterator(); iterator.hasNext();) { RouteItem
|
||||
* routeItem = (RouteItem) iterator.next();
|
||||
* if(routeItem.getDestlink().isCongress()) {
|
||||
*
|
||||
* }else { processPacket(iPv6Packet,pri); break; } }
|
||||
*/
|
||||
// else
|
||||
// System.out.println("路由失败:"+iPv6Packet);
|
||||
|
||||
} else {
|
||||
IcmpV6TimeExceededPacket.Builder icmpte = new IcmpV6TimeExceededPacket.Builder();
|
||||
ByteBuffer IPv6data = NetworkPacket.databufferpool_65535.borrow();
|
||||
iPv6Packet.writeToChannel(KNEChannels.newWritableChannel(IPv6data));
|
||||
byte[] raw = new byte[IPv6data.remaining()];
|
||||
IPv6data.get(0, raw);
|
||||
icmpte.payload(IpV6Packet.newPacket(raw, 0, raw.length));
|
||||
|
||||
IcmpV6CommonPacket.Builder icbd = new IcmpV6CommonPacket.Builder();
|
||||
icbd.type(IcmpV6Type.TIME_EXCEEDED);
|
||||
icbd.code(IcmpV6Code.HOP_LIMIT_EXCEEDED);
|
||||
icbd.srcAddr(locator.getAddress());
|
||||
icbd.dstAddr(iPv6Packet.getSourceAddress());
|
||||
icbd.correctChecksumAtBuild(true);
|
||||
icbd.payloadBuilder(icmpte);
|
||||
|
||||
IPv6Packet icmpv = new IPv6Packet();
|
||||
icmpv.setSourceAddress(locator.getAddress());
|
||||
icmpv.setDestinationAddress(iPv6Packet.getSourceAddress());
|
||||
icmpv.setTrafficClass(iPv6Packet.getTrafficClass());
|
||||
icmpv.setVersion(6);
|
||||
icmpv.setFlowLabel(0);
|
||||
icmpv.setHopLimit(255);
|
||||
IPv6Payload ipl = new IPv6Payload(IpNumber.ICMPV6.value());
|
||||
ipl.getData().put(icbd.build().getRawData());
|
||||
ipl.getData().flip();
|
||||
icmpv.setPayload(ipl);
|
||||
insertSRHandRoutePacket(icmpv);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if(debug) {
|
||||
System.out.println(dbg.toString());
|
||||
}
|
||||
iPv6Packet.unlockAll();
|
||||
}
|
||||
// }finally {
|
||||
// routelock.readLock().unlock();
|
||||
// }
|
||||
}
|
||||
|
||||
private void processPacket(IPv6Packet iPv6Packet, RouteItem ri) throws IllegalRawDataException, IOException {
|
||||
int hop = iPv6Packet.getHopLimit();
|
||||
|
||||
if (ri.getDestlink().isLoopBack()) {
|
||||
IPv6SegmentRoutingHeader srhh = getSRHHeaderFromPacket(iPv6Packet);
|
||||
if (srhh != null) {
|
||||
processSRv6Packet(iPv6Packet, ri, srhh);
|
||||
} else {
|
||||
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
|
||||
}
|
||||
} else {
|
||||
hop--;
|
||||
// System.out.println(ipp.getHeader().getSrcAddr()+"->"+ipp.getHeader().getDstAddr()+"
|
||||
// "+(hop+1)+"->"+hop);
|
||||
if (hop > 0) {
|
||||
|
||||
iPv6Packet.setHopLimit(hop);
|
||||
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
|
||||
} else {
|
||||
IcmpV6TimeExceededPacket.Builder icmpte = new IcmpV6TimeExceededPacket.Builder();
|
||||
ByteBuffer IPv6data = NetworkPacket.databufferpool_65535.borrow();
|
||||
iPv6Packet.writeToChannel(KNEChannels.newWritableChannel(IPv6data));
|
||||
byte[] raw = new byte[IPv6data.remaining()];
|
||||
IPv6data.get(0, raw);
|
||||
icmpte.payload(IpV6Packet.newPacket(raw, 0, raw.length));
|
||||
|
||||
IcmpV6CommonPacket.Builder icbd = new IcmpV6CommonPacket.Builder();
|
||||
icbd.type(IcmpV6Type.TIME_EXCEEDED);
|
||||
icbd.code(IcmpV6Code.HOP_LIMIT_EXCEEDED);
|
||||
icbd.srcAddr(locator.getAddress());
|
||||
icbd.dstAddr(iPv6Packet.getSourceAddress());
|
||||
icbd.correctChecksumAtBuild(true);
|
||||
icbd.payloadBuilder(icmpte);
|
||||
|
||||
IPv6Packet icmpv = new IPv6Packet();
|
||||
icmpv.setSourceAddress(locator.getAddress());
|
||||
icmpv.setDestinationAddress(iPv6Packet.getSourceAddress());
|
||||
icmpv.setTrafficClass(iPv6Packet.getTrafficClass());
|
||||
icmpv.setVersion(6);
|
||||
icmpv.setFlowLabel(0);
|
||||
icmpv.setHopLimit(255);
|
||||
IPv6Payload ipl = new IPv6Payload(IpNumber.ICMPV6.value());
|
||||
ipl.getData().put(icbd.build().getRawData());
|
||||
ipl.getData().flip();
|
||||
icmpv.setPayload(ipl);
|
||||
insertSRHandRoutePacket(icmpv);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void processSRv6Packet(IPv6Packet iPv6Packet, RouteItem ri, IPv6SegmentRoutingHeader srhh)
|
||||
throws IllegalRawDataException, IOException {
|
||||
/*byte[] srd = new byte[(int) (srhh.getLength() - 4)];
|
||||
srhh.getData().get(4, srd);
|
||||
IpV6RoutingSRHData srh = IpV6RoutingSRHData.newInstance(srd, 0, srd.length);*/
|
||||
if (srhh.getSegmentsLeft() <= 0) {
|
||||
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
|
||||
} else {
|
||||
|
||||
int newSL = srhh.getSegmentsLeft() - 1;
|
||||
srhh.setSegmentsLeft(newSL);
|
||||
iPv6Packet.setDestinationAddress(srhh.getAddresses().get(newSL));
|
||||
klalbRouteProtol.putHotspotAddress(iPv6Packet.getSourceAddress());
|
||||
routePacket(iPv6Packet);
|
||||
}
|
||||
}
|
||||
|
||||
private IPv6SegmentRoutingHeader getSRHHeaderFromPacket(IPv6Packet iPv6Packet) {
|
||||
IPv6SegmentRoutingHeader srhh = null;
|
||||
List<IPv6ExtHeader> exhs = iPv6Packet.getHeaders();
|
||||
for (int j = 0; j < exhs.size(); j++) {
|
||||
IPv6ExtHeader exh = exhs.get(j);
|
||||
if (exh instanceof IPv6SegmentRoutingHeader) {
|
||||
if (((IPv6SegmentRoutingHeader) exh).getRoutingType() == 4) {
|
||||
srhh = (IPv6SegmentRoutingHeader) exh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return srhh;
|
||||
}
|
||||
|
||||
public SRv6Router(Inet6AddressGroup hostAddress) {
|
||||
super();
|
||||
this.locator = hostAddress;
|
||||
//this.inLoopBackSRv6=new LoopbackIPv6NetworkLink(locator.getAddress());
|
||||
this.hostLoopBack= new LoopbackIPv6NetworkLink(hostAddress.getAddress());
|
||||
linkTabel.add(inLoopBack);
|
||||
//linkTabel.add(inLoopBackSRv6);
|
||||
linkTabel.add(hostLoopBack);
|
||||
}
|
||||
|
||||
/*public SRv6Router() {
|
||||
super();
|
||||
linkTabel.add(inLoopBack);
|
||||
}*/
|
||||
|
||||
private KLALBRoutingProtocol klalbRouteProtol = null;
|
||||
|
||||
public void runKLALBRouteProtocol() {
|
||||
if (klalbRouteProtol != null)
|
||||
throw new IllegalStateException("KLALB routing protocol is already running!");
|
||||
klalbRouteProtol = new KLALBRoutingProtocol(this);
|
||||
klalbRouteProtol.start();
|
||||
}
|
||||
|
||||
public KLALBRoutingProtocol getKlalbRouteProtol() {
|
||||
return klalbRouteProtol;
|
||||
}
|
||||
|
||||
private Map<Integer, PacketConsumer> protocolNumberRegister = new ConcurrentHashMap<>();
|
||||
|
||||
public Map<Integer, PacketConsumer> getProtocolNumberRegister() {
|
||||
return protocolNumberRegister;
|
||||
}
|
||||
|
||||
public void putProtocolNumberPacketAndInsertSRH(IPv6Packet pkt) {
|
||||
// inLoopBack.getReceiveConsumer().accept(pkt);
|
||||
srhReceive.accept(pkt);
|
||||
}
|
||||
|
||||
public void putProtocolNumberPacket(IPv6Packet pkt) {
|
||||
// inLoopBack.getReceiveConsumer().accept(pkt);
|
||||
defaultReceive.accept(pkt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
|
||||
public class SRv6StreamSequenceTLV extends SRv6TLV {
|
||||
|
||||
public SRv6StreamSequenceTLV() {
|
||||
super(SEQS, 22, new byte[22]);
|
||||
}
|
||||
public SRv6StreamSequenceTLV(int lengthQTLV, byte[] rawQTLV) {
|
||||
super(SEQS, lengthQTLV, rawQTLV);
|
||||
}
|
||||
public int getReserved(){
|
||||
return getValue()[0]<<8|getValue()[1];
|
||||
}
|
||||
public void setReserved(int reserved) {
|
||||
getValue()[0]=(byte) (reserved>>>8);
|
||||
getValue()[1]=(byte) reserved;
|
||||
}
|
||||
public long getSequence() {
|
||||
return (((long)getValue()[6] << 56) +
|
||||
((long)(getValue()[7] & 255) << 48) +
|
||||
((long)(getValue()[8] & 255) << 40) +
|
||||
((long)(getValue()[9] & 255) << 32) +
|
||||
((long)(getValue()[10] & 255) << 24) +
|
||||
((getValue()[11] & 255) << 16) +
|
||||
((getValue()[12] & 255) << 8) +
|
||||
((getValue()[13] & 255) << 0));
|
||||
}
|
||||
public void setSequence(long sequence) {
|
||||
getValue()[6] = (byte)(sequence >>> 56);
|
||||
getValue()[7] = (byte)(sequence >>> 48);
|
||||
getValue()[8] = (byte)(sequence >>> 40);
|
||||
getValue()[9] = (byte)(sequence >>> 32);
|
||||
getValue()[10] = (byte)(sequence >>> 24);
|
||||
getValue()[11] = (byte)(sequence >>> 16);
|
||||
getValue()[12] = (byte)(sequence >>> 8);
|
||||
getValue()[13] = (byte)(sequence >>> 0);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SRv6TLV {
|
||||
public static final int PAD1=0;
|
||||
public static final int PADN=4;
|
||||
public static final int HMAC=5;
|
||||
public static final int SEQS=7;
|
||||
|
||||
private int type;
|
||||
private int length;
|
||||
private byte[]value;
|
||||
public SRv6TLV(int type, int length, byte[] value) {
|
||||
super();
|
||||
this.type = type;
|
||||
this.length = length;
|
||||
this.value = value;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SRv6TLV [type=" + type + ", length=" + length + ", value=" + Arrays.toString(value) + "]";
|
||||
}
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
public byte[] getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public int getTotalLength() {
|
||||
if(type==PAD1) {
|
||||
return 1;
|
||||
}
|
||||
return 2+length;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SingleDijkstraAlgorithm implements DijkstraAlgorithm {
|
||||
|
||||
private long[][] heap;
|
||||
private long[][]pointers;
|
||||
|
||||
private long[] direction;
|
||||
private long[] shortest;
|
||||
private boolean[] flags;
|
||||
private long startPoint;
|
||||
|
||||
|
||||
private static final long MAX_WEIGHT=Long.MAX_VALUE/256L;
|
||||
@Override
|
||||
public void setGraph(long[][] pointers,long[][] heap,long startPoint) {
|
||||
this.heap=heap;
|
||||
this.pointers=pointers;
|
||||
/*for (int i = 0; i < pointers.length; i++) {
|
||||
for (int j = 0; j < pointers[i].length; j++) {
|
||||
System.out.println("pointers["+i+"]["+j+"]="+pointers[i][j]);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < heap.length; i++) {
|
||||
for (int j = 0; j < heap[i].length; j++) {
|
||||
System.out.println("heap["+i+"]["+j+"]="+heap[i][j]);
|
||||
}
|
||||
}*/
|
||||
|
||||
this.startPoint=startPoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
direction=new long[pointers.length];
|
||||
shortest=new long[pointers.length];
|
||||
flags=new boolean[pointers.length];
|
||||
Arrays.fill(shortest, MAX_WEIGHT);
|
||||
Arrays.fill(direction, -1);
|
||||
|
||||
|
||||
shortest[(int) startPoint]=0;
|
||||
direction[(int) startPoint]=startPoint;
|
||||
|
||||
for(long i=1;i<pointers.length;i++) {
|
||||
long shortestNode=-1;
|
||||
long shortestLength=MAX_WEIGHT+1;
|
||||
for(long j=0;j<pointers.length;j++) {
|
||||
if(flags[(int) j]) {
|
||||
continue;
|
||||
}
|
||||
long pathLength=shortest[(int) j];
|
||||
if(pathLength<shortestLength) {
|
||||
shortestLength=pathLength;
|
||||
shortestNode=j;
|
||||
}
|
||||
}
|
||||
flags[(int) shortestNode]=true;
|
||||
|
||||
|
||||
long pointer =pointers[(int) shortestNode][0];
|
||||
long count =pointers[(int) shortestNode][1];
|
||||
for (long j = 0; j < count; j++) {
|
||||
long lenthJ=heap[(int) (pointer+j)][1]+shortestLength;
|
||||
long pos= heap[(int) (pointer+j)][0];
|
||||
if(lenthJ<shortest[(int)pos]) {
|
||||
shortest[(int)pos]=lenthJ;
|
||||
direction[(int)pos]=shortestNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getShortest() {
|
||||
return shortest;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.pcap4j.packet.IpV6Packet;
|
||||
import org.pcap4j.packet.TcpPacket;
|
||||
|
||||
public class SlidingWindowInformation {
|
||||
public SlidingWindowInformation(long sequenceNumber) {
|
||||
this.sequenceNumber =sequenceNumber;
|
||||
}
|
||||
private ReentrantLock rlock=new ReentrantLock();
|
||||
private List<TcpPacketEntry> tcps=new ArrayList<>();
|
||||
private volatile long sequenceNumber;
|
||||
public List<TcpPacketEntry> getTcps() {
|
||||
return tcps;
|
||||
}
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
public static class TcpPacketEntry{
|
||||
private IPv6Packet packet;
|
||||
private long sequenceNumber;
|
||||
private int length;
|
||||
private long addtime=System.nanoTime();
|
||||
|
||||
public TcpPacketEntry(IPv6Packet packet, long sequenceNumber, int length) {
|
||||
super();
|
||||
this.packet = packet;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.length = length;
|
||||
}
|
||||
public IPv6Packet getPacket() {
|
||||
return packet;
|
||||
}
|
||||
public long getAddtime() {
|
||||
return addtime;
|
||||
}
|
||||
public boolean checkTimeOut() {
|
||||
return System.nanoTime()-addtime>5000000000L;
|
||||
}
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TcpPacketEntry [sequenceNumber=" + sequenceNumber + ", length=" + length
|
||||
+ ", addtime=" + addtime + "]";
|
||||
}
|
||||
}
|
||||
public void sortPackets(IPv6Packet pack,long seq,int length, PacketConsumer packconsumer) throws IOException {
|
||||
rlock.lock();
|
||||
try {
|
||||
//System.out.println("包序号:"+seq+" 长度:"+length);
|
||||
//System.out.println("当前序号:"+sequenceNumber);
|
||||
if(seq<sequenceNumber) {
|
||||
packconsumer.accept(pack);
|
||||
}else {
|
||||
loop: do {
|
||||
for(int i=0;i<tcps.size();i++) {
|
||||
TcpPacketEntry tpe=tcps.get(i);
|
||||
if(seq<tpe.getSequenceNumber()) {
|
||||
tcps.add(i, new TcpPacketEntry(pack, seq, length));
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
tcps.add(new TcpPacketEntry(pack, seq, length));
|
||||
}while(false);
|
||||
}
|
||||
for (Iterator<TcpPacketEntry> iterator = tcps.iterator(); iterator.hasNext();) {
|
||||
TcpPacketEntry tcpPacketEntry = (TcpPacketEntry) iterator.next();
|
||||
if(tcpPacketEntry.getSequenceNumber()==sequenceNumber) {
|
||||
iterator.remove();
|
||||
sequenceNumber+=tcpPacketEntry.getLength();
|
||||
packconsumer.accept(pack);
|
||||
}else if(tcpPacketEntry.getSequenceNumber()<sequenceNumber) {
|
||||
iterator.remove();
|
||||
packconsumer.accept(pack);
|
||||
}else if(tcpPacketEntry.checkTimeOut()){
|
||||
iterator.remove();
|
||||
sequenceNumber=tcpPacketEntry.getSequenceNumber()+ tcpPacketEntry.getLength();
|
||||
packconsumer.accept(pack);
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
rlock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.pcap4j.packet.IpV6Packet;
|
||||
import org.pcap4j.packet.TcpPacket;
|
||||
|
||||
public class TCPTransimitAgent {
|
||||
public TCPTransimitAgent() {
|
||||
}
|
||||
private ReentrantLock rlock=new ReentrantLock();
|
||||
private Map<Long,TcpPacketEntry> tcps=new ConcurrentHashMap();
|
||||
public Map<Long,TcpPacketEntry> getTcps() {
|
||||
return tcps;
|
||||
}
|
||||
public static class TcpPacketEntry{
|
||||
private IPv6Packet packet;
|
||||
private long sequenceNumber;
|
||||
private int length;
|
||||
private long addtime=System.nanoTime();
|
||||
|
||||
public TcpPacketEntry(IPv6Packet packet, long sequenceNumber, int length) {
|
||||
super();
|
||||
this.packet = packet;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.length = length;
|
||||
}
|
||||
public IPv6Packet getPacket() {
|
||||
return packet;
|
||||
}
|
||||
public long getAddtime() {
|
||||
return addtime;
|
||||
}
|
||||
public boolean checkTimeOut() {
|
||||
return System.nanoTime()-addtime>1000000000L;
|
||||
}
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
public int getLength() {
|
||||
return length;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TcpPacketEntry [sequenceNumber=" + sequenceNumber + ", length=" + length
|
||||
+ ", addtime=" + addtime + "]";
|
||||
}
|
||||
}
|
||||
public boolean sortPackets(IPv6Packet pack,long seq,int length, PacketConsumer packconsumer) throws IOException {
|
||||
if(length<=0) {
|
||||
packconsumer.accept(pack);
|
||||
return true;
|
||||
}
|
||||
rlock.lock();
|
||||
try {
|
||||
//System.out.println("包序号:"+seq+" 长度:"+length);
|
||||
Set<Entry<Long,TcpPacketEntry >>et= tcps.entrySet();
|
||||
for (Iterator<Entry<Long, TcpPacketEntry>> iterator = et.iterator(); iterator.hasNext();) {
|
||||
Entry<Long, TcpPacketEntry> entry = (Entry<Long, TcpPacketEntry>) iterator.next();
|
||||
if(entry.getValue().checkTimeOut()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
TcpPacketEntry tpe= tcps.get(seq);
|
||||
if(tpe==null) {
|
||||
tcps.put(seq, new TcpPacketEntry(pack, seq, length));
|
||||
packconsumer.accept(pack);
|
||||
}else {
|
||||
if(tpe.getLength()==length) {
|
||||
return false;
|
||||
}else {
|
||||
tcps.put(seq, new TcpPacketEntry(pack, seq, length));
|
||||
packconsumer.accept(pack);
|
||||
}
|
||||
}
|
||||
}finally {
|
||||
rlock.unlock();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
|
||||
public class UnheaderObjectInputStream extends ObjectInputStream{
|
||||
|
||||
|
||||
public UnheaderObjectInputStream(InputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
@Override
|
||||
protected void readStreamHeader() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.kne.cloud.network.srv6;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class UnheaderObjectOutputStream extends ObjectOutputStream{
|
||||
|
||||
|
||||
public UnheaderObjectOutputStream(OutputStream out) throws IOException {
|
||||
super(out);
|
||||
}
|
||||
@Override
|
||||
protected void writeStreamHeader() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user