forked from KNEMC/KLALB
KLALB V3.6.0 写了一半
This commit is contained in:
@@ -6,13 +6,27 @@ import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.klalb.KLALBRemoteLine;
|
||||
import org.kne.cloud.network.srv6.SRv6Router;
|
||||
|
||||
public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
|
||||
private CopyOnWriteArraySet<IPv6LinkStateListener> listeners = new CopyOnWriteArraySet<>();
|
||||
|
||||
private SRv6Router srv6Router;
|
||||
|
||||
|
||||
public SRv6Router getSrv6Router() {
|
||||
return srv6Router;
|
||||
}
|
||||
|
||||
public void setSRv6Router(SRv6Router srv6Router) {
|
||||
this.srv6Router = srv6Router;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addIPv6LinkStateListener(IPv6LinkStateListener listener) {
|
||||
listeners.add(listener);
|
||||
@@ -40,4 +54,14 @@ public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
|
||||
v.onAddressUpdate(this);
|
||||
});
|
||||
}
|
||||
|
||||
public BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> getReceiveConsumer() {
|
||||
return receiveConsumer;
|
||||
}
|
||||
|
||||
private BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> receiveConsumer;
|
||||
@Override
|
||||
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> receiveConsumer) {
|
||||
this.receiveConsumer = receiveConsumer;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface ControlledIPv6NetworkLink extends IPv6NetworkLink {
|
||||
|
||||
public boolean isCongress(IPv6Packet iPv6Packet,double scale);
|
||||
public default boolean isCongress(IPv6Packet iPv6Packet) {
|
||||
return isCongress(iPv6Packet, 1.0);
|
||||
}
|
||||
void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer);
|
||||
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet);
|
||||
public void setCongressCondition(Lock lock,Condition condition);
|
||||
}
|
||||
@@ -6,19 +6,19 @@ import java.net.InetAddress;
|
||||
import java.util.Objects;
|
||||
|
||||
public class FlowSession implements Serializable{
|
||||
private Inet6Address srcAddr;
|
||||
private Inet6Address dstAddr;
|
||||
private IPv6Address srcAddr;
|
||||
private IPv6Address dstAddr;
|
||||
private int flowLabel;
|
||||
public FlowSession(Inet6Address srcAddr, Inet6Address dstAddr, int flowLabel) {
|
||||
public FlowSession(IPv6Address srcAddr, IPv6Address dstAddr, int flowLabel) {
|
||||
super();
|
||||
this.srcAddr = srcAddr;
|
||||
this.dstAddr = dstAddr;
|
||||
this.flowLabel = flowLabel;
|
||||
}
|
||||
public Inet6Address getSrcAddr() {
|
||||
public IPv6Address getSrcAddr() {
|
||||
return srcAddr;
|
||||
}
|
||||
public Inet6Address getDstAddr() {
|
||||
public IPv6Address getDstAddr() {
|
||||
return dstAddr;
|
||||
}
|
||||
public int getFlowLabel() {
|
||||
@@ -30,7 +30,12 @@ public class FlowSession implements Serializable{
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(dstAddr, flowLabel, srcAddr);
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((dstAddr == null) ? 0 : dstAddr.hashCode());
|
||||
result = prime * result + flowLabel;
|
||||
result = prime * result + ((srcAddr == null) ? 0 : srcAddr.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
@@ -41,8 +46,19 @@ public class FlowSession implements Serializable{
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
FlowSession other = (FlowSession) obj;
|
||||
return Objects.equals(dstAddr, other.dstAddr) && flowLabel == other.flowLabel
|
||||
&& Objects.equals(srcAddr, other.srcAddr);
|
||||
if (dstAddr == null) {
|
||||
if (other.dstAddr != null)
|
||||
return false;
|
||||
} else if (!dstAddr.equals(other.dstAddr))
|
||||
return false;
|
||||
if (flowLabel != other.flowLabel)
|
||||
return false;
|
||||
if (srcAddr == null) {
|
||||
if (other.srcAddr != null)
|
||||
return false;
|
||||
} else if (!srcAddr.equals(other.srcAddr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
@@ -22,21 +23,38 @@ public class ICMPv6Packet extends IPv6Payload {
|
||||
public static final int TYPE_PARAMETER_PROBLEM = 4;
|
||||
public static final int TYPE_ECHO_REQUEST = 128;
|
||||
public static final int TYPE_ECHO_REPLY = 129;
|
||||
public static final int TYPE_POSTCARD = 253;
|
||||
|
||||
private ByteBuffer header = NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
|
||||
private ByteBuffer header;
|
||||
private ByteBuffer data;
|
||||
public void setData(ByteBuffer data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public ICMPv6Packet() {
|
||||
private boolean isDefault;
|
||||
|
||||
protected ICMPv6Packet(ByteBuffer header,boolean isDefault) {
|
||||
super(ICMPv6_PROTOCOL_NUMBER, false);
|
||||
this.header=header;
|
||||
this.isDefault=isDefault;
|
||||
|
||||
}
|
||||
|
||||
public ICMPv6Packet(int type, int code) {
|
||||
this(type,code,true);
|
||||
}
|
||||
|
||||
protected ICMPv6Packet(int type, int code,boolean isDefault) {
|
||||
super(ICMPv6_PROTOCOL_NUMBER, false);
|
||||
header = NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
|
||||
getHeader().put((byte) type);
|
||||
getHeader().put((byte) code);
|
||||
// 校验和字段初始为0,后续计算
|
||||
getHeader().putChar((char) 0);
|
||||
this.isDefault=isDefault;
|
||||
if(isDefault) {
|
||||
data = NetworkPacket.bufferAllocator.allocate(65535);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,7 +68,7 @@ public class ICMPv6Packet extends IPv6Payload {
|
||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
// 写入头部和数据
|
||||
dto.write(getHeader().slice(0, ICMPv6_HEADER_LENGTH));
|
||||
if (data != null && data.limit() > 0) {
|
||||
if ( isDefault) {
|
||||
dto.write(data.slice(0, data.limit()));
|
||||
}
|
||||
}
|
||||
@@ -58,9 +76,9 @@ public class ICMPv6Packet extends IPv6Payload {
|
||||
@Override
|
||||
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
// 读取ICMPv6头部
|
||||
getHeader().clear().limit(ICMPv6_HEADER_LENGTH);
|
||||
getHeader().limit(ICMPv6_HEADER_LENGTH);
|
||||
KNEChannels.readFully(din, getHeader());
|
||||
|
||||
getHeader().flip();
|
||||
// 读取数据部分(总长度减去头部长度)
|
||||
long dataLength = length - ICMPv6_HEADER_LENGTH;
|
||||
|
||||
@@ -68,18 +86,16 @@ public class ICMPv6Packet extends IPv6Payload {
|
||||
throw new IOException("Invalid ICMPv6 packet: total length < header length");
|
||||
}
|
||||
|
||||
if (dataLength > 0) {
|
||||
if (isDefault) {
|
||||
data = NetworkPacket.bufferAllocator.allocate((int) dataLength);
|
||||
KNEChannels.readFully(din, data);
|
||||
data.flip();
|
||||
} else {
|
||||
data = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needEndPosition() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -167,17 +183,10 @@ public class ICMPv6Packet extends IPv6Payload {
|
||||
// 临时将校验和字段设为0
|
||||
setChecksum(0);
|
||||
|
||||
long sum = 0;
|
||||
|
||||
// IPv6伪首部
|
||||
byte[] srcAddr = new byte[16], dstAddr = new byte[16];
|
||||
getParent().getRawSourceAddress(srcAddr);
|
||||
getParent().getRawDestinationAddress(dstAddr);
|
||||
|
||||
for (int i = 0; i < 16; i += 2) {
|
||||
sum += ((srcAddr[i] & 0xFF) << 8) | (srcAddr[i + 1] & 0xFF);
|
||||
sum += ((dstAddr[i] & 0xFF) << 8) | (dstAddr[i + 1] & 0xFF);
|
||||
}
|
||||
long sum = getParent().calculateAddressChecksum();
|
||||
|
||||
|
||||
// ICMPv6报文长度
|
||||
int totalLength = (int) getTotalLength();
|
||||
@@ -281,4 +290,26 @@ public class ICMPv6Packet extends IPv6Payload {
|
||||
public ByteBuffer getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public static ICMPv6Packet readICMPv6PacketFromChannel(ReadableByteChannel din, int payloadlength) throws EOFException, IOException {
|
||||
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(ICMPv6_HEADER_LENGTH);
|
||||
bb.position(0);
|
||||
bb.limit(ICMPv6_HEADER_LENGTH);
|
||||
KNEChannels.readFully(din, bb);
|
||||
int type=bb.get(0)&0xff;
|
||||
switch(type) {
|
||||
case ICMPv6TimeExceededPacket.TYPE_TIME_EXCEEDED:
|
||||
ICMPv6TimeExceededPacket timeExceed=new ICMPv6TimeExceededPacket(bb);
|
||||
timeExceed.readFromChannel(din, payloadlength);
|
||||
return timeExceed;
|
||||
case ICMPv6PostcardPacket.TYPE_POSTCARD:
|
||||
ICMPv6PostcardPacket postcards=new ICMPv6PostcardPacket(bb);
|
||||
postcards.readFromChannel(din, payloadlength);
|
||||
return postcards;
|
||||
default:
|
||||
ICMPv6Packet icmp=new ICMPv6Packet(bb, true);
|
||||
icmp.readFromChannel(din, payloadlength);
|
||||
return icmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StreamCorruptedException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.io.KNEChannels;
|
||||
|
||||
public class ICMPv6PostcardPacket extends ICMPv6Packet {
|
||||
private List<PostcardEntry> postcards=new ArrayList<>();
|
||||
protected ICMPv6PostcardPacket(ByteBuffer header) {
|
||||
super(header, false);
|
||||
}
|
||||
|
||||
public ICMPv6PostcardPacket(int code) {
|
||||
super(ICMPv6Packet.TYPE_POSTCARD, code, false);
|
||||
}
|
||||
|
||||
public ICMPv6PostcardPacket() {
|
||||
this(0);
|
||||
}
|
||||
|
||||
public List<PostcardEntry> getPostcards() {
|
||||
return postcards;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalLength() {
|
||||
return ICMPv6Packet.ICMPv6_HEADER_LENGTH+postcards.size()*PostcardEntry.POSTCARD_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
super.writeToChannel(dto);
|
||||
for(PostcardEntry postcard:postcards) {
|
||||
postcard.writeToChannel(dto);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ICMPv6PostcardPacket [postcards=" + postcards + ", getTotalLength()=" + getTotalLength() + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
super.readFromChannel(din, length);
|
||||
postcards.clear();
|
||||
int count= (int) ((length-ICMPv6Packet.ICMPv6_HEADER_LENGTH)/PostcardEntry.POSTCARD_ENTRY_SIZE);
|
||||
for(int i=0;i<count;i++) {
|
||||
PostcardEntry pe=new PostcardEntry();
|
||||
pe.readFromChannel(din);
|
||||
postcards.add(pe);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.io.KNEChannels;
|
||||
|
||||
public class ICMPv6TimeExceededPacket extends ICMPv6Packet {
|
||||
private static final int UNUSED_FIELD_LENGTH = 4; // 未使用字段长度
|
||||
|
||||
// 代码值常量
|
||||
public static final int CODE_HOP_LIMIT_EXCEEDED = 0; // 跳数限制超时
|
||||
@@ -18,7 +17,11 @@ public class ICMPv6TimeExceededPacket extends ICMPv6Packet {
|
||||
setUnused(0);
|
||||
}
|
||||
|
||||
/**
|
||||
public ICMPv6TimeExceededPacket(ByteBuffer bb) {
|
||||
super(bb, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取未使用字段(通常为0)
|
||||
*/
|
||||
public int getUnused() {
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.kne.cloud.network.klalb.KLALBUtils;
|
||||
|
||||
/**
|
||||
* 高性能IPv6地址实现,使用两个long代替byte[16],
|
||||
* 大幅减少GC压力和提高路由表查找性能
|
||||
*/
|
||||
public final class IPv6Address implements Comparable<IPv6Address> {
|
||||
|
||||
private final long high;
|
||||
private final long low;
|
||||
|
||||
// 常用常量地址
|
||||
public static final IPv6Address LOOPBACK = new IPv6Address(0, 1);
|
||||
public static final IPv6Address UNSPECIFIED = new IPv6Address(0, 0);
|
||||
public static final IPv6Address LOCALHOST = LOOPBACK;
|
||||
|
||||
// IPv4映射的IPv6地址前缀
|
||||
private static final long IPV4_MAPPED_HIGH = 0x0000_0000_0000_0000L;
|
||||
private static final long IPV4_MAPPED_LOW_PREFIX = 0x0000_0000_FFFF_0000L;
|
||||
|
||||
// 构造方法
|
||||
public IPv6Address(long high, long low) {
|
||||
this.high = high;
|
||||
this.low = low;
|
||||
}
|
||||
|
||||
public IPv6Address(Inet6Address address) {
|
||||
this(address.getAddress());
|
||||
}
|
||||
|
||||
public IPv6Address(byte[] bytes) {
|
||||
if (bytes.length != 16) {
|
||||
throw new IllegalArgumentException("IPv6 address must be 16 bytes");
|
||||
}
|
||||
|
||||
this. high = ((long)(bytes[0] & 0xFF) << 56) |
|
||||
((long)(bytes[1] & 0xFF) << 48) |
|
||||
((long)(bytes[2] & 0xFF) << 40) |
|
||||
((long)(bytes[3] & 0xFF) << 32) |
|
||||
((long)(bytes[4] & 0xFF) << 24) |
|
||||
((long)(bytes[5] & 0xFF) << 16) |
|
||||
((long)(bytes[6] & 0xFF) << 8) |
|
||||
((long)(bytes[7] & 0xFF));
|
||||
|
||||
this.low = ((long)(bytes[8] & 0xFF) << 56) |
|
||||
((long)(bytes[9] & 0xFF) << 48) |
|
||||
((long)(bytes[10] & 0xFF) << 40) |
|
||||
((long)(bytes[11] & 0xFF) << 32) |
|
||||
((long)(bytes[12] & 0xFF) << 24) |
|
||||
((long)(bytes[13] & 0xFF) << 16) |
|
||||
((long)(bytes[14] & 0xFF) << 8) |
|
||||
((long)(bytes[15] & 0xFF));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从两个long创建IPv6地址
|
||||
*/
|
||||
public static IPv6Address valueOf(long high, long low) {
|
||||
return new IPv6Address(high, low);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从byte[16]创建IPv6地址(高性能版本)
|
||||
*/
|
||||
public static IPv6Address valueOf(byte[] bytes) {
|
||||
return new IPv6Address(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从ByteBuffer创建IPv6地址(零拷贝友好)
|
||||
*/
|
||||
public static IPv6Address valueOf(ByteBuffer buffer) {
|
||||
if (buffer.remaining() < 16) {
|
||||
throw new IllegalArgumentException("Buffer must have at least 16 bytes remaining");
|
||||
}
|
||||
|
||||
long high = buffer.getLong();
|
||||
long low = buffer.getLong();
|
||||
return valueOf(high, low);
|
||||
}
|
||||
|
||||
|
||||
public static IPv6Address valueOf(int offset, ByteBuffer buffer) {
|
||||
long high = buffer.getLong(offset);
|
||||
long low = buffer.getLong(offset+8);
|
||||
return valueOf(high, low);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从字符串解析IPv6地址(高性能版本)
|
||||
* @throws UnknownHostException
|
||||
*/
|
||||
public static IPv6Address valueOf(String ipString) throws UnknownHostException {
|
||||
if (ipString == null || ipString.isEmpty()) {
|
||||
throw new IllegalArgumentException("Invalid IPv6 address string");
|
||||
}
|
||||
|
||||
return new IPv6Address((Inet6Address)Inet6Address.getByName(ipString));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 从Java InetAddress转换
|
||||
*/
|
||||
public static IPv6Address valueOf(InetAddress inetAddress) {
|
||||
if (inetAddress == null) {
|
||||
throw new IllegalArgumentException("InetAddress cannot be null");
|
||||
}
|
||||
|
||||
byte[] bytes = inetAddress.getAddress();
|
||||
if (bytes.length == 4) {
|
||||
// IPv4地址,转换为IPv4映射的IPv6地址
|
||||
return valueOf(IPV4_MAPPED_HIGH,
|
||||
IPV4_MAPPED_LOW_PREFIX |
|
||||
(((long)(bytes[0] & 0xFF) << 24) |
|
||||
((bytes[1] & 0xFF) << 16) |
|
||||
((bytes[2] & 0xFF) << 8) |
|
||||
(bytes[3] & 0xFF)));
|
||||
}
|
||||
|
||||
return valueOf(bytes);
|
||||
}
|
||||
|
||||
// 核心getter方法
|
||||
public long getHigh() {
|
||||
return high;
|
||||
}
|
||||
|
||||
public long getLow() {
|
||||
return low;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为byte[16](需要时使用)
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] bytes = new byte[16];
|
||||
toByteArray(bytes, 0);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入到现有byte数组(避免创建新对象)
|
||||
*/
|
||||
public void toByteArray(byte[] dest, int offset) {
|
||||
if (dest.length - offset < 16) {
|
||||
throw new IllegalArgumentException("Destination array too small");
|
||||
}
|
||||
|
||||
dest[offset] = (byte) (high >> 56);
|
||||
dest[offset + 1] = (byte) (high >> 48);
|
||||
dest[offset + 2] = (byte) (high >> 40);
|
||||
dest[offset + 3] = (byte) (high >> 32);
|
||||
dest[offset + 4] = (byte) (high >> 24);
|
||||
dest[offset + 5] = (byte) (high >> 16);
|
||||
dest[offset + 6] = (byte) (high >> 8);
|
||||
dest[offset + 7] = (byte) high;
|
||||
|
||||
dest[offset + 8] = (byte) (low >> 56);
|
||||
dest[offset + 9] = (byte) (low >> 48);
|
||||
dest[offset + 10] = (byte) (low >> 40);
|
||||
dest[offset + 11] = (byte) (low >> 32);
|
||||
dest[offset + 12] = (byte) (low >> 24);
|
||||
dest[offset + 13] = (byte) (low >> 16);
|
||||
dest[offset + 14] = (byte) (low >> 8);
|
||||
dest[offset + 15] = (byte) low;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入到ByteBuffer(高性能网络操作)
|
||||
*/
|
||||
public void writeTo(ByteBuffer buffer) {
|
||||
buffer.putLong(high);
|
||||
buffer.putLong(low);
|
||||
}
|
||||
|
||||
|
||||
public void writeTo(int offset, ByteBuffer buffer) {
|
||||
buffer.putLong(offset,high);
|
||||
buffer.putLong(offset+8,low);
|
||||
}
|
||||
/**
|
||||
* 转换为标准IPv6字符串表示
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
try {
|
||||
return Inet6Address.getByAddress(toByteArray()).getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
return "Internal Error";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换为压缩形式的字符串(::格式)
|
||||
*/
|
||||
public String toCompressedString() {
|
||||
return KLALBUtils.parseAbbrIPv6(toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为IPv4映射地址
|
||||
*/
|
||||
public boolean isIPv4MappedAddress() {
|
||||
return high == IPV4_MAPPED_HIGH &&
|
||||
(low & 0x0000_0000_FFFF_0000L) == IPV4_MAPPED_LOW_PREFIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果这是IPv4映射地址,提取IPv4部分
|
||||
*/
|
||||
public byte[] getIPv4Bytes() {
|
||||
if (!isIPv4MappedAddress()) {
|
||||
throw new IllegalStateException("Not an IPv4 mapped address");
|
||||
}
|
||||
|
||||
byte[] ipv4 = new byte[4];
|
||||
ipv4[0] = (byte) (low >> 24);
|
||||
ipv4[1] = (byte) (low >> 16);
|
||||
ipv4[2] = (byte) (low >> 8);
|
||||
ipv4[3] = (byte) low;
|
||||
|
||||
return ipv4;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为多播地址
|
||||
*/
|
||||
public boolean isMulticastAddress() {
|
||||
return (high & 0xFF00_0000_0000_0000L) == 0xFF00_0000_0000_0000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为链路本地地址
|
||||
*/
|
||||
public boolean isLinkLocalAddress() {
|
||||
return (high & 0xFFC0_0000_0000_0000L) == 0xFE80_0000_0000_0000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为站点本地地址(已弃用,但为了兼容性保留)
|
||||
*/
|
||||
public boolean isSiteLocalAddress() {
|
||||
return (high & 0xFFC0_0000_0000_0000L) == 0xFEC0_0000_0000_0000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为唯一本地地址 (ULA)
|
||||
*/
|
||||
public boolean isUniqueLocalAddress() {
|
||||
return (high & 0xFE00_0000_0000_0000L) == 0xFC00_0000_0000_0000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为环回地址
|
||||
*/
|
||||
public boolean isLoopbackAddress() {
|
||||
return this.equals(LOOPBACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为未指定地址
|
||||
*/
|
||||
public boolean isUnspecifiedAddress() {
|
||||
return this.equals(UNSPECIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取多播地址的scope
|
||||
*/
|
||||
public int getMulticastScope() {
|
||||
if (!isMulticastAddress()) {
|
||||
return -1;
|
||||
}
|
||||
return (int) ((low >> 48) & 0x0F);
|
||||
}
|
||||
|
||||
// 路由表相关的实用方法
|
||||
|
||||
/**
|
||||
* 创建掩码(用于CIDR表示法)
|
||||
*/
|
||||
public static IPv6Address createMask(int prefixLength) {
|
||||
if (prefixLength < 0 || prefixLength > 128) {
|
||||
throw new IllegalArgumentException("Prefix length must be between 0 and 128");
|
||||
}
|
||||
|
||||
long maskHigh, maskLow;
|
||||
if (prefixLength == 128) {
|
||||
maskHigh = -1L; // 0xFFFFFFFF_FFFFFFFF
|
||||
maskLow = -1L;
|
||||
} else if (prefixLength > 64) {
|
||||
maskHigh = -1L;
|
||||
maskLow = (-1L) << (64 - (prefixLength - 64));
|
||||
} else if (prefixLength == 64) {
|
||||
maskHigh = -1L;
|
||||
maskLow = 0;
|
||||
} else {
|
||||
maskHigh = (-1L) << (64 - prefixLength);
|
||||
maskLow = 0;
|
||||
}
|
||||
|
||||
return valueOf(maskHigh, maskLow);
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用掩码(用于网络地址计算)
|
||||
*/
|
||||
public IPv6Address maskWith(IPv6Address mask) {
|
||||
return valueOf(high & mask.high, low & mask.low);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查地址是否在指定网络内
|
||||
*/
|
||||
public boolean isInNetwork(IPv6Address network, IPv6Address mask) {
|
||||
IPv6Address maskedThis = this.maskWith(mask);
|
||||
IPv6Address maskedNetwork = network.maskWith(mask);
|
||||
return maskedThis.equals(maskedNetwork);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查地址是否在指定CIDR网络内
|
||||
*/
|
||||
public boolean isInNetwork(IPv6Address network, int prefixLength) {
|
||||
IPv6Address mask = createMask(prefixLength);
|
||||
return isInNetwork(network, mask);
|
||||
}
|
||||
|
||||
// 比较和哈希
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null || getClass() != obj.getClass()) return false;
|
||||
|
||||
IPv6Address other = (IPv6Address) obj;
|
||||
return high == other.high && low == other.low;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// 优化的哈希计算,考虑long的分布
|
||||
return (int) (high ^ (high >>> 32) ^ low ^ (low >>> 32));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(IPv6Address other) {
|
||||
int highCompare = Long.compareUnsigned(high, other.high);
|
||||
if (highCompare != 0) return highCompare;
|
||||
return Long.compareUnsigned(low, other.low);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws UnknownHostException {
|
||||
// 创建IPv6地址
|
||||
IPv6Address addr1 = IPv6Address.valueOf("2001:db8::1");
|
||||
IPv6Address addr2 = IPv6Address.valueOf(0x20010DB800000000L, 0x0000000000000001L);
|
||||
|
||||
// 高性能路由表查找
|
||||
IPv6Address target = IPv6Address.valueOf("2001:db8:1234::5678");
|
||||
IPv6Address network = IPv6Address.valueOf("2001:db8:1234::");
|
||||
int prefixLength = 64;
|
||||
|
||||
if (target.isInNetwork(network, prefixLength)) {
|
||||
System.out.println("地址在目标网络内");
|
||||
}
|
||||
|
||||
// 转换为字节数组(需要时)
|
||||
byte[] bytes = addr1.toByteArray();
|
||||
|
||||
// 直接写入ByteBuffer(零拷贝)
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(16);
|
||||
addr1.writeTo(buffer);
|
||||
|
||||
}
|
||||
|
||||
public Inet6Address toInet6Address() {
|
||||
try {
|
||||
return (Inet6Address) Inet6Address.getByAddress(toByteArray());
|
||||
} catch (UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAnyLocalAddress() {
|
||||
return high==0&&low==0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class IPv6AddressGroup implements Comparable<IPv6AddressGroup>{
|
||||
|
||||
public IPv6AddressGroup(IPv6Address address) {
|
||||
this(address, 128);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return address+"/"+prefixLength;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(address, prefixLength);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
IPv6AddressGroup other = (IPv6AddressGroup) obj;
|
||||
return Objects.equals(address, other.address) && prefixLength == other.prefixLength;
|
||||
}
|
||||
public IPv6AddressGroup(IPv6Address address, int prefixLength) {
|
||||
super();
|
||||
this.address = address;
|
||||
this.prefixLength = prefixLength;
|
||||
}
|
||||
public IPv6AddressGroup(DataInputStream in) throws IOException {
|
||||
readFromStream(in);
|
||||
}
|
||||
private IPv6Address address;
|
||||
private int prefixLength=128;
|
||||
public IPv6Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
public int getPrefixLength() {
|
||||
return prefixLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(IPv6AddressGroup o) {
|
||||
return -Integer.compare(prefixLength, o.prefixLength);
|
||||
}
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
out.writeLong(address.getHigh());
|
||||
out.writeLong(address.getLow());
|
||||
out.write(prefixLength);
|
||||
}
|
||||
public void readFromStream(DataInputStream in) throws IOException {
|
||||
long high=in.readLong();
|
||||
long low=in.readLong();
|
||||
address=new IPv6Address(high,low);
|
||||
prefixLength=in.read();
|
||||
}
|
||||
public boolean checkMatch(IPv6Address address2) {
|
||||
return address2.equals(address.maskWith(IPv6Address.createMask(prefixLength)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,6 +13,8 @@ public class IPv6HopByHopTLV extends TLV {
|
||||
public static final int PADN = 1;
|
||||
public static final int JUMBO_PAYLOAD = 0xC2;
|
||||
public static final int ROUTER_ALERT = 0x05;
|
||||
public static final int KLALB_OAM = 0x3E;
|
||||
public static final int KLALB_PASSPORT = 0x1E;
|
||||
|
||||
public IPv6HopByHopTLV(ByteBuffer header) {
|
||||
this(header, true);
|
||||
@@ -62,6 +64,16 @@ public class IPv6HopByHopTLV extends TLV {
|
||||
htlv = new JumboPayloadHopByHopTLV(bbf, true);
|
||||
htlv.readFromChannel(din, 0);
|
||||
return htlv;
|
||||
case KLALB_OAM:
|
||||
// KLALB OAM
|
||||
htlv = new KLALBOAMHopByHopTLV(bbf);
|
||||
htlv.readFromChannel(din, 0);
|
||||
return htlv;
|
||||
case KLALB_PASSPORT:
|
||||
// KLALB Passport
|
||||
htlv = new KLALBPassportHopByHopTLV(bbf);
|
||||
htlv.readFromChannel(din, 0);
|
||||
return htlv;
|
||||
default:
|
||||
// 未知类型: 假设有数据部分
|
||||
htlv = new IPv6HopByHopTLV(bbf, true);
|
||||
|
||||
@@ -5,29 +5,29 @@ import java.net.Inet6Address;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||
import org.kne.cloud.network.klalb.KLALBPacket;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
|
||||
import org.kne.cloud.network.srv6.SRv6Router;
|
||||
|
||||
public interface IPv6NetworkLink {
|
||||
public SRv6Router getSrv6Router() ;
|
||||
|
||||
public void setSRv6Router(SRv6Router srv6Router) ;
|
||||
public boolean isLoopBack();
|
||||
public List<Inet6AddressGroup> getAddressGroups();
|
||||
public List<IPv6AddressGroup> getAddressGroups();
|
||||
public List<Neighbor> getNeighborsInfo();
|
||||
public List<RouteItem> getRouteItems();
|
||||
public void sendPacket(IPv6Packet pack, Inet6Address inet6Address) throws IOException;
|
||||
public boolean isCongress(IPv6Packet iPv6Packet,double scale);
|
||||
public default boolean isCongress(IPv6Packet iPv6Packet) {
|
||||
return isCongress(iPv6Packet, 1.0);
|
||||
}
|
||||
public void sendPacket(IPv6Packet pack, IPv6Address inet6Address) throws IOException;
|
||||
public String getName();
|
||||
public boolean isUp();
|
||||
public void setReceiveConsumer(Consumer<IPv6Packet>con);
|
||||
void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer);
|
||||
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet);
|
||||
public void setCongressCondition(Lock lock,Condition condition);
|
||||
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> srhReceive);
|
||||
public void addIPv6LinkStateListener(IPv6LinkStateListener listener);
|
||||
public void removeIPv6LinkStateListener(IPv6LinkStateListener listener);
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.nio.channels.WritableByteChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -35,6 +36,8 @@ import org.pcap4j.packet.namednumber.IpNumber;
|
||||
*/
|
||||
public class IPv6Packet extends NetworkPacket {
|
||||
|
||||
private static final boolean debug=false;
|
||||
|
||||
// ==================== IPv6扩展头类型 ====================
|
||||
|
||||
/** 逐跳选项头 - RFC 8200 */
|
||||
@@ -238,17 +241,6 @@ public class IPv6Packet extends NetworkPacket {
|
||||
this.previousLink = previousLink;
|
||||
}
|
||||
|
||||
// 流序列标记,用于标识数据包在流中的顺序
|
||||
private long flowSeqMark = -1;
|
||||
|
||||
public long getFlowSeqMark() {
|
||||
return flowSeqMark;
|
||||
}
|
||||
|
||||
public void setFlowSeqMark(long flowSeqMark) {
|
||||
this.flowSeqMark = flowSeqMark;
|
||||
}
|
||||
|
||||
// TTL是否已减少的标志
|
||||
private boolean TTLdecreased = false;
|
||||
|
||||
@@ -261,14 +253,19 @@ public class IPv6Packet extends NetworkPacket {
|
||||
}
|
||||
|
||||
// IPv6头部数据缓冲区
|
||||
private volatile ByteBuffer IPv6header;
|
||||
private ByteBuffer IPv6header;
|
||||
|
||||
private IPv6HopByHopHeader hopByHopHeader;
|
||||
|
||||
private IPv6RoutingHeader routingHeader;
|
||||
|
||||
// IPv6扩展头部列表
|
||||
private volatile List<IPv6ExtHeader> headers = new ArrayList<>();
|
||||
private List<IPv6ExtHeader> headers = new ArrayList<>();
|
||||
|
||||
// IPv6负载数据
|
||||
private IPv6Payload payload;
|
||||
|
||||
|
||||
// IPv6头部固定长度
|
||||
public static final int IPv6_HEADER_LENGTH = 40;
|
||||
|
||||
@@ -289,7 +286,6 @@ public class IPv6Packet extends NetworkPacket {
|
||||
*/
|
||||
public IPv6Packet() {
|
||||
IPv6header = NetworkPacket.bufferAllocator.allocate(IPv6_HEADER_LENGTH);
|
||||
IPv6header.limit(IPv6_HEADER_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -354,7 +350,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
*/
|
||||
public void markCE() {
|
||||
IPv6header.put(1, (byte) (IPv6header.get(1) | 0b00110000));
|
||||
// new Exception().printStackTrace();
|
||||
// new Exception().printStackTrace();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -434,7 +430,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* 获取原始源地址字节数组
|
||||
* @param sourceAddress 用于存储源地址的字节数组
|
||||
*/
|
||||
public void getRawSourceAddress(byte[] sourceAddress) {
|
||||
public void getRawSourceAddressArray(byte[] sourceAddress) {
|
||||
IPv6header.get(SOURCE_ADDRESS_OFFSET, sourceAddress, 0, sourceAddress.length);
|
||||
}
|
||||
|
||||
@@ -442,21 +438,15 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* 设置原始源地址字节数组
|
||||
* @param sourceAddress 源地址字节数组
|
||||
*/
|
||||
public void setRawSourceAddress(byte[] sourceAddress) {
|
||||
public void setRawSourceAddressArray(byte[] sourceAddress) {
|
||||
IPv6header.put(SOURCE_ADDRESS_OFFSET, sourceAddress, 0, sourceAddress.length);
|
||||
}
|
||||
|
||||
public IPv6RouteTableKey getSourceRouteTableKey() {
|
||||
long most=IPv6header.getLong(SOURCE_ADDRESS_OFFSET);
|
||||
long least=IPv6header.getLong(SOURCE_ADDRESS_OFFSET+8);
|
||||
return new IPv6RouteTableKey(most, least);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原始目标地址字节数组
|
||||
* @param destinationAddress 用于存储目标地址的字节数组
|
||||
*/
|
||||
public void getRawDestinationAddress(byte[] destinationAddress) {
|
||||
public void getRawDestinationAddressArray(byte[] destinationAddress) {
|
||||
IPv6header.get(DESTINATION_ADDRESS_OFFSET, destinationAddress, 0, destinationAddress.length);
|
||||
|
||||
}
|
||||
@@ -465,22 +455,49 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* 设置原始目标地址字节数组
|
||||
* @param destinationAddress 目标地址字节数组
|
||||
*/
|
||||
public void setRawDestinationAddress(byte[] destinationAddress) {
|
||||
public void setRawDestinationAddressArray(byte[] destinationAddress) {
|
||||
IPv6header.put(DESTINATION_ADDRESS_OFFSET, destinationAddress, 0, destinationAddress.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原始源地址字节数组
|
||||
* @param sourceAddress 用于存储源地址的字节数组
|
||||
* @return
|
||||
*/
|
||||
public IPv6Address getSourceAddress() {
|
||||
return IPv6Address.valueOf(SOURCE_ADDRESS_OFFSET,IPv6header);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置原始源地址字节数组
|
||||
* @param sourceAddress 源地址字节数组
|
||||
*/
|
||||
public void setSourceAddress(IPv6Address sourceAddress) {
|
||||
sourceAddress.writeTo(SOURCE_ADDRESS_OFFSET,IPv6header);
|
||||
}
|
||||
|
||||
public IPv6RouteTableKey getDestinationRouteTableKey() {
|
||||
long most=IPv6header.getLong(DESTINATION_ADDRESS_OFFSET);
|
||||
long least=IPv6header.getLong(DESTINATION_ADDRESS_OFFSET+8);
|
||||
return new IPv6RouteTableKey(most, least);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取原始目标地址字节数组
|
||||
* @param destinationAddress 用于存储目标地址的字节数组
|
||||
*/
|
||||
public IPv6Address getDestinationAddress() {
|
||||
return IPv6Address.valueOf(DESTINATION_ADDRESS_OFFSET,IPv6header);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置原始目标地址字节数组
|
||||
* @param destinationAddress 目标地址字节数组
|
||||
*/
|
||||
public void setDestinationAddress(IPv6Address destinationAddress) {
|
||||
destinationAddress.writeTo(DESTINATION_ADDRESS_OFFSET,IPv6header);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取源地址
|
||||
* @return 源地址
|
||||
*/
|
||||
public Inet6Address getSourceAddress() {
|
||||
public Inet6Address getSourceAddress2() {
|
||||
byte[] b = new byte[IPV6_ADDRESS_LENGTH];
|
||||
IPv6header.get(SOURCE_ADDRESS_OFFSET, b, 0, b.length);
|
||||
try {
|
||||
@@ -494,7 +511,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* 设置源地址
|
||||
* @param sourceAddress 源地址
|
||||
*/
|
||||
public void setSourceAddress(Inet6Address sourceAddress) {
|
||||
public void setSourceAddress2(Inet6Address sourceAddress) {
|
||||
byte[] b = sourceAddress.getAddress();
|
||||
IPv6header.put(SOURCE_ADDRESS_OFFSET, b, 0, b.length);
|
||||
}
|
||||
@@ -503,7 +520,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* 获取目标地址
|
||||
* @return 目标地址
|
||||
*/
|
||||
public Inet6Address getDestinationAddress() {
|
||||
public Inet6Address getDestinationAddress2() {
|
||||
byte[] b = new byte[IPV6_ADDRESS_LENGTH];
|
||||
IPv6header.get(DESTINATION_ADDRESS_OFFSET, b, 0, b.length);
|
||||
try {
|
||||
@@ -517,7 +534,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* 设置目标地址
|
||||
* @param destinationAddress 目标地址
|
||||
*/
|
||||
public void setDestinationAddress(Inet6Address destinationAddress) {
|
||||
public void setDestinationAddress2(Inet6Address destinationAddress) {
|
||||
byte[] b = destinationAddress.getAddress();
|
||||
IPv6header.put(DESTINATION_ADDRESS_OFFSET, b, 0, b.length);
|
||||
}
|
||||
@@ -539,7 +556,11 @@ public class IPv6Packet extends NetworkPacket {
|
||||
private int calcPayloadLength() {
|
||||
int lth = 0;
|
||||
for (int i = 0; i < headers.size(); i++) {
|
||||
lth += headers.get(i).getTotalLength();
|
||||
int extHeaderLength=(int) headers.get(i).getTotalLength();
|
||||
if(extHeaderLength<=0) {
|
||||
throw new IllegalArgumentException("extHeaderLength:"+extHeaderLength+"<0");
|
||||
}
|
||||
lth += extHeaderLength;
|
||||
}
|
||||
lth += payload.getTotalLength();
|
||||
return lth;
|
||||
@@ -578,6 +599,9 @@ public class IPv6Packet extends NetworkPacket {
|
||||
exth.writeToChannel(dto);
|
||||
}
|
||||
payload.writeToChannel(dto);
|
||||
|
||||
if(debug)
|
||||
debug("send");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -607,6 +631,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
nextheader = ext.getNextHeader();
|
||||
payloadlength -= ext.getTotalLength();
|
||||
headers.add(ext);
|
||||
hopByHopHeader=(IPv6HopByHopHeader) ext;
|
||||
break;
|
||||
case DESTINATION_OPTIONS: // 目标选项头部
|
||||
ext = new IPv6DestinationHeader();
|
||||
@@ -637,6 +662,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
nextheader = ext.getNextHeader();
|
||||
payloadlength -= ext.getTotalLength();
|
||||
headers.add(ext);
|
||||
routingHeader=(IPv6RoutingHeader) ext;
|
||||
break;
|
||||
case FRAGMENT: // 分段头部
|
||||
ext = new IPv6ExtHeader(nextheader);
|
||||
@@ -666,12 +692,16 @@ public class IPv6Packet extends NetworkPacket {
|
||||
payloadlength -= ext.getTotalLength();
|
||||
headers.add(ext);
|
||||
break;
|
||||
|
||||
case ICMPv6:
|
||||
ICMPv6Packet icmp=ICMPv6Packet.readICMPv6PacketFromChannel(din,payloadlength);
|
||||
icmp.setParent(this);
|
||||
this.payload=icmp;
|
||||
break loop;
|
||||
case UDP: // UDP协议
|
||||
UDPPacket up=new UDPPacket();
|
||||
up.setParent(this);
|
||||
up.readFromChannel(din,payloadlength);
|
||||
this.payload=up;
|
||||
UDPPacket udp=new UDPPacket();
|
||||
udp.setParent(this);
|
||||
udp.readFromChannel(din,payloadlength);
|
||||
this.payload=udp;
|
||||
break loop;
|
||||
case KLALBPacket.KLALB_PROTOCOL_NUMBER: // KLALB协议
|
||||
KLALBPacket kp = KLALBPacket.readKLALBPacketFromChannel(din);
|
||||
@@ -689,9 +719,24 @@ public class IPv6Packet extends NetworkPacket {
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
|
||||
if(debug)
|
||||
debug("recv");
|
||||
}
|
||||
|
||||
private void debug(String description) {
|
||||
StringBuilder sb=new StringBuilder();
|
||||
sb.append(description);
|
||||
sb.append(" total:");
|
||||
sb.append(getPayloadLength());
|
||||
sb.append(" ");
|
||||
for (IPv6ExtHeader iPv6ExtHeader : headers) {
|
||||
sb.append(iPv6ExtHeader.getTotalLength());
|
||||
sb.append(' ');
|
||||
}
|
||||
if(payload!=null)
|
||||
sb.append(payload.getTotalLength());
|
||||
System.out.println(sb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 转换为字符串表示
|
||||
@@ -1062,7 +1107,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
*/
|
||||
public static class IPv6SegmentRoutingHeader extends IPv6RoutingHeader {
|
||||
|
||||
private final List<Inet6Address> addresses = new ArrayList<Inet6Address>();
|
||||
private final List<IPv6Address> addresses = new ArrayList<IPv6Address>();
|
||||
private final List<IPv6SegmentRoutingTLV> tlvs = new ArrayList<IPv6SegmentRoutingTLV>();
|
||||
|
||||
@Override
|
||||
@@ -1083,7 +1128,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
super(EXT_HEADER_ALIGNMENT, bbf);
|
||||
}
|
||||
|
||||
public IPv6SegmentRoutingHeader(List<Inet6Address> segs) {
|
||||
public IPv6SegmentRoutingHeader(List<IPv6Address> segs) {
|
||||
this();
|
||||
this.addresses.addAll(segs);
|
||||
int ln = addresses.size() - 1;
|
||||
@@ -1115,7 +1160,7 @@ public class IPv6Packet extends NetworkPacket {
|
||||
getData().putShort(6, (short) tag);
|
||||
}
|
||||
|
||||
public List<Inet6Address> getAddresses() {
|
||||
public List<IPv6Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
@@ -1134,9 +1179,12 @@ public class IPv6Packet extends NetworkPacket {
|
||||
setLastEntry(addresses.size() - 1);
|
||||
super.writeToChannel(dto);
|
||||
|
||||
for (Inet6Address inet6Address : addresses) {
|
||||
dto.write(ByteBuffer.wrap(inet6Address.getAddress()));
|
||||
ByteBuffer addr=NetworkPacket.bufferAllocator.allocateHeap(addresses.size() *IPV6_ADDRESS_LENGTH);
|
||||
for (IPv6Address inet6Address : addresses) {
|
||||
inet6Address.writeTo(addr);
|
||||
}
|
||||
addr.flip();
|
||||
dto.write(addr);
|
||||
for (IPv6SegmentRoutingTLV tlv : tlvs) {
|
||||
IPv6SegmentRoutingTLV.writeIPv6SegmentRoutingTLVToChannel(dto, tlv);
|
||||
}
|
||||
@@ -1200,15 +1248,12 @@ public class IPv6Packet extends NetworkPacket {
|
||||
}
|
||||
|
||||
addresses.clear();
|
||||
bfr = NetworkPacket.bufferAllocator.allocateHeap(IPV6_ADDRESS_LENGTH);
|
||||
|
||||
for (int i = 0; i <= laste; i++) { // 注意:应该是 <= laste
|
||||
bfr.clear();
|
||||
KNEChannels.readFully(din, bfr);
|
||||
bfr.flip();
|
||||
bfr = NetworkPacket.bufferAllocator.allocateHeap(IPV6_ADDRESS_LENGTH*(laste+1));
|
||||
KNEChannels.readFully(din, bfr);
|
||||
bfr.flip();
|
||||
usdl += bfr.limit();
|
||||
Inet6Address addr = (Inet6Address) Inet6Address.getByAddress(bfr.array());
|
||||
addresses.add(addr);
|
||||
for (int i = 0; i <= laste; i++) { // 注意:应该是 <= laste
|
||||
addresses.add(IPv6Address.valueOf(bfr));
|
||||
}
|
||||
|
||||
tlvs.clear();
|
||||
@@ -1290,38 +1335,59 @@ public class IPv6Packet extends NetworkPacket {
|
||||
* @return IPv6段逐跳头部,如果不存在则返回null
|
||||
*/
|
||||
public IPv6HopByHopHeader getHopByHopHeader() {
|
||||
IPv6HopByHopHeader hoph = null;
|
||||
List<IPv6ExtHeader> exhs = headers;
|
||||
for (int j = 0; j < exhs.size(); j++) {
|
||||
IPv6ExtHeader exh = exhs.get(j);
|
||||
if (exh instanceof IPv6HopByHopHeader) {
|
||||
hoph=(IPv6HopByHopHeader) exh;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hoph;
|
||||
return hopByHopHeader;
|
||||
}
|
||||
/**
|
||||
* 获取路由头部
|
||||
* @return 路由头部,如果不存在则返回null
|
||||
*/
|
||||
public IPv6RoutingHeader getRoutingHeader() {
|
||||
return routingHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
|
||||
public void setHopByHopHeader(IPv6HopByHopHeader hopByHopHeader) {
|
||||
this.hopByHopHeader = hopByHopHeader;
|
||||
}
|
||||
|
||||
public void setRoutingHeader(IPv6RoutingHeader routingHeader) {
|
||||
this.routingHeader = routingHeader;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取SRv6段路由头部
|
||||
* @return SRv6段路由头部,如果不存在则返回null
|
||||
*/
|
||||
public IPv6SegmentRoutingHeader getSRHHeader() {
|
||||
IPv6SegmentRoutingHeader srhh = null;
|
||||
List<IPv6ExtHeader> exhs = headers;
|
||||
for (int j = 0; j < exhs.size(); j++) {
|
||||
IPv6ExtHeader exh = exhs.get(j);
|
||||
if (exh instanceof IPv6SegmentRoutingHeader) {
|
||||
if (((IPv6SegmentRoutingHeader) exh).getRoutingType() == SRV6_ROUTING_TYPE) {
|
||||
srhh = (IPv6SegmentRoutingHeader) exh;
|
||||
break;
|
||||
public IPv6SegmentRoutingHeader getSegmentRoutingHeader() {
|
||||
IPv6RoutingHeader rh=getRoutingHeader();
|
||||
if(rh==null)
|
||||
return null;
|
||||
IPv6SegmentRoutingHeader srhh=null;
|
||||
if (rh instanceof IPv6SegmentRoutingHeader) {
|
||||
if (((IPv6SegmentRoutingHeader) rh).getRoutingType() == SRV6_ROUTING_TYPE) {
|
||||
srhh = (IPv6SegmentRoutingHeader) rh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return srhh;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public UUID getPacketID() {
|
||||
IPv6HopByHopHeader hop=getHopByHopHeader();
|
||||
if(hop==null)
|
||||
return null;
|
||||
List<IPv6HopByHopTLV> tlvs= hop.getTlvs();
|
||||
for(IPv6HopByHopTLV tlv:tlvs) {
|
||||
if(tlv instanceof KLALBOAMHopByHopTLV)
|
||||
return ((KLALBOAMHopByHopTLV)tlv).getUUID();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean needEndPosition() {
|
||||
return false;
|
||||
@@ -1334,16 +1400,21 @@ public class IPv6Packet extends NetworkPacket {
|
||||
return rerouteCounter;
|
||||
}
|
||||
|
||||
// 承诺标志,用于某种状态跟踪
|
||||
private volatile boolean promise = true;
|
||||
public long calculateAddressChecksum() {
|
||||
long sum=0;
|
||||
|
||||
ByteBuffer dataCopy = IPv6header.slice(SOURCE_ADDRESS_OFFSET,32);
|
||||
|
||||
while (dataCopy.remaining() >= 2) {
|
||||
sum += dataCopy.getChar();
|
||||
}
|
||||
|
||||
if (dataCopy.remaining() == 1) {
|
||||
sum += (dataCopy.get() & 0xFF) << 8;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
public void setPromise(boolean b) {
|
||||
promise = b;
|
||||
}
|
||||
|
||||
public boolean isPromise() {
|
||||
return promise;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.util.Objects;
|
||||
|
||||
public class IPv6RouteTableKey {
|
||||
private long most;
|
||||
private long least;
|
||||
|
||||
public IPv6RouteTableKey(byte[] address) {
|
||||
long[] l = inet6AddressToLongs(address);
|
||||
this.most = l[0];
|
||||
this.least = l[1]; // 修复:应该是 l[1] 而不是 l[0]
|
||||
}
|
||||
|
||||
public IPv6RouteTableKey(long most, long least) {
|
||||
super();
|
||||
this.most = most;
|
||||
this.least = least;
|
||||
}
|
||||
|
||||
public IPv6RouteTableKey(Inet6Address address) {
|
||||
this(address.getAddress());
|
||||
}
|
||||
|
||||
public IPv6RouteTableKey(Inet6AddressGroup address) {
|
||||
this(address.getAddress());
|
||||
applyMask(address.getPrefixLength());
|
||||
}
|
||||
|
||||
public long getMost() {
|
||||
return most;
|
||||
}
|
||||
|
||||
public long getLeast() {
|
||||
return least;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (least ^ (least >>> 32));
|
||||
result = prime * result + (int) (most ^ (most >>> 32));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
IPv6RouteTableKey other = (IPv6RouteTableKey) obj;
|
||||
if (least != other.least)
|
||||
return false;
|
||||
if (most != other.most)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据前缀长度应用掩码,仅保留网络部分
|
||||
* @param prefixLength 前缀长度 (0-128)
|
||||
* @return 应用掩码后的新 IPv6RouteTableKey 对象
|
||||
*/
|
||||
public IPv6RouteTableKey mask(int prefixLength) {
|
||||
if (prefixLength < 0 || prefixLength > 128) {
|
||||
throw new IllegalArgumentException("前缀长度必须在 0 到 128 之间");
|
||||
}
|
||||
|
||||
if (prefixLength == 0) {
|
||||
return new IPv6RouteTableKey(0L, 0L); // 默认路由
|
||||
}
|
||||
|
||||
long maskedMost = this.most;
|
||||
long maskedLeast = this.least;
|
||||
|
||||
if (prefixLength <= 64) {
|
||||
// 仅影响高位
|
||||
long mask = createMask(prefixLength);
|
||||
maskedMost &= mask;
|
||||
maskedLeast = 0L; // 低位全部清零
|
||||
} else {
|
||||
// 影响高位和部分低位
|
||||
int lowPrefixLength = prefixLength - 64;
|
||||
long lowMask = createMask(lowPrefixLength);
|
||||
maskedLeast &= lowMask;
|
||||
// 高位保持不变
|
||||
}
|
||||
|
||||
return new IPv6RouteTableKey(maskedMost, maskedLeast);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据前缀长度应用掩码,仅保留网络部分
|
||||
* @param prefixLength 前缀长度 (0-128)
|
||||
* @return 应用掩码后的新 IPv6RouteTableKey 对象
|
||||
*/
|
||||
public void applyMask(int prefixLength) {
|
||||
if (prefixLength < 0 || prefixLength > 128) {
|
||||
throw new IllegalArgumentException("前缀长度必须在 0 到 128 之间");
|
||||
}
|
||||
|
||||
if (prefixLength == 0) {
|
||||
this.most=0;
|
||||
this.least=0;
|
||||
return;
|
||||
//return new IPv6RouteTableKey(0L, 0L); // 默认路由
|
||||
}
|
||||
|
||||
long maskedMost = this.most;
|
||||
long maskedLeast = this.least;
|
||||
|
||||
if (prefixLength <= 64) {
|
||||
// 仅影响高位
|
||||
long mask = createMask(prefixLength);
|
||||
maskedMost &= mask;
|
||||
maskedLeast = 0L; // 低位全部清零
|
||||
} else {
|
||||
// 影响高位和部分低位
|
||||
int lowPrefixLength = prefixLength - 64;
|
||||
long lowMask = createMask(lowPrefixLength);
|
||||
maskedLeast &= lowMask;
|
||||
// 高位保持不变
|
||||
}
|
||||
this.most=maskedMost;
|
||||
this.least=maskedLeast;
|
||||
// return new IPv6RouteTableKey(maskedMost, maskedLeast);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建指定长度的掩码
|
||||
* @param bits 要保留的位数 (0-64)
|
||||
* @return 掩码值
|
||||
*/
|
||||
private long createMask(int bits) {
|
||||
// 使用查表法,预先计算所有可能的掩码值
|
||||
return MASK_TABLE[bits];
|
||||
}
|
||||
|
||||
// 预计算的掩码表
|
||||
private static final long[] MASK_TABLE = new long[65]; // 0-64 共65个值
|
||||
|
||||
// 静态初始化块,在类加载时预计算所有掩码值
|
||||
static {
|
||||
for (int bits = 0; bits <= 64; bits++) {
|
||||
if (bits == 0) {
|
||||
MASK_TABLE[bits] = 0L;
|
||||
} else if (bits == 64) {
|
||||
MASK_TABLE[bits] = -1L;
|
||||
} else {
|
||||
MASK_TABLE[bits] = (-1L) << (64 - bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 byte[] 转换为两个 long 值(高位和低位)
|
||||
* @param bytes 16字节的IPv6地址
|
||||
* @return 包含两个long值的数组,第一个是高位,第二个是低位
|
||||
*/
|
||||
public static long[] inet6AddressToLongs(byte[] bytes) {
|
||||
if (bytes.length != 16) {
|
||||
throw new IllegalArgumentException("IPv6地址必须是16字节");
|
||||
}
|
||||
|
||||
long high = 0;
|
||||
long low = 0;
|
||||
|
||||
// 处理前8字节(高位)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
high = (high << 8) | (bytes[i] & 0xFF);
|
||||
}
|
||||
|
||||
// 处理后8字节(低位)
|
||||
for (int i = 8; i < 16; i++) {
|
||||
low = (low << 8) | (bytes[i] & 0xFF);
|
||||
}
|
||||
|
||||
return new long[]{high, low};
|
||||
}
|
||||
|
||||
/**
|
||||
* 将两个long值转换回byte[]
|
||||
* @param high 高位long值
|
||||
* @param low 低位long值
|
||||
* @return 16字节的IPv6地址
|
||||
*/
|
||||
public static byte[] longsToInet6Address(long high, long low) {
|
||||
byte[] bytes = new byte[16];
|
||||
|
||||
// 提取高位的8个字节
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bytes[i] = (byte) ((high >> (56 - i * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
// 提取低位的8个字节
|
||||
for (int i = 0; i < 8; i++) {
|
||||
bytes[8 + i] = (byte) ((low >> (56 - i * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%016x:%016x", most, least);
|
||||
}
|
||||
|
||||
/**
|
||||
* 单元测试
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
for(int i=0;i<65;i++) {
|
||||
long l=MASK_TABLE[i];
|
||||
System.out.println(Long.toUnsignedString(l, 16));
|
||||
}
|
||||
|
||||
System.out.println("开始 IPv6RouteTableKey 单元测试...");
|
||||
|
||||
// 测试1: 基本转换测试
|
||||
System.out.println("\n1. 测试基本转换:");
|
||||
byte[] testAddress = new byte[16];
|
||||
// 创建测试地址: 2001:0db8:85a3::8a2e:0370:7334
|
||||
testAddress[0] = 0x20; testAddress[1] = 0x01;
|
||||
testAddress[2] = 0x0d; testAddress[3] = (byte) 0xb8;
|
||||
testAddress[4] = (byte) 0x85; testAddress[5] = (byte) 0xa3;
|
||||
// 中间部分为0
|
||||
testAddress[12] = (byte) 0x8a; testAddress[13] = 0x2e;
|
||||
testAddress[14] = 0x03; testAddress[15] = 0x70;
|
||||
// testAddress[16] = 0x73; testAddress[17] = 0x34; // 注意: 数组只有16个元素
|
||||
|
||||
IPv6RouteTableKey key = new IPv6RouteTableKey(testAddress);
|
||||
System.out.println("原始地址: " + key);
|
||||
|
||||
// 测试2: 掩码应用测试
|
||||
System.out.println("\n2. 测试掩码应用:");
|
||||
IPv6RouteTableKey masked64 = key.mask(64);
|
||||
System.out.println("/64 掩码: " + masked64);
|
||||
|
||||
IPv6RouteTableKey masked48 = key.mask(48);
|
||||
System.out.println("/48 掩码: " + masked48);
|
||||
|
||||
IPv6RouteTableKey masked128 = key.mask(128);
|
||||
System.out.println("/128 掩码: " + masked128);
|
||||
|
||||
IPv6RouteTableKey masked0 = key.mask(0);
|
||||
System.out.println("/0 掩码: " + masked0);
|
||||
|
||||
// 测试3: 相等性测试
|
||||
System.out.println("\n3. 测试相等性:");
|
||||
IPv6RouteTableKey key2 = new IPv6RouteTableKey(testAddress);
|
||||
System.out.println("相同地址是否相等: " + key.equals(key2));
|
||||
System.out.println("哈希码是否相同: " + (key.hashCode() == key2.hashCode()));
|
||||
|
||||
// 测试4: 转换函数测试
|
||||
System.out.println("\n4. 测试转换函数:");
|
||||
long[] longs = inet6AddressToLongs(testAddress);
|
||||
System.out.println("转换为longs: " + Long.toHexString(longs[0]) + ":" + Long.toHexString(longs[1]));
|
||||
|
||||
byte[] reconverted = longsToInet6Address(longs[0], longs[1]);
|
||||
boolean conversionOk = true;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (testAddress[i] != reconverted[i]) {
|
||||
conversionOk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println("转换是否可逆: " + conversionOk);
|
||||
|
||||
// 测试5: 边界条件测试
|
||||
System.out.println("\n5. 测试边界条件:");
|
||||
try {
|
||||
key.applyMask(-1);
|
||||
System.out.println("错误: 应该抛出异常");
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("正确: 负前缀长度抛出异常");
|
||||
}
|
||||
|
||||
try {
|
||||
key.applyMask(129);
|
||||
System.out.println("错误: 应该抛出异常");
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("正确: 过大前缀长度抛出异常");
|
||||
}
|
||||
|
||||
// 测试6: 全零和全一地址测试
|
||||
System.out.println("\n6. 测试特殊地址:");
|
||||
byte[] allZeros = new byte[16];
|
||||
IPv6RouteTableKey zeroKey = new IPv6RouteTableKey(allZeros);
|
||||
System.out.println("全零地址: " + zeroKey);
|
||||
|
||||
byte[] allOnes = new byte[16];
|
||||
for (int i = 0; i < 16; i++) allOnes[i] = (byte) 0xFF;
|
||||
IPv6RouteTableKey onesKey = new IPv6RouteTableKey(allOnes);
|
||||
System.out.println("全一地址: " + onesKey);
|
||||
|
||||
System.out.println("\n所有测试完成!");
|
||||
}
|
||||
}
|
||||
@@ -2,156 +2,147 @@ package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6HopByHopHeader;
|
||||
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.klalb.CONST;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
|
||||
import org.kne.cloud.network.srv6.DetNetSRv6TLV;
|
||||
import org.kne.cloud.network.srv6.IPv6SegmentRoutingTLV;
|
||||
import org.kne.cloud.network.srv6.IpV6RoutingSRHData;
|
||||
import org.kne.cloud.network.srv6.PacketConsumer;
|
||||
import org.kne.cloud.network.srv6.PacketReorder;
|
||||
import org.kne.cloud.network.srv6.SEQSSegmentRoutingTLV;
|
||||
import org.kne.cloud.network.srv6.SRv6PacketReorder;
|
||||
import org.kne.cloud.network.srv6.SRv6PacketSeqMarker;
|
||||
import org.kne.cloud.network.srv6.SRv6Router;
|
||||
import org.kne.cloud.network.srv6.SRv6StreamSequenceTLV;
|
||||
import org.kne.cloud.network.srv6.SRv6TLV;
|
||||
import org.kne.cloud.network.srv6.TCPTransimitAgent;
|
||||
import org.kne.cloud.network.tun.InetAddressRow;
|
||||
import org.kne.cloud.network.tun.TUNChannel;
|
||||
import org.kne.cloud.network.tun.TUNNetworkDevice;
|
||||
import org.kne.concurrent.DisruptorExecutor;
|
||||
import org.kne.concurrent.HighPerformanceExecutor;
|
||||
import org.kne.concurrent.SpinLock;
|
||||
import org.kne.io.KNEChannels;
|
||||
|
||||
public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implements IPv6NetworkLink, Closeable, AutoCloseable {
|
||||
public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink
|
||||
implements IPv6NetworkLink, Closeable, AutoCloseable {
|
||||
|
||||
public static final String KLALB_DECENTRALIZED_S_RV6_NETWORK = "KLALB Decentralized SRv6 Network";
|
||||
|
||||
public static final String KLALB_S_RV6 = "KLALB SRv6";
|
||||
|
||||
private TUNNetworkDevice tun;
|
||||
|
||||
private Inet6AddressGroup hostAddress;
|
||||
private IPv6AddressGroup hostAddress;
|
||||
|
||||
private Thread tr;
|
||||
|
||||
private Lock slok=new SpinLock();
|
||||
|
||||
private SRv6PacketSeqMarker seqm=new SRv6PacketSeqMarker();
|
||||
|
||||
public IPv6TUNLoopbackNetworkLink(Inet6AddressGroup hostAddress, int mtu,List<InetAddress>dns) throws IOException {
|
||||
private Lock slok = new SpinLock();
|
||||
|
||||
public IPv6TUNLoopbackNetworkLink(String name,IPv6AddressGroup hostAddress, int mtu, List<InetAddress> dns) throws IOException {
|
||||
if (tun != null)
|
||||
throw new IllegalStateException("already open!");
|
||||
try {
|
||||
tun = TUNNetworkDevice.createDevice(KLALB_S_RV6, KLALB_DECENTRALIZED_S_RV6_NETWORK);
|
||||
tun.open();
|
||||
tun.setStatus(true);
|
||||
this.hostAddress = hostAddress;
|
||||
if (hostAddress != null)
|
||||
tun.setIPAddress(hostAddress.getAddress(), hostAddress.getPrefixLength());
|
||||
if(dns!=null) {
|
||||
tun.setDNSAddress(dns);
|
||||
}
|
||||
try {
|
||||
tun.setMTU(mtu);
|
||||
}catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Thread tb = new Thread(() -> {
|
||||
while (true) {
|
||||
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
|
||||
try {
|
||||
tun.read(tmp);
|
||||
tmp.flip();
|
||||
//System.out.println(tmp);
|
||||
if (IPv6Packet.getIPVersion(tmp.get(0)) == 6) {
|
||||
|
||||
HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
||||
tun = TUNNetworkDevice.createDevice(name, CONST.KLALB_DECENTRALIZED_S_RV6_NETWORK);
|
||||
this.hostAddress = hostAddress;
|
||||
if (hostAddress != null) {
|
||||
List<InetAddressRow>rows=new ArrayList<>();
|
||||
rows.add(new InetAddressRow(hostAddress.getAddress().toInet6Address(), hostAddress.getPrefixLength()));
|
||||
tun.setIPAddress(rows);
|
||||
}
|
||||
if (dns != null) {
|
||||
tun.setDNSAddress(dns);
|
||||
}
|
||||
try {
|
||||
tun.setMTU(mtu);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
TUNChannel channel= tun.openSession();
|
||||
Thread tb = new Thread(() -> {
|
||||
while (true) {
|
||||
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
|
||||
try {
|
||||
channel.read(tmp);
|
||||
tmp.flip();
|
||||
// System.out.println(tmp);
|
||||
if (IPv6Packet.getIPVersion(tmp.get(0)) == 6) {
|
||||
|
||||
try {
|
||||
IPv6Packet ipp = new IPv6Packet();
|
||||
ipp.readFromChannel(KNEChannels.newReadableChannel(tmp), mtu);
|
||||
|
||||
//NetworkPacket.databufferpool_65535.back(tmp);
|
||||
if (con != null) {
|
||||
|
||||
monitor.getOutPacketCounterAL().add(1);
|
||||
monitor.getOutTrafficAL().add(ipp.getTotalLength());
|
||||
// ipp.setDisposeAfterSend(true);
|
||||
// ipp.getPayload().setDisposeAfterSend(true);
|
||||
ipp.setPromise(true);
|
||||
if(ipp.getPayload().getProtocolNumber()==6) {
|
||||
seqm.mark(ipp);
|
||||
}
|
||||
con.accept(ipp);
|
||||
// NetworkPacket.databufferpool_65535.back(tmp);
|
||||
BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> con = super.getReceiveConsumer();
|
||||
if (con != null) {
|
||||
if (ipp.getPayload().getProtocolNumber() == 6) {
|
||||
SRv6Router router = getSrv6Router();
|
||||
|
||||
if (router != null) {
|
||||
router.insertHopByHopHeader(ipp);
|
||||
}
|
||||
}
|
||||
|
||||
con.accept(IPv6TUNLoopbackNetworkLink.this, () -> {
|
||||
UUID pid = ipp.getPacketID();
|
||||
if (pid != null) {
|
||||
monitor.getUploadBandwidth().recordPacket(pid, (int) ipp.getTotalLength());
|
||||
}
|
||||
// ipp.setDisposeAfterSend(true);
|
||||
// ipp.getPayload().setDisposeAfterSend(true);
|
||||
return ipp;
|
||||
});
|
||||
} else {
|
||||
//ipp.dispose();
|
||||
// ipp.dispose();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
});
|
||||
}else {
|
||||
//NetworkPacket.databufferpool_65535.back(tmp);
|
||||
} else {
|
||||
// NetworkPacket.databufferpool_65535.back(tmp);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// NetworkPacket.databufferpool_65535.back(tmp);
|
||||
e.printStackTrace();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//NetworkPacket.databufferpool_65535.back(tmp);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
tb.setPriority(Thread.MAX_PRIORITY-1);
|
||||
tb.start();
|
||||
tr = new Thread(() -> {
|
||||
while (true) {
|
||||
ByteBuffer tmp = sendQueue.poll();
|
||||
if (tmp != null) {
|
||||
});
|
||||
tb.setPriority(Thread.MAX_PRIORITY - 1);
|
||||
tb.start();
|
||||
tr = new Thread(() -> {
|
||||
while (true) {
|
||||
ByteBuffer tmp = sendQueue.poll();
|
||||
if (tmp != null) {
|
||||
|
||||
slok.lock();
|
||||
try {
|
||||
tun.write(tmp);
|
||||
channel.write(tmp);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
} finally {
|
||||
slok.unlock();
|
||||
//NetworkPacket.databufferpool_65535.back(tmp);
|
||||
}
|
||||
} else {
|
||||
for(SRv6PacketReorder spr:reorder.values()) {
|
||||
try {
|
||||
spr.runOrdering();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
// NetworkPacket.databufferpool_65535.back(tmp);
|
||||
}
|
||||
} else {
|
||||
|
||||
LockSupport.parkNanos(1000000L);
|
||||
}
|
||||
LockSupport.parkNanos(10000000L);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
tr.setPriority(Thread.MAX_PRIORITY-1);
|
||||
tr.start();
|
||||
|
||||
}catch(UnsatisfiedLinkError e) {
|
||||
});
|
||||
tr.setPriority(Thread.MAX_PRIORITY - 1);
|
||||
tr.start();
|
||||
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
throw new IOException(e);
|
||||
}
|
||||
onOnlineStateUpdate();
|
||||
@@ -159,87 +150,64 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
|
||||
|
||||
private LinkedBlockingQueue<ByteBuffer> sendQueue = new LinkedBlockingQueue<ByteBuffer>();
|
||||
|
||||
private volatile Consumer<IPv6Packet> con;
|
||||
|
||||
private SpeedAndTrafficMonitorDataImpl monitor;
|
||||
|
||||
private ConcurrentHashMap<FlowSession, SRv6PacketReorder> reorder=new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException {
|
||||
if (tun != null) {
|
||||
|
||||
public void sendPacket(IPv6Packet pack, IPv6Address next) throws IOException {
|
||||
if (tun != null) {
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
// System.out.println("rev");
|
||||
IPv6SegmentRoutingHeader srh= pack.getSRHHeader();
|
||||
SEQSSegmentRoutingTLV seqs=null;
|
||||
if(srh!=null) {
|
||||
List<IPv6SegmentRoutingTLV> l=srh.getTlvs();
|
||||
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
IPv6SegmentRoutingTLV tlv=l.get(i);
|
||||
if(tlv instanceof SEQSSegmentRoutingTLV) {
|
||||
seqs=(SEQSSegmentRoutingTLV) tlv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sendPacket0(pack,seqs);
|
||||
|
||||
} catch (IOException e) {
|
||||
//NetworkPacket.databufferpool_65535.back(tmp);
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
|
||||
//pack.disposeAll();
|
||||
|
||||
} else {
|
||||
//pack.disposeAll();
|
||||
IPv6HopByHopHeader hbh = pack.getHopByHopHeader();
|
||||
KLALBOAMHopByHopTLV oamtlv = null;
|
||||
if (hbh != null) {
|
||||
List<IPv6HopByHopTLV> ll = hbh.getTlvs();
|
||||
|
||||
for (int i = 0; i < ll.size(); i++) {
|
||||
IPv6HopByHopTLV tlv = ll.get(i);
|
||||
if (tlv instanceof KLALBOAMHopByHopTLV) {
|
||||
oamtlv = (KLALBOAMHopByHopTLV) tlv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IPv6SegmentRoutingHeader srh = pack.getSegmentRoutingHeader();
|
||||
DetNetSRv6TLV seqs = null;
|
||||
if (srh != null) {
|
||||
List<IPv6SegmentRoutingTLV> l = srh.getTlvs();
|
||||
|
||||
for (int i = 0; i < l.size(); i++) {
|
||||
IPv6SegmentRoutingTLV tlv = l.get(i);
|
||||
if (tlv instanceof DetNetSRv6TLV) {
|
||||
seqs = (DetNetSRv6TLV) tlv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sendPacket0(pack, oamtlv, seqs);
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendPacket0(IPv6Packet pack,SEQSSegmentRoutingTLV seqs) throws IOException {
|
||||
private void sendPacket0(IPv6Packet pack, KLALBOAMHopByHopTLV oamtlv, DetNetSRv6TLV detNet) throws IOException {
|
||||
|
||||
|
||||
if(seqs!=null&&seqs.isKeepOrder()) {
|
||||
FlowSession fss=pack.getFlowSession();
|
||||
|
||||
|
||||
SRv6PacketReorder newr= new SRv6PacketReorder(new PacketConsumer() {
|
||||
|
||||
@Override
|
||||
public boolean accept(IPv6Packet packx) throws IOException {
|
||||
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocateNative(65535);
|
||||
packx.writeToChannel(KNEChannels.newWritableChannel(tmp));
|
||||
monitor.getInPacketCounterAL().add(1);
|
||||
monitor.getInTrafficAL().add(packx.getTotalLength());
|
||||
tmp.flip();
|
||||
sendQueue.add(tmp);
|
||||
LockSupport.unpark(tr);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
SRv6PacketReorder olr=reorder.putIfAbsent(fss,newr);
|
||||
if(olr==null) {
|
||||
olr=newr;
|
||||
}
|
||||
olr.put(pack,seqs.getSequence());
|
||||
|
||||
|
||||
}else {
|
||||
ByteBuffer tmp = NetworkPacket.bufferAllocator.allocate(65535);
|
||||
pack.writeToChannel(KNEChannels.newWritableChannel(tmp));
|
||||
monitor.getInPacketCounterAL().add(1);
|
||||
monitor.getInTrafficAL().add(pack.getTotalLength());
|
||||
tmp.flip();
|
||||
sendQueue.add(tmp);
|
||||
LockSupport.unpark(tr);
|
||||
}
|
||||
UUID pid = pack.getPacketID();
|
||||
if (pid != null) {
|
||||
monitor.getUploadBandwidth().recordPacket(pid, (int) pack.getTotalLength());
|
||||
}
|
||||
tmp.flip();
|
||||
sendQueue.add(tmp);
|
||||
LockSupport.unpark(tr);
|
||||
}
|
||||
|
||||
private SRv6StreamSequenceTLV getStreamSequenceTLV(IpV6RoutingSRHData srh) {
|
||||
@@ -261,15 +229,15 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
|
||||
@Override
|
||||
public List<Neighbor> getNeighborsInfo() {
|
||||
List<Neighbor> hs = new ArrayList<>();
|
||||
//if (hostAddress != null)
|
||||
//hs.put(hostAddress, null);
|
||||
// if (hostAddress != null)
|
||||
// hs.put(hostAddress, null);
|
||||
return hs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
|
||||
return sendQueue.size() > 1000*scale;
|
||||
}
|
||||
/*
|
||||
* @Override public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
|
||||
* return sendQueue.size() > 1000*scale; }
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -289,11 +257,6 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
|
||||
onOnlineStateUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReceiveConsumer(Consumer<IPv6Packet> con) {
|
||||
this.con = con;
|
||||
}
|
||||
|
||||
public void setMonitor(SpeedAndTrafficMonitorDataImpl monitor) {
|
||||
this.monitor = monitor;
|
||||
}
|
||||
@@ -303,49 +266,31 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public List< Inet6AddressGroup> getAddressGroups() {
|
||||
public List<IPv6AddressGroup> getAddressGroups() {
|
||||
return List.of(hostAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RouteItem> getRouteItems() {
|
||||
List<RouteItem> rlist=new ArrayList<>();
|
||||
|
||||
for(Inet6AddressGroup grp:getAddressGroups()) {
|
||||
rlist.add(new RouteItem(new Inet6AddressGroup(grp.getAddress(), 128),
|
||||
grp.getAddress(), this, "Direct", 0, 1, null, "D",true));
|
||||
List<RouteItem> rlist = new ArrayList<>();
|
||||
|
||||
for (IPv6AddressGroup grp : getAddressGroups()) {
|
||||
rlist.add(new RouteItem(new IPv6AddressGroup(grp.getAddress(), 128), grp.getAddress(), this, "Direct", 0, 1,
|
||||
null, "D", true));
|
||||
}
|
||||
|
||||
for (Iterator<Neighbor> iteratorx = getNeighborsInfo()
|
||||
.iterator(); iteratorx.hasNext();) {
|
||||
|
||||
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
|
||||
Neighbor addresses = (Neighbor) iteratorx.next();
|
||||
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(),
|
||||
this, "Direct", 0, 128, addresses.getMonitor(), "D",false);
|
||||
rlist.add(ri);
|
||||
|
||||
RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(),
|
||||
this, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D",false);
|
||||
rlist.add(ris);
|
||||
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
||||
addresses.getAddress().getAddress(), this, "Direct", 0, 128, addresses.getMonitor(), "D", false);
|
||||
rlist.add(ri);
|
||||
|
||||
RouteItem ris = new RouteItem(addresses.getLocator(), addresses.getLocator().getAddress(), this,
|
||||
"KLALB SRv6", 13, 128, addresses.getMonitor(), "D", false);
|
||||
rlist.add(ris);
|
||||
|
||||
}
|
||||
return rlist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCongressCondition(Lock lock, Condition condition) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Inet6AddressGroup implements Comparable<Inet6AddressGroup>{
|
||||
private static final byte[][] maskTransf=new byte[129][16];
|
||||
static {
|
||||
for (int i = 0; i < 129; i++) {
|
||||
for(int j=0;j<i;j++) {
|
||||
maskTransf[i][j/8]=(byte) (((0b10000000)>>>j%8)|maskTransf[i][j/8]);
|
||||
}
|
||||
}
|
||||
/* for (int i = 0; i < maskTransf.length; i++) {
|
||||
try {
|
||||
System.out.println(InetAddress.getByAddress(maskTransf[i]));
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
public Inet6AddressGroup(Inet6Address address) {
|
||||
this(address, 128);
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return address.getHostAddress()+"/"+prefixLength;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(address, prefixLength);
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
Inet6AddressGroup other = (Inet6AddressGroup) obj;
|
||||
return Objects.equals(address, other.address) && prefixLength == other.prefixLength;
|
||||
}
|
||||
public Inet6AddressGroup(Inet6Address address, int prefixLength) {
|
||||
super();
|
||||
this.address = address;
|
||||
this.prefixLength = prefixLength;
|
||||
}
|
||||
public Inet6AddressGroup(DataInputStream in) throws IOException {
|
||||
readFromStream(in);
|
||||
}
|
||||
private Inet6Address address;
|
||||
private int prefixLength=128;
|
||||
public Inet6Address getAddress() {
|
||||
return address;
|
||||
}
|
||||
public int getPrefixLength() {
|
||||
return prefixLength;
|
||||
}
|
||||
private byte[] cachedRawAddress;
|
||||
public byte[] getRawAddress() {
|
||||
if(cachedRawAddress==null) {
|
||||
return (cachedRawAddress=address.getAddress());
|
||||
}else {
|
||||
return cachedRawAddress;
|
||||
}
|
||||
}
|
||||
private byte[] cachedAndm;
|
||||
private byte[] getAndm(byte[]mask) {
|
||||
if(cachedAndm==null) {
|
||||
return (cachedAndm=and0(mask ,getRawAddress()));
|
||||
}else {
|
||||
return cachedAndm;
|
||||
}
|
||||
}
|
||||
public boolean checkMatch(Inet6Address ia) {
|
||||
byte[]mask=maskTransf[prefixLength];
|
||||
byte[]andm=getAndm(mask);
|
||||
|
||||
return andeq0(mask,ia.getAddress(),andm);
|
||||
}
|
||||
public boolean checkMatch(byte[] ia) {
|
||||
byte[]mask=maskTransf[prefixLength];
|
||||
byte[]andm=getAndm(mask);
|
||||
|
||||
return andeq0(mask,ia,andm);
|
||||
}
|
||||
private static boolean andeq0(byte[] bs, byte[] address2, byte[] andm) {
|
||||
for (int i = 0; i < bs.length; i++) {
|
||||
if(andm[i]!=(byte) (bs[i]&address2[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private static byte[] and0(byte[] bs, byte[] address2) {
|
||||
byte[]rez=new byte[bs.length];
|
||||
for (int i = 0; i < rez.length; i++) {
|
||||
rez[i]=(byte) (bs[i]&address2[i]);
|
||||
}
|
||||
return rez;
|
||||
}
|
||||
@Override
|
||||
public int compareTo(Inet6AddressGroup o) {
|
||||
return -Integer.compare(prefixLength, o.prefixLength);
|
||||
}
|
||||
public void writeToStream(DataOutputStream out) throws IOException {
|
||||
out.write(address.getAddress());
|
||||
out.write(prefixLength);
|
||||
}
|
||||
public void readFromStream(DataInputStream in) throws IOException {
|
||||
byte[]b=new byte[16];
|
||||
in.readFully(b);
|
||||
address=(Inet6Address) Inet6Address.getByAddress(b);
|
||||
prefixLength=in.read();
|
||||
}
|
||||
|
||||
public Inet6AddressGroup createPrefixOnlyAddressGroup(int newPrefixLength) {
|
||||
byte[]mask=maskTransf[newPrefixLength];
|
||||
byte[]andm=getAndm(mask);
|
||||
try {
|
||||
return new Inet6AddressGroup((Inet6Address) Inet6Address.getByAddress(andm), newPrefixLength);
|
||||
} catch (UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
public Inet6AddressGroup createPrefixOnlyAddressGroup() {
|
||||
return createPrefixOnlyAddressGroup(prefixLength);
|
||||
}
|
||||
public static void main(String[] args) throws UnknownHostException {
|
||||
Inet6AddressGroup i6ag=new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("1234:1234::1234"),12);
|
||||
System.out.println(i6ag);
|
||||
System.out.println(i6ag.createPrefixOnlyAddressGroup());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KLALBOAMHopByHopTLV extends IPv6HopByHopTLV {
|
||||
|
||||
// 标志位掩码定义 - 移除了DetNet相关标志
|
||||
public static final int FLAG_RECORD_PASSPORT = 0x01; // 第1位: 记录Passport
|
||||
public static final int FLAG_POSTCARD_TO_SOURCE = 0x02; // 第2位: 向源地址回传Postcard
|
||||
public static final int FLAG_POSTCARD_TO_PREV_HOP = 0x04; // 第3位: 向上一跳回传Postcard
|
||||
|
||||
// 保留其他位用于未来扩展 (0x08, 0x10, 0x20, 0x40, 0x80)
|
||||
|
||||
public KLALBOAMHopByHopTLV(ByteBuffer klalbHeader) {
|
||||
super(klalbHeader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLALBOAMHopByHopTLV [getVersion()=" + getVersion() + ", getFlags()=" + getFlags()
|
||||
+ ", getInitialHops()=" + getInitialHops() + ", getUUID()=" + getUUID()
|
||||
+ ", isRecordPassport()=" + isRecordPassport()
|
||||
+ ", isPostcardToSource()=" + isPostcardToSource()
|
||||
+ ", isPostcardToPreviousHop()=" + isPostcardToPreviousHop()
|
||||
+ "]";
|
||||
}
|
||||
|
||||
public KLALBOAMHopByHopTLV(int version, int flags, int initialHops, UUID uuid,long timestamp) {
|
||||
super(IPv6HopByHopTLV.KLALB_OAM);
|
||||
setVersion(version);
|
||||
setFlags(flags);
|
||||
setInitialHops(initialHops);
|
||||
getData().put(3, (byte) 0);
|
||||
getData().put(4, (byte) 0);
|
||||
getData().put(5, (byte) 0);
|
||||
setUUID(uuid);
|
||||
setTimestamp(timestamp);
|
||||
getData().limit(30);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新的构造方法,通过boolean参数设置OAM测量相关的标志位
|
||||
*
|
||||
* @param version 版本号
|
||||
* @param initialHops 初始跳数
|
||||
* @param recordPassport 是否启用记录Passport
|
||||
* @param postcardToSource 是否启用向源地址回传Postcard
|
||||
* @param postcardToPreviousHop 是否启用向上一跳回传Postcard
|
||||
* @param flowuuid 流UUID
|
||||
* @param sequence 序列号
|
||||
*/
|
||||
public KLALBOAMHopByHopTLV(int version, int initialHops, boolean recordPassport, boolean postcardToSource,
|
||||
boolean postcardToPreviousHop, UUID uuid ,long timestamp) {
|
||||
super(IPv6HopByHopTLV.KLALB_OAM);
|
||||
|
||||
setVersion(version);
|
||||
setInitialHops(initialHops);
|
||||
|
||||
// 根据boolean参数计算flags值
|
||||
int flags = 0;
|
||||
if (recordPassport) flags |= FLAG_RECORD_PASSPORT;
|
||||
if (postcardToSource) flags |= FLAG_POSTCARD_TO_SOURCE;
|
||||
if (postcardToPreviousHop) flags |= FLAG_POSTCARD_TO_PREV_HOP;
|
||||
|
||||
setFlags(flags);
|
||||
|
||||
// 设置保留字段为0
|
||||
getData().put(3, (byte) 0);
|
||||
getData().put(4, (byte) 0);
|
||||
getData().put(5, (byte) 0);
|
||||
|
||||
setUUID(uuid);
|
||||
setTimestamp(timestamp);
|
||||
getData().limit(30);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public int getVersion() {
|
||||
return getData().get(0) & 0xff;
|
||||
}
|
||||
|
||||
public void setVersion(int version) {
|
||||
getData().put(0, (byte) version);
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return getData().get(1) & 0xff;
|
||||
}
|
||||
|
||||
public void setFlags(int flags) {
|
||||
getData().put(1, (byte) flags);
|
||||
}
|
||||
|
||||
public int getInitialHops() {
|
||||
return getData().get(2) & 0xff;
|
||||
}
|
||||
|
||||
public void setInitialHops(int initialHops) {
|
||||
getData().put(2, (byte) initialHops);
|
||||
}
|
||||
|
||||
public void setUUID(UUID uuid) {
|
||||
getData().putLong(6, uuid.getMostSignificantBits());
|
||||
getData().putLong(14, uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return new UUID(getData().getLong(6), getData().getLong(14));
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return getData().getLong(22);
|
||||
}
|
||||
|
||||
public void setTimestamp(long sequence) {
|
||||
getData().putLong(22, sequence);
|
||||
}
|
||||
|
||||
// 第1位: 记录Passport
|
||||
public boolean isRecordPassport() {
|
||||
return (getFlags() & FLAG_RECORD_PASSPORT) != 0;
|
||||
}
|
||||
|
||||
public void setRecordPassport(boolean enabled) {
|
||||
int flags = getFlags();
|
||||
if (enabled) {
|
||||
flags |= FLAG_RECORD_PASSPORT;
|
||||
} else {
|
||||
flags &= ~FLAG_RECORD_PASSPORT;
|
||||
}
|
||||
setFlags(flags);
|
||||
}
|
||||
|
||||
// 第2位: 向源地址回传Postcard
|
||||
public boolean isPostcardToSource() {
|
||||
return (getFlags() & FLAG_POSTCARD_TO_SOURCE) != 0;
|
||||
}
|
||||
|
||||
public void setPostcardToSource(boolean enabled) {
|
||||
int flags = getFlags();
|
||||
if (enabled) {
|
||||
flags |= FLAG_POSTCARD_TO_SOURCE;
|
||||
} else {
|
||||
flags &= ~FLAG_POSTCARD_TO_SOURCE;
|
||||
}
|
||||
setFlags(flags);
|
||||
}
|
||||
|
||||
// 第3位: 向上一跳回传Postcard
|
||||
public boolean isPostcardToPreviousHop() {
|
||||
return (getFlags() & FLAG_POSTCARD_TO_PREV_HOP) != 0;
|
||||
}
|
||||
|
||||
public void setPostcardToPreviousHop(boolean enabled) {
|
||||
int flags = getFlags();
|
||||
if (enabled) {
|
||||
flags |= FLAG_POSTCARD_TO_PREV_HOP;
|
||||
} else {
|
||||
flags &= ~FLAG_POSTCARD_TO_PREV_HOP;
|
||||
}
|
||||
setFlags(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
super.writeToChannel(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
super.readFromChannel(din, length);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
|
||||
public class KLALBPassportHopByHopTLV extends IPv6HopByHopTLV {
|
||||
|
||||
public KLALBPassportHopByHopTLV(ByteBuffer buffer) {
|
||||
super(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造方法 - 创建新的护照时间戳记录
|
||||
*
|
||||
* @param packetSize 包长度(2字节)
|
||||
* @param timestampOffset 时间戳偏移量(4字节),相对于流开始时间
|
||||
*/
|
||||
public KLALBPassportHopByHopTLV(int packetSize, int timestampOffset) {
|
||||
super(IPv6HopByHopTLV.KLALB_PASSPORT); // 护照记录类型
|
||||
|
||||
setPacketSize(packetSize);
|
||||
setTimestampOffset(timestampOffset);
|
||||
getData().limit(6); // 固定6字节数据
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "KLALBPassportHopByHopTLV [packetLength=" + getPacketSize() +
|
||||
", timestampOffset=" + getTimestampOffset() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置包长度(2字节,大端序)
|
||||
* 范围: 0-65535字节
|
||||
*/
|
||||
public void setPacketSize(int packetSize) {
|
||||
if (packetSize < 0 || packetSize > 65535) {
|
||||
throw new IllegalArgumentException("Packet length must be between 0 and 65535");
|
||||
}
|
||||
getData().put(0, (byte) ((packetSize >> 8) & 0xFF));
|
||||
getData().put(1, (byte) (packetSize & 0xFF));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包长度(2字节,大端序)
|
||||
*/
|
||||
public int getPacketSize() {
|
||||
return ((getData().get(0) & 0xFF) << 8) | (getData().get(1) & 0xFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置时间戳偏移量(4字节,有符号整数,大端序)
|
||||
*/
|
||||
public void setTimestampOffset(int timestampOffset) {
|
||||
getData().putInt(2, timestampOffset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间戳偏移量(4字节,有符号整数,大端序)
|
||||
*/
|
||||
public int getTimestampOffset() {
|
||||
return getData().getInt(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
super.writeToChannel(dto);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
super.readFromChannel(din, length);
|
||||
}
|
||||
|
||||
public long getTimestampOffsetLong() {
|
||||
return ((long)getTimestampOffset())<<4;
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,9 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.locks.Condition;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.kne.cloud.network.srv6.PacketConsumer;
|
||||
import org.kne.cloud.network.srv6.SRv6Router;
|
||||
@@ -32,23 +34,18 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
||||
return protocolNumberRegister;
|
||||
}
|
||||
|
||||
private List<Inet6AddressGroup> addressGroups =new ArrayList<>();
|
||||
private List<IPv6AddressGroup> addressGroups =new ArrayList<>();
|
||||
|
||||
//new Inet6AddressGroup(loopbackAddress, 128) new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("::1"), 128)
|
||||
public LoopbackIPv6NetworkLink(List<Inet6AddressGroup> addressGroupsx,SRv6Router router) {
|
||||
public LoopbackIPv6NetworkLink(List<IPv6AddressGroup> addressGroupsx,SRv6Router router) {
|
||||
this.addressGroups .addAll( addressGroupsx);
|
||||
}
|
||||
|
||||
public Consumer<IPv6Packet> getReceiveConsumer() {
|
||||
return receiveConsumer;
|
||||
}
|
||||
|
||||
private Consumer<IPv6Packet> receiveConsumer;
|
||||
|
||||
private Consumer<IPv6Packet> rerouteConsumer;
|
||||
private SRv6Router router;
|
||||
|
||||
@Override
|
||||
public void sendPacket(IPv6Packet pack, Inet6Address next) throws IOException {
|
||||
public void sendPacket(IPv6Packet pack, IPv6Address next) throws IOException {
|
||||
PacketConsumer pcm= protocolNumberRegister.get(pack.getPayload().getProtocolNumber());
|
||||
if (pcm != null) {
|
||||
if(!pcm.accept(pack)) {
|
||||
@@ -74,10 +71,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
||||
return hs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCongress(IPv6Packet iPv6Packet, double scale) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -90,26 +83,18 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReceiveConsumer(Consumer<IPv6Packet> con) {
|
||||
this.receiveConsumer = con;
|
||||
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> con) {
|
||||
super.setReceiveConsumer(con);
|
||||
if(fallbackLink!=null) {
|
||||
fallbackLink.setReceiveConsumer(con);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Inet6AddressGroup> getAddressGroups() {
|
||||
public List<IPv6AddressGroup> getAddressGroups() {
|
||||
return addressGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
|
||||
this.rerouteConsumer=rerouteConsumer;
|
||||
if(fallbackLink!=null) {
|
||||
fallbackLink.setRerouteConsumer(rerouteConsumer);
|
||||
}
|
||||
}
|
||||
|
||||
public Consumer<IPv6Packet> getRerouteConsumer() {
|
||||
return rerouteConsumer;
|
||||
}
|
||||
@@ -117,20 +102,20 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
||||
@Override
|
||||
public List<RouteItem> getRouteItems() {
|
||||
List<RouteItem> rlist = new ArrayList<>();
|
||||
for(Inet6AddressGroup group:addressGroups) {
|
||||
rlist.add(new RouteItem(new Inet6AddressGroup(group.getAddress(), 128),
|
||||
for(IPv6AddressGroup group:addressGroups) {
|
||||
rlist.add(new RouteItem(new IPv6AddressGroup(group.getAddress(), 128),
|
||||
group.getAddress(), this, "Direct", 0, 0, null, "D", true));
|
||||
}
|
||||
|
||||
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
|
||||
Neighbor addresses = (Neighbor) iteratorx.next();
|
||||
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128),
|
||||
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
||||
addresses.getAddress().getAddress(), this, "Direct", 0, 128, addresses.getMonitor(), "D",
|
||||
false);
|
||||
rlist.add(ri);
|
||||
|
||||
RouteItem ris = new RouteItem(addresses.getLocator(),
|
||||
(Inet6Address) addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
|
||||
addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
|
||||
addresses.getMonitor(), "D", false);
|
||||
rlist.add(ris);
|
||||
|
||||
@@ -138,10 +123,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
||||
return rlist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public SRv6Router getRouter() {
|
||||
return router;
|
||||
@@ -150,13 +131,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
||||
public void setRouter(SRv6Router router) {
|
||||
this.router = router;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCongressCondition(Lock lock, Condition condition) {
|
||||
// TODO 自动生成的方法存根
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
@@ -5,34 +5,33 @@ import java.net.InetAddress;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
|
||||
import org.kne.cloud.network.te.BandwidthDistributer;
|
||||
|
||||
public class Neighbor {
|
||||
private Inet6AddressGroup address;
|
||||
private Inet6AddressGroup locator;
|
||||
private IPv6AddressGroup address;
|
||||
private IPv6AddressGroup locator;
|
||||
private MonitorData monitor;
|
||||
private BandwidthDistributer<Inet6Address> bandwidthDistributer;
|
||||
public MonitorData getMonitor() {
|
||||
return monitor;
|
||||
}
|
||||
public Inet6AddressGroup getAddress() {
|
||||
public IPv6AddressGroup getAddress() {
|
||||
return address;
|
||||
}
|
||||
public Inet6AddressGroup getLocator() {
|
||||
public IPv6AddressGroup getLocator() {
|
||||
return locator;
|
||||
}
|
||||
|
||||
public BandwidthDistributer<Inet6Address> getBandwidthDistributer() {
|
||||
return bandwidthDistributer;
|
||||
}
|
||||
public Neighbor(Inet6AddressGroup address, Inet6AddressGroup locator, MonitorData monitor) {
|
||||
public Neighbor(IPv6AddressGroup address, IPv6AddressGroup locator, MonitorData monitor) {
|
||||
super();
|
||||
this.address = address;
|
||||
this.locator = locator;
|
||||
this.monitor = monitor;
|
||||
}
|
||||
public Neighbor(Inet6AddressGroup address, Inet6AddressGroup locator, MonitorData monitor2,
|
||||
public Neighbor(IPv6AddressGroup address, IPv6AddressGroup locator, MonitorData monitor2,
|
||||
BandwidthDistributer<Inet6Address> bandwidthDistributer) {
|
||||
this(address,locator,monitor2);
|
||||
this.bandwidthDistributer=bandwidthDistributer;
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class PacketID {
|
||||
private UUID flowuuid;
|
||||
private long sequence;
|
||||
|
||||
public PacketID(UUID flowuuid, long sequence) {
|
||||
super();
|
||||
this.flowuuid = flowuuid;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
long value = flowuuid.getMostSignificantBits() ^ flowuuid.getLeastSignificantBits();
|
||||
result = prime * result + (int)(value ^ (value >>> 32));
|
||||
result = prime * result + (int) (sequence ^ (sequence >>> 32));
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
PacketID other = (PacketID) obj;
|
||||
if (flowuuid == null) {
|
||||
if (other.flowuuid != null)
|
||||
return false;
|
||||
} else if (!flowuuid.equals(other.flowuuid))
|
||||
return false;
|
||||
if (sequence != other.sequence)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PacketID [flowuuid=" + flowuuid + ", sequence=" + sequence + "]";
|
||||
}
|
||||
public UUID getFlowuuid() {
|
||||
return flowuuid;
|
||||
}
|
||||
public long getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class PacketIDGenerator {
|
||||
private UUID flowuuid;
|
||||
private AtomicLong sequence;
|
||||
public PacketIDGenerator() {
|
||||
flowuuid=UUID.randomUUID();
|
||||
sequence=new AtomicLong();
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((flowuuid == null) ? 0 : flowuuid.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
PacketIDGenerator other = (PacketIDGenerator) obj;
|
||||
if (flowuuid == null) {
|
||||
if (other.flowuuid != null)
|
||||
return false;
|
||||
} else if (!flowuuid.equals(other.flowuuid))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
public PacketIDGenerator(UUID flowuuid, AtomicLong sequence) {
|
||||
super();
|
||||
this.flowuuid = flowuuid;
|
||||
this.sequence = sequence;
|
||||
}
|
||||
public UUID getFlowuuid() {
|
||||
return flowuuid;
|
||||
}
|
||||
public AtomicLong getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PacketIDGenerater [flowuuid=" + flowuuid + ", sequence=" + sequence + "]";
|
||||
}
|
||||
|
||||
public PacketID generate() {
|
||||
return new PacketID(flowuuid, sequence.getAndIncrement());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package org.kne.cloud.network.ipv6;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.nio.channels.WritableByteChannel;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.kne.cloud.network.NetworkPacket;
|
||||
import org.kne.io.KNEChannels;
|
||||
|
||||
public class PostcardEntry extends NetworkPacket {
|
||||
public static final int POSTCARD_ENTRY_SIZE = 48;
|
||||
private ByteBuffer data = NetworkPacket.bufferAllocator.allocate(POSTCARD_ENTRY_SIZE);
|
||||
|
||||
// 字段偏移量常量
|
||||
private static final int SID_OFFSET = 0; // 16字节
|
||||
private static final int UUID_OFFSET = 16; // 16字节
|
||||
private static final int SEQUENCE_OFFSET = 16+16; // 8字节
|
||||
private static final int TIMESTAMP_BASE_OFFSET = 16+16; // 8字节
|
||||
private static final int TIMESTAMP_DELTA_OFFSET = 24+16; // 4字节
|
||||
private static final int PACKET_SIZE_OFFSET = 28+16; // 2字节
|
||||
private static final int RESERVED_OFFSET = 30+16; // 6字节
|
||||
|
||||
public PostcardEntry(IPv6Address sid,UUID uuid,long timestampBase,int timestampDelta,int packetSize) {
|
||||
setSID(sid);
|
||||
setPacketUUID(uuid);
|
||||
setTimestampBase(timestampBase);
|
||||
setTimestampDelta(timestampDelta);
|
||||
setPacketSize(packetSize);
|
||||
data.limit(POSTCARD_ENTRY_SIZE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void setSID(IPv6Address sid) {
|
||||
data.putLong(SID_OFFSET, sid.getHigh());
|
||||
data.putLong(SID_OFFSET+8, sid.getLow());
|
||||
}
|
||||
|
||||
public IPv6Address getSID() {
|
||||
long high=data.getLong(SID_OFFSET);
|
||||
long low =data.getLong(SID_OFFSET+8);
|
||||
return new IPv6Address(high, low);
|
||||
}
|
||||
|
||||
public PostcardEntry() {
|
||||
// 初始化缓冲区
|
||||
data.limit(POSTCARD_ENTRY_SIZE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTotalLength() {
|
||||
return POSTCARD_ENTRY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||
data.position(0);
|
||||
data.limit(POSTCARD_ENTRY_SIZE);
|
||||
dto.write(data.slice());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||
data.clear();
|
||||
data.limit(POSTCARD_ENTRY_SIZE);
|
||||
KNEChannels.readFully(din, data);
|
||||
data.flip();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needEndPosition() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置包UUID(16字节)
|
||||
*/
|
||||
public void setPacketUUID(UUID uuid) {
|
||||
data.putLong(UUID_OFFSET, uuid.getMostSignificantBits());
|
||||
data.putLong(UUID_OFFSET + 8, uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包UUID(16字节)
|
||||
*/
|
||||
public UUID getPacketUUID() {
|
||||
long mostSigBits = data.getLong(UUID_OFFSET);
|
||||
long leastSigBits = data.getLong(UUID_OFFSET + 8);
|
||||
return new UUID(mostSigBits, leastSigBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置序列号(8字节)
|
||||
*/
|
||||
public void setSequence(long sequence) {
|
||||
data.putLong(SEQUENCE_OFFSET, sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取序列号(8字节)
|
||||
*/
|
||||
public long getSequence() {
|
||||
return data.getLong(SEQUENCE_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置时间戳(8字节)
|
||||
*/
|
||||
public void setTimestampBase(long timestamp) {
|
||||
data.putLong(TIMESTAMP_BASE_OFFSET, timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取时间戳(8字节)
|
||||
*/
|
||||
public long getTimestampBase() {
|
||||
return data.getLong(TIMESTAMP_BASE_OFFSET);
|
||||
}
|
||||
|
||||
public int getTimestampDelta() {
|
||||
return data.getInt(TIMESTAMP_DELTA_OFFSET);
|
||||
}
|
||||
|
||||
public void setTimestampDelta(int delta) {
|
||||
data.putInt(TIMESTAMP_DELTA_OFFSET, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置包大小(2字节,无符号)
|
||||
*/
|
||||
public void setPacketSize(int packetSize) {
|
||||
if (packetSize < 0 || packetSize > 65535) {
|
||||
throw new IllegalArgumentException("Packet size must be between 0 and 65535");
|
||||
}
|
||||
data.putShort(PACKET_SIZE_OFFSET, (short) packetSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取包大小(2字节,无符号)
|
||||
*/
|
||||
public int getPacketSize() {
|
||||
return data.getShort(PACKET_SIZE_OFFSET) & 0xFFFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置保留字段(2字节)
|
||||
*/
|
||||
public void setReserved(int reserved) {
|
||||
data.putChar(RESERVED_OFFSET ,(char) reserved);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取保留字段(2字节)
|
||||
*/
|
||||
public int getReserved() {
|
||||
return data.getChar(RESERVED_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空保留字段(设置为0)
|
||||
*/
|
||||
public void clearReserved() {
|
||||
setReserved(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
UUID uuid = getPacketUUID();
|
||||
return String.format("PostcardEntry[uuid=%s, seq=%d, time=%d, delta=%d, size=%d]",
|
||||
uuid.toString(),
|
||||
getSequence(),
|
||||
getTimestampBase(),
|
||||
getTimestampDelta(),
|
||||
getPacketSize());
|
||||
}
|
||||
|
||||
public double getTimestampDeltaLong() {
|
||||
return ((long)getTimestampDelta())<<4;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -6,14 +6,13 @@ import java.util.Objects;
|
||||
|
||||
|
||||
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
||||
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
|
||||
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
||||
import org.kne.cloud.network.monitor.DelayMonitorData;
|
||||
import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
|
||||
|
||||
public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
private Inet6AddressGroup destination;
|
||||
private Inet6Address nexthop;
|
||||
private IPv6AddressGroup destination;
|
||||
private IPv6Address nexthop;
|
||||
private IPv6NetworkLink destlink;
|
||||
private String proto;
|
||||
private int pre;
|
||||
@@ -44,7 +43,7 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
&& Objects.equals(flag, other.flag)
|
||||
&& pre == other.pre && Objects.equals(proto, other.proto);
|
||||
}
|
||||
public RouteItem(Inet6AddressGroup destination, Inet6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
|
||||
public RouteItem(IPv6AddressGroup destination, IPv6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
|
||||
long cost,String flag,boolean isLoopback) {
|
||||
super();
|
||||
this.destination = destination;
|
||||
@@ -56,7 +55,7 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
this.flag=flag;
|
||||
this.isLoopback=isLoopback;
|
||||
}
|
||||
public RouteItem(Inet6AddressGroup destination, Inet6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
|
||||
public RouteItem(IPv6AddressGroup destination, IPv6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
|
||||
long cost,MonitorData monitor,String flag,boolean isLoopback) {
|
||||
super();
|
||||
this.destination = destination;
|
||||
@@ -69,10 +68,10 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
this.flag=flag;
|
||||
this.isLoopback=isLoopback;
|
||||
}
|
||||
public Inet6AddressGroup getDestination() {
|
||||
public IPv6AddressGroup getDestination() {
|
||||
return destination;
|
||||
}
|
||||
public Inet6Address getNexthop() {
|
||||
public IPv6Address getNexthop() {
|
||||
return nexthop;
|
||||
}
|
||||
public IPv6NetworkLink getDestlink() {
|
||||
@@ -89,17 +88,17 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop().getHostAddress()+"\t"+getDestlink().getName();
|
||||
return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop()+"\t"+getDestlink().getName();
|
||||
}
|
||||
public long getCost() {
|
||||
return cost;
|
||||
}
|
||||
public boolean checkMatch(Inet6Address ia) {
|
||||
/*public boolean checkMatch(IPv6Address ia) {
|
||||
return destination.checkMatch(ia);
|
||||
}
|
||||
public boolean checkMatch(byte[] ia) {
|
||||
return destination.checkMatch(ia);
|
||||
}
|
||||
}*/
|
||||
@Override
|
||||
public int compareTo(RouteItem o) {
|
||||
int v1=destination.compareTo(o.destination);
|
||||
@@ -109,13 +108,7 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
if(v2!=0)
|
||||
return v2;
|
||||
int v3=Long.compare(cost, o.cost);
|
||||
if(v3!=0)
|
||||
return v3;
|
||||
if(monitor==null||o.monitor==null||(!(monitor instanceof DelayMonitorData))||(!(o.monitor instanceof DelayMonitorData)))
|
||||
return v3;
|
||||
if(!(monitor instanceof QueueingMonitorDataImpl)||!(o.monitor instanceof QueueingMonitorDataImpl))
|
||||
return Long.compare(outDelay, o.outDelay);
|
||||
return Long.compare(outDelay+queueingDelay, o.outDelay+o.queueingDelay);
|
||||
return v3;
|
||||
}
|
||||
@Override
|
||||
public Object clone() {
|
||||
@@ -130,18 +123,13 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||
}
|
||||
}
|
||||
|
||||
long outDelay;
|
||||
long queueingDelay;
|
||||
public void preSort() {
|
||||
if(monitor!=null) {
|
||||
outDelay=((DelayMonitorData)monitor).getOutDelay();
|
||||
if(monitor instanceof QueueingMonitorDataImpl) {
|
||||
queueingDelay=((QueueingMonitorDataImpl)monitor).getQueueingDelay();
|
||||
}
|
||||
cost=((DelayMonitorData)monitor).getOutDelay();
|
||||
}
|
||||
}
|
||||
public boolean ECMPequals(RouteItem prevr) {
|
||||
return prevr.getDestination().getPrefixLength()==getDestination().getPrefixLength()&&prevr.getPre()==getPre()&&prevr.getCost()==getCost();
|
||||
return prevr.getDestination().getPrefixLength()==getDestination().getPrefixLength()&&prevr.getPre()==getPre();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ public static final int PAD1=0;
|
||||
if(getType()==PAD1)
|
||||
setHeaderLength(1);
|
||||
if(isDefault&&(getHeaderLength()>1)) {
|
||||
data=NetworkPacket.bufferAllocator.allocate(512);
|
||||
data=NetworkPacket.bufferAllocator.allocate(256);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public static final int PAD1=0;
|
||||
header.put((byte) 0);
|
||||
header.flip();
|
||||
if(isDefault&&(getHeaderLength()>1)) {
|
||||
data=NetworkPacket.bufferAllocator.allocate(512);
|
||||
data=NetworkPacket.bufferAllocator.allocate(256);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user