This commit is contained in:
Administrator
2025-04-24 10:16:38 +08:00
parent 6de65562be
commit 7267aec1fd
108 changed files with 7621 additions and 1890 deletions
+340 -142
View File
@@ -6,6 +6,7 @@ import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -15,18 +16,19 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Consumer;
import org.kne.acclerate.FastLib;
import org.kne.cloud.network.NetworkPacket;
import org.kne.cloud.network.ipv6.FlowSession;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
@@ -74,8 +76,10 @@ import com.google.gson.internal.Pair;
public class SRv6Router {
private static final boolean debug = false;
public static final int MTU = 9000;
public static final int MTU = 8192;
public static final int MAX_REROUTE_COUNT=2;//1
public static final IpV6RoutingType SRH_HEADER = new IpV6RoutingType((byte) 4, "SRH Header");
// private List<NetworkLink>links=new ArrayList<>();
@@ -140,7 +144,7 @@ public class SRv6Router {
}
@Override
public boolean isCongress(IPv6Packet iPv6Packet) {
public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
return false;
}
@@ -170,6 +174,40 @@ public class SRv6Router {
return loopbackAddress;
}
@Override
public void setRerouteConsumer(Consumer<IPv6Packet> rerouteConsumer) {
// TODO 自动生成的方法存根
}
@Override
public List<RouteItem> getRouteItems() {
List<RouteItem> rlist=new ArrayList<>();
rlist.add(new RouteItem(new Inet6AddressGroup(this.getAddressGroup().getAddress(), 128),
this.getAddressGroup().getAddress(), this, "Direct", 0, 0, null, "D",true));
for (Iterator<Neighbor> iteratorx = getNeighborsInfo()
.iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
RouteItem ri = new RouteItem(new Inet6AddressGroup(addresses.getAddress().getAddress(), 128), addresses.getAddress().getAddress(),
this, "Direct", 0, 128, addresses.getMonitor(), "D",false);
rlist.add(ri);
RouteItem ris = new RouteItem(addresses.getLocator(), (Inet6Address) addresses.getLocator().getAddress(),
this, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D",false);
rlist.add(ris);
}
return rlist;
}
@Override
public boolean isReachSpeedLimit(IPv6Packet iPv6Packet) {
return false;
}
};
public List<RouteItem> getRouteTabel() {
@@ -180,32 +218,44 @@ public class SRv6Router {
return routeTabel0;
}
private Consumer<IPv6Packet> defaultReroute = new Consumer<IPv6Packet>() {
@Override
public void accept(IPv6Packet t) {
//HighPerformanceExecutor.defaultExecutor.execute(() -> {
routePacket(t,true);
t.putTimePassport("rerouted");
//});
}
};
private Consumer<IPv6Packet> defaultReceive = new Consumer<IPv6Packet>() {
@Override
public void accept(IPv6Packet t) {
HighPerformanceExecutor.defaultExecutor.execute(() -> {
//HighPerformanceExecutor.defaultExecutor.execute(() -> {
routePacket(t);
t.putTimePassport("routed");
});
//});
}
};
private Consumer<IPv6Packet> srhReceive = new Consumer<IPv6Packet>() {
@Override
public void accept(IPv6Packet t) {
HighPerformanceExecutor.defaultExecutor.execute(() -> {
//HighPerformanceExecutor.defaultExecutor.execute(() -> {
insertSRHandRoutePacket(t);
});
//});
}
};
private volatile UUID suid=UUID.randomUUID();
public void updateRouteTabel() {
List<RouteItem> routeTabel0x = new ArrayList<>();
for (Iterator<IPv6NetworkLink> iterator = linkTabel.iterator(); iterator.hasNext();) {
IPv6NetworkLink nlink = (IPv6NetworkLink) iterator.next();
if (nlink.isLoopBack()) {
/*if (nlink.isLoopBack()) {
if (nlink instanceof IPv6TUNLoopbackNetworkLink) {
routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128),
nlink.getAddressGroup().getAddress(), nlink, "Direct", 0, 1, null, "D"));
@@ -215,10 +265,7 @@ public class SRv6Router {
nlink.getAddressGroup().getAddress(), nlink, "Direct", 0, 0, null, "D"));
}
}/*else {
routeTabel0x.add(new RouteItem(new Inet6AddressGroup(nlink.getAddressGroup().getAddress(), 128),
nlink.getAddressGroup().getAddress(), inLoopBack, "Direct", 0, 0, null, "D"));
}*/
}
for (Iterator<Neighbor> iteratorx = nlink.getNeighborsInfo()
.iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
@@ -230,9 +277,11 @@ public class SRv6Router {
nlink, "KLALB SRv6", 13, 128, addresses.getMonitor(), "D");
routeTabel0x.add(ris);
}
}*/
List<RouteItem>routes=nlink.getRouteItems();
routeTabel0x.addAll(routes);
if (nlink instanceof IPv6TUNLoopbackNetworkLink) {
@@ -240,14 +289,28 @@ public class SRv6Router {
} else {
nlink.setReceiveConsumer(defaultReceive);
}
nlink.setRerouteConsumer(defaultReroute);
}
/*List<RouteItem> routeTabel1x=new ArrayList<>(routeTabel0x.size());
routeTabel0x.addAll(routeTabel);
for (Iterator<RouteItem> iterator = routeTabel0x.iterator(); iterator.hasNext();) {
RouteItem routeItem = (RouteItem) iterator.next();
routeTabel1x.add((RouteItem) routeItem.clone());
}*/
for (Iterator<RouteItem> iterator = routeTabel0x.iterator(); iterator.hasNext();) {
RouteItem routeItem = (RouteItem) iterator.next();
routeItem.preSort();
}
Collections.sort(routeTabel0x);
routeTabel0 = routeTabel0x;
suid=UUID.randomUUID();
}
private Inet6AddressGroup locator;
private long asn=new SecureRandom().nextLong(1,Long.MAX_VALUE);
/*
* public List<NetworkLink> getLinks() { return links; }
*/
@@ -259,42 +322,50 @@ public class SRv6Router {
return locator;
}
public long getASN() {
return asn;
}
public void setASN(long asn) {
this.asn = asn;
}
public void setLocator(Inet6AddressGroup locator) {
this.locator = locator;
updateRouteTabel();
}
private ConcurrentHashMap<FlowSession, TCPTransimitAgent> swist = new ConcurrentHashMap<>();
//private ConcurrentHashMap<FlowSession, TCPTransimitAgent> swist = new ConcurrentHashMap<>();
// private AtomicLong qsn=new AtomicLong();
public void insertSRHandRoutePacket(IPv6Packet ipp) {
insertSRH(ipp);
ipp.putTimePassport("SRH inserted");
routePacket(ipp);
ipp.putTimePassport("routed");
}
public void insertSRH(IPv6Packet ipp) {
if(ipp.getSRHHeader()!=null) {
throw new IllegalStateException("packet already has SRH!");
}
if (klalbRouteProtol != null) {
List<Inet6Address> segs = klalbRouteProtol.createSegmentList(ipp.getDestinationAddress());
// System.out.println(segs);
if (segs != null && (!segs.isEmpty())) {
/*
* List<SRv6TLV>tlvs=new ArrayList<>(1); if(ipp.getPayload().getType()==6) {
* SRv6StreamSequenceTLV sers= new SRv6StreamSequenceTLV();
* sers.setSequence(qsn.getAndIncrement()); tlvs.add(sers); }
*/
//IpV6RoutingSRHData srh = new IpV6RoutingSRHData(segs);
IPv6SegmentRoutingHeader irh = new IPv6SegmentRoutingHeader(segs);
//System.out.println(ipp.getFlowLabel());
ThreadLocalRandom tlr=ThreadLocalRandom.current();
//System.out.println(ipp.getFlowSeqMark());
irh.getTlvs().add(new SEQSSegmentRoutingTLV(ipp.getFlowSeqMark(),new UUID(suid.getMostSignificantBits()^tlr.nextLong(),suid.getMostSignificantBits()^tlr.nextLong()),ipp.isPromise(),ipp.getFlowSeqMark()!=-1));
ipp.getHeaders().add(irh);
ipp.setDestinationAddress(segs.get(segs.size() - 1));
/*
* if(ipp.getPayload().getType()==6) System.out.println(ipp);
*/
}
}
}
@@ -303,7 +374,14 @@ public class SRv6Router {
private volatile List<RouteItem> routeTabel0 = new ArrayList<>();
// private ReentrantReadWriteLock routelock=new ReentrantReadWriteLock();
//路由数据包
public void routePacket(IPv6Packet iPv6Packet) {
routePacket(iPv6Packet ,false);
}
//路由数据包
public void routePacket(IPv6Packet iPv6Packet, boolean reroute) {
// routelock.readLock().lock();
// try {
// System.out.println("路由表:"+routeTabel0);
@@ -311,96 +389,55 @@ public class SRv6Router {
if (debug) {
dbg=new StringBuilder();
}
iPv6Packet.lockAll();
try {
if(iPv6Packet.isSomeDisposed())
return;
int hop = iPv6Packet.getHopLimit();
int hop = iPv6Packet.getHopLimit();//检查TTL值,只有大于0才会被转发,否则丢弃
if (hop > 0) {
// List<RouteItem> mached=new ArrayList<>();
// RouteItem pri=null;
Inet6Address ia = iPv6Packet.getDestinationAddress();
if (debug) {
dbg.append("----------------------------------------\n");
dbg.append("packet:" + iPv6Packet.getSourceAddress().getHostAddress() + "->"
+ iPv6Packet.getDestinationAddress().getHostAddress()+"\n");
}
for (int i = 0; i < routeTabel0.size(); i++) {
RouteItem tri = routeTabel0.get(i);
if (!tri.checkMatch(ia)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("unmatched.\n");
}
continue;
}
if (!tri.getDestlink().isUp()) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("linkdown.\n");
}
continue;
}
if (tri.getDestlink().isCongress(iPv6Packet)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("congress.\n");
}
continue;
}
if (!tri.getDestlink().canSend(iPv6Packet)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("linkrefused.\n");
}
continue;
}
if (debug) {
dbg.append(tri+"\n");
dbg.append("matched.\n");
}
processPacket(iPv6Packet, tri);
return;
/*
* if(pri==null||pri.equals(tri)) { mached.add(tri); pri=tri; }else { break; }
*/
}
if (debug) {
dbg.append("miss.\n");
}
if (iPv6Packet.isEnableECN()) {
iPv6Packet.markCE();
for (int i = 0; i < routeTabel0.size(); i++) {
RouteItem tri = routeTabel0.get(i);
if (tri.checkMatch(ia)) {
if (!tri.getDestlink().isUp()) {
continue;
}
processPacket(iPv6Packet, tri);
return;
/*
* if(pri==null||pri.equals(tri)) { mached.add(tri); pri=tri; }else { break; }
*/
}
}
//按延迟顺序从小到大匹配路由表
if(searchTableAndFoward(iPv6Packet, reroute, dbg)) {
//匹配到路由表,返回
return ;
}
if (debug)
dbg.append("congress\n");
// System.out.println(ia.getAddress()+" match "+ri);
/*
* for (Iterator iterator = mached.iterator(); iterator.hasNext();) { RouteItem
* routeItem = (RouteItem) iterator.next();
* if(routeItem.getDestlink().isCongress()) {
*
* }else { processPacket(iPv6Packet,pri); break; } }
*/
// else
// System.out.println("路由失败:"+iPv6Packet);
dbg.append("noroute\n");
//System.out.println("找不到路由表:"+iPv6Packet.getSourceAddress().getHostAddress()+" -> "+iPv6Packet.getDestinationAddress().getHostAddress());
//未找到合适的路由表或路由表对应的链路down,使用FRR保护创建备用路由表
IPv6SegmentRoutingHeader srh=iPv6Packet.getSRHHeader();
if(srh!=null) {
System.out.println("原SRH"+srh);
int segmentsLeft=srh.getSegmentsLeft();
if(segmentsLeft>0) {
srh.getAddresses().remove(segmentsLeft);
segmentsLeft--;
}
List<Inet6Address> repairSegments= klalbRouteProtol.createSegmentList(srh.getAddresses().get(segmentsLeft));
if(repairSegments ==null) {
System.out.println("FRR保护失败");
return;
}
repairSegments.remove(0);
srh.getAddresses().addAll(segmentsLeft+1, repairSegments);
segmentsLeft+=repairSegments.size();
srh.setSegmentsLeft(segmentsLeft);
iPv6Packet.setDestinationAddress(srh.getAddresses().get(segmentsLeft));
}else {
return;
}
System.out.println("FRR修复SRH"+srh);
if(searchTableAndFoward(iPv6Packet, reroute, dbg)) {
return ;
}
} else {
IcmpV6TimeExceededPacket.Builder icmpte = new IcmpV6TimeExceededPacket.Builder();
ByteBuffer IPv6data = NetworkPacket.databufferpool_65535.borrow();
ByteBuffer IPv6data = NetworkPacket.bufferAllocator.allocate(65535);
iPv6Packet.writeToChannel(KNEChannels.newWritableChannel(IPv6data));
byte[] raw = new byte[IPv6data.remaining()];
IPv6data.get(0, raw);
@@ -433,34 +470,206 @@ public class SRv6Router {
if(debug) {
System.out.println(dbg.toString());
}
iPv6Packet.unlockAll();
}
// }finally {
// routelock.readLock().unlock();
// }
}
private void processPacket(IPv6Packet iPv6Packet, RouteItem ri) throws IllegalRawDataException, IOException {
int hop = iPv6Packet.getHopLimit();
private boolean searchTableAndFoward(IPv6Packet iPv6Packet, boolean reroute, StringBuilder dbg)
throws IllegalRawDataException, IOException {
byte[] ia = new byte[16];
iPv6Packet.getRawDestinationAddress(ia);
if (debug) {
dbg.append("----------------------------------------\n");
dbg.append("packet:" + iPv6Packet.getSourceAddress().getHostAddress() + " -> "
+ iPv6Packet.getDestinationAddress().getHostAddress()+"\n");
}
boolean routeFound=false;
RouteItem prevr=null;
List<RouteItem> routes=new ArrayList<>();
//遍历路由表
for (RouteItem tri: routeTabel0) {
if(!tri.checkMatch(ia)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("unmatched.\n");
}
//跳过前缀与掩码不符合要求的路由表条目
continue;
}
if (!tri.getDestlink().canSend(iPv6Packet)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("linkrefused.\n");
}
//跳过不能转发这种数据包的链路
continue;
}
if (!tri.getDestlink().isUp()) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("linkdown.\n");
}
//跳过断开连接的链路
continue;
}
routeFound=true;
if(prevr!=null) {
if(!tri.ECMPequals(prevr)) {
//执行流量整形负载均衡调度算法
if(routingLoadBalance(iPv6Packet, reroute, dbg, routes)) {
return routeFound;
}
routes.clear();
}
}
//将等价路由加入负载均衡列表
routes.add(tri);
prevr=tri;
}
routingLoadBalance(iPv6Packet, reroute, dbg, routes);
return routeFound;
}
private boolean routingLoadBalance(IPv6Packet iPv6Packet, boolean reroute, StringBuilder dbg, List<RouteItem> routes)
throws IllegalRawDataException, IOException {
double cscale=1.0;
if(iPv6Packet.getPayload().getProtocolNumber()==6) {
cscale=15.0;
}
boolean retry=false;
long start=System.nanoTime();
do {
retry=false;
//遍历可用于负载均衡调度的路由表
for (RouteItem tri: routes) {
if (!tri.getDestlink().isUp()) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("linkdown.\n");
}
//跳过断开的链路
continue;
}
if (tri.getDestlink().isCongress(iPv6Packet,cscale)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("congress.\n");
}
//跳过缓冲区拥塞的链路
continue;
}
if (tri.getDestlink().isReachSpeedLimit(iPv6Packet)) {
retry=true;
if (debug) {
dbg.append(tri+"\n");
dbg.append("reachspeedlimit.\n");
}
//跳过达到流量整形速度限制的链路(若仅超过流量整形速度限制,可多次重试)
continue;
}
if (debug) {
dbg.append(tri+"\n");
dbg.append("matched.\n");
}
//链路可用,处理并转发数据包
processPacket(iPv6Packet, tri,reroute);
return true;
}
if(retry) {
if(System.nanoTime()-start>200000000L) {
break;
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//Thread.yield();
//短暂挂起当前线程,待链路速度未超限时重试发送数据包
}
}while((!routes.isEmpty())&&retry);
if (debug) {
dbg.append("miss.\n");
}
//负载均衡未匹配成功,若数据包支持ECN,打上拥塞标记位
if(iPv6Packet.isEnableECN()) {
iPv6Packet.markCE();
if (debug) {
dbg.append("ECN enabled.\n");
}
}
for (RouteItem tri: routes) {
if (!tri.getDestlink().isUp()) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("linkdown.\n");
}
continue;
}
if (tri.getDestlink().isCongress(iPv6Packet,25.0)) {
if (debug) {
dbg.append(tri+"\n");
dbg.append("congress.\n");
}
//缓冲区留部分余量避免丢包
continue;
}
processPacket(iPv6Packet, tri,reroute);
return true;
}
//仍未成功发送,丢弃数据包
return false;
}
private void processPacket(IPv6Packet iPv6Packet, RouteItem ri, boolean reroute) throws IllegalRawDataException, IOException {
int hop = iPv6Packet.getHopLimit();
if (ri.getDestlink().isLoopBack()) {
IPv6SegmentRoutingHeader srhh = getSRHHeaderFromPacket(iPv6Packet);
IPv6SegmentRoutingHeader srhh =iPv6Packet. getSRHHeader();
if (srhh != null) {
processSRv6Packet(iPv6Packet, ri, srhh);
processSRv6Packet(iPv6Packet, ri, srhh,reroute);
} else {
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
}
} else {
if(iPv6Packet.getRerouteCounter().getAndIncrement()>=MAX_REROUTE_COUNT) {
//System.out.println("reroute count >=2");
return;
}
if(!reroute) {
// if(!iPv6Packet.isTTLdecreased()) {
hop--;
/* iPv6Packet.setTTLdecreased(true);
}else {
System.out.print("ttl err");
}*/
}
// System.out.println(ipp.getHeader().getSrcAddr()+"->"+ipp.getHeader().getDstAddr()+"
// "+(hop+1)+"->"+hop);
if (hop > 0) {
iPv6Packet.setHopLimit(hop);
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
} else {
IcmpV6TimeExceededPacket.Builder icmpte = new IcmpV6TimeExceededPacket.Builder();
ByteBuffer IPv6data = NetworkPacket.databufferpool_65535.borrow();
ByteBuffer IPv6data = NetworkPacket.bufferAllocator.allocate(65535);
iPv6Packet.writeToChannel(KNEChannels.newWritableChannel(IPv6data));
byte[] raw = new byte[IPv6data.remaining()];
IPv6data.get(0, raw);
@@ -491,37 +700,25 @@ public class SRv6Router {
}
private void processSRv6Packet(IPv6Packet iPv6Packet, RouteItem ri, IPv6SegmentRoutingHeader srhh)
private void processSRv6Packet(IPv6Packet iPv6Packet, RouteItem ri, IPv6SegmentRoutingHeader srhh, boolean reroute)
throws IllegalRawDataException, IOException {
/*byte[] srd = new byte[(int) (srhh.getLength() - 4)];
srhh.getData().get(4, srd);
IpV6RoutingSRHData srh = IpV6RoutingSRHData.newInstance(srd, 0, srd.length);*/
if (srhh.getSegmentsLeft() <= 0) {
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
} else {
if(reroute) {
}else {
int newSL = srhh.getSegmentsLeft() - 1;
srhh.setSegmentsLeft(newSL);
iPv6Packet.setDestinationAddress(srhh.getAddresses().get(newSL));
}
klalbRouteProtol.putHotspotAddress(iPv6Packet.getSourceAddress());
routePacket(iPv6Packet);
routePacket(iPv6Packet,reroute);
}
}
private IPv6SegmentRoutingHeader getSRHHeaderFromPacket(IPv6Packet iPv6Packet) {
IPv6SegmentRoutingHeader srhh = null;
List<IPv6ExtHeader> exhs = iPv6Packet.getHeaders();
for (int j = 0; j < exhs.size(); j++) {
IPv6ExtHeader exh = exhs.get(j);
if (exh instanceof IPv6SegmentRoutingHeader) {
if (((IPv6SegmentRoutingHeader) exh).getRoutingType() == 4) {
srhh = (IPv6SegmentRoutingHeader) exh;
break;
}
}
}
return srhh;
}
public SRv6Router(Inet6AddressGroup hostAddress) {
super();
@@ -551,19 +748,20 @@ public class SRv6Router {
return klalbRouteProtol;
}
private Map<Integer, PacketConsumer> protocolNumberRegister = new ConcurrentHashMap<>();
private Map<Integer, PacketConsumer> protocolNumberRegister = new ConcurrentHashMap<>(256*2);
public Map<Integer, PacketConsumer> getProtocolNumberRegister() {
return protocolNumberRegister;
}
public void putProtocolNumberPacketAndInsertSRH(IPv6Packet pkt) {
/*public void putProtocolNumberPacketAndInsertSRHAsync(IPv6Packet pkt) {
// inLoopBack.getReceiveConsumer().accept(pkt);
srhReceive.accept(pkt);
}
public void putProtocolNumberPacket(IPv6Packet pkt) {
public void putProtocolNumberPacketAsync(IPv6Packet pkt) {
// inLoopBack.getReceiveConsumer().accept(pkt);
defaultReceive.accept(pkt);
}
}*/
}