Files
KLALB/src/org/kne/cloud/network/srv6/SRv6Router.java
T

983 lines
33 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package org.kne.cloud.network.srv6;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.jctools.counters.FixedSizeStripedLongCounter;
import org.kne.cloud.clock.HighAccuracyClock;
import org.kne.cloud.network.congestion.MessageBatcher;
import org.kne.cloud.network.ipv6.ControlledIPv6NetworkLink;
import org.kne.cloud.network.ipv6.ICMPv6PostcardPacket;
import org.kne.cloud.network.ipv6.ICMPv6TimeExceededPacket;
import org.kne.cloud.network.ipv6.IPv6Address;
import org.kne.cloud.network.ipv6.IPv6HopByHopTLV;
import org.kne.cloud.network.ipv6.IPv6LinkStateListener;
import org.kne.cloud.network.ipv6.IPv6NetworkLink;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6HopByHopHeader;
import org.kne.cloud.network.ipv6.IPv6Packet.IPv6SegmentRoutingHeader;
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
import org.kne.cloud.network.ipv6.KLALBOAMHopByHopTLV;
import org.kne.cloud.network.ipv6.KLALBPassportHopByHopTLV;
import org.kne.cloud.network.ipv6.LoopbackIPv6NetworkLink;
import org.kne.cloud.network.ipv6.Neighbor;
import org.kne.cloud.network.ipv6.PadNHopByHopTLV;
import org.kne.cloud.network.ipv6.PostcardEntry;
import org.kne.cloud.network.ipv6.RouteItem;
import org.kne.cloud.network.klalb.KLALBRemoteLink;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.concurrent.HighPerformanceExecutor2;
import org.kne.concurrent.TimeoutConcurrentHashMap;
import org.pcap4j.packet.IllegalRawDataException;
import com.google.gson.internal.Pair;
// SRv6路由器主类,实现IPv6段路由功能
public class SRv6Router {
private static final boolean debug = false; // 调试模式开关
// public static final int MTU = 16384;
public static final int MTU = 16384; // 最大传输单元
public static final int MAX_REROUTE_COUNT = 2;// 1 // 最大重路由次数
private static final int IPv6_BITS = 128; // IPv6地址位数
/*private TimeoutConcurrentHashMap<FlowSession, PacketIDGenerator> flowIDmap = new TimeoutConcurrentHashMap<FlowSession, PacketIDGenerator>(
60000000000L);
*/
private Set<UUID> unduplicateSet = Collections
.newSetFromMap(new TimeoutConcurrentHashMap<UUID, Boolean>(3000000000L, 1024, 0.5f));
private HighAccuracyClock clock;
// 获取环回地址 ::1
private static Inet6Address getLoopbackAddress() {
try {
return (Inet6Address) Inet6Address.getByName("::1");
} catch (UnknownHostException e) {
e.printStackTrace();
}
return null;
}
// 获取任意本地地址 ::0
private static Inet6Address getAnyLocalAddress() {
try {
return (Inet6Address) Inet6Address.getByName("::0");
} catch (UnknownHostException e) {
e.printStackTrace();
}
return null;
}
private List<RouteItem> routeTabel = new ArrayList<>(); // 路由表
private List<IPv6NetworkLink> linkTabel = new CopyOnWriteArrayList<>(); // 网络链路表,线程安全
public List<IPv6NetworkLink> getLinkTabel() {
return linkTabel;
}
// 环回网络链路
private final LoopbackIPv6NetworkLink inLoopBack;
// 获取路由表
public List<RouteItem> getRouteTabel() {
return routeTabel;
}
// 获取当前路由表
public List<RouteItem> getCurrentRouteTabel() {
return routeTable0;
}
// 默认重路由处理器
private Consumer<IPv6Packet> defaultReroute = new Consumer<IPv6Packet>() {
@Override
public void accept(IPv6Packet t) {
// HighPerformanceExecutor.defaultExecutor.execute(() -> {
routePacket(null, t, true); // 执行重路由
// });
}
};
private boolean unduplicate(IPv6Packet pack) {
IPv6HopByHopHeader hbh = pack.getHopByHopHeader();
KLALBOAMHopByHopTLV oamtlv = null;
if (hbh != null) {
List<IPv6HopByHopTLV> tlvs = hbh.getTlvs();
for (IPv6HopByHopTLV tlv : tlvs) {
if (tlv instanceof KLALBOAMHopByHopTLV) {
oamtlv = (KLALBOAMHopByHopTLV) tlv;
break;
}
}
}
if (oamtlv == null)
return true;
boolean bool = unduplicateSet.add(oamtlv.getUUID());
// System.out.println(bool);
return bool;
}
// 默认接收处理器
/*
* private BiConsumer<IPv6NetworkLink,IPv6Packet> defaultReceive = new
* BiConsumer<IPv6NetworkLink,IPv6Packet>() {
*
* @Override public void accept(IPv6NetworkLink link,IPv6Packet t) { //
* HighPerformanceExecutor.defaultExecutor.execute(() -> { if(unduplicate(t)) {
* routePacket(t); // 执行路由 t.putTimePassport("routed"); // 标记路由时间点 } // }); } };
*/
// SRH接收处理器
private BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> srhReceive = new BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>>() {
@Override
public void accept(IPv6NetworkLink link, Supplier<IPv6Packet> pack) {
enqueuePacketReceiveTask(link, pack);
}
};
// 链路状态监听器实现
private class LinkListener implements IPv6LinkStateListener {
@Override
public void onOnlineStateUpdate(IPv6NetworkLink link) {
srListeners.forEach((v) -> {
v.onLinkChanged(SRv6Router.this, link);
}); // 通知所有监听器链路状态变化
}
@Override
public void onAddressUpdate(IPv6NetworkLink link) {
srListeners.forEach((v) -> {
v.onLinkChanged(SRv6Router.this, link);
}); // 通知所有监听器地址更新
}
@Override
public void onLocatorUpdate(IPv6NetworkLink link) {
srListeners.forEach((v) -> {
v.onLinkChanged(SRv6Router.this, link);
}); // 通知所有监听器定位器更新
}
}
private IPv6LinkStateListener listener = new LinkListener(); // 链路状态监听器实例
private Set<SRv6RouterListener> srListeners = new CopyOnWriteArraySet<SRv6RouterListener>(); // SRv6路由器监听器集合
// 添加SRv6路由器监听器
public void addSRv6RouterListener(SRv6RouterListener listener) {
srListeners.add(listener);
}
// 移除SRv6路由器监听器
public void removeSRv6RouterListener(SRv6RouterListener listener) {
srListeners.remove(listener);
}
public void sortRouteTabel() {
// 构建前缀长度索引的路由表
List<Map<IPv6Address, List<RouteItem>>> routeTabel1x = new ArrayList<Map<IPv6Address, List<RouteItem>>>(
IPv6_BITS + 1);
for (int i = 0; i < IPv6_BITS + 1; i++) {
routeTabel1x.add(new HashMap<IPv6Address, List<RouteItem>>(1024, 0.5f));
}
List<RouteItem> routeTabel0x=routeTable0;
// 按前缀长度组织路由表
for (RouteItem item : routeTabel0x) {
IPv6AddressGroup iag = item.getDestination();
Map<IPv6Address, List<RouteItem>> map = routeTabel1x.get(iag.getPrefixLength());
List<RouteItem> newlist = new ArrayList<RouteItem>();
List<RouteItem> oldlist = map.putIfAbsent(iag.getAddress(), newlist);
if (oldlist == null) {
oldlist = newlist;
}
oldlist.add(item);
}
for(Map<IPv6Address, List<RouteItem>> map:routeTabel1x) {
for(List<RouteItem>v:map.values()) {
Collections.sort(v);
}
}
// System.out.println(routeTabel1x);
routeTabel1 = routeTabel1x; // 更新索引路由表
}
// 更新路由表
public void updateRouteTabel() {
List<RouteItem> routeTabel0x = new ArrayList<>();
// 遍历所有网络链路,收集路由信息
for (Iterator<IPv6NetworkLink> iterator = linkTabel.iterator(); iterator.hasNext();) {
IPv6NetworkLink nlink = (IPv6NetworkLink) iterator.next();
List<RouteItem> routes = nlink.getRouteItems(); // 获取链路的路由项
routeTabel0x.addAll(routes); // 添加到路由表
nlink.setSRv6Router(this);
nlink.addIPv6LinkStateListener(listener); // 添加链路状态监听器
nlink.setReceiveConsumer(srhReceive); // 设置接收处理器
if (nlink instanceof ControlledIPv6NetworkLink) {
((ControlledIPv6NetworkLink) nlink).setRerouteConsumer(defaultReroute); // 设置重路由处理器
((ControlledIPv6NetworkLink) nlink).setCongressCondition(congressLock, congressCondition); // 设置拥塞条件
}
}
// 预处理和排序路由项
for (Iterator<RouteItem> iterator = routeTabel0x.iterator(); iterator.hasNext();) {
RouteItem routeItem = (RouteItem) iterator.next();
routeItem.updateCost(); // 预排序
}
Collections.sort(routeTabel0x); // 排序路由表
// 构建前缀长度索引的路由表
ArrayList<Map<IPv6Address, List<RouteItem>>> routeTabel1x = new ArrayList<Map<IPv6Address, List<RouteItem>>>(
IPv6_BITS + 1);
for (int i = 0; i < IPv6_BITS + 1; i++) {
routeTabel1x.add(new HashMap<IPv6Address, List<RouteItem>>(1024, 0.5f));
}
// 按前缀长度组织路由表
for (RouteItem item : routeTabel0x) {
IPv6AddressGroup iag = item.getDestination();
Map<IPv6Address, List<RouteItem>> map = routeTabel1x.get(iag.getPrefixLength());
List<RouteItem> newlist = new ArrayList<RouteItem>();
List<RouteItem> oldlist = map.putIfAbsent(iag.getAddress(), newlist);
if (oldlist == null) {
oldlist = newlist;
}
oldlist.add(item);
}
// System.out.println(routeTabel1x);
routeTable0 = routeTabel0x; // 更新平面路由表
routeTabel1 = routeTabel1x; // 更新索引路由表
}
private IPv6AddressGroup locator; // SRv6定位器
private long asn = new SecureRandom().nextLong(1, Long.MAX_VALUE); // 自治系统号
public IPv6AddressGroup getLocator() {
return locator;
}
public long getASN() {
return asn;
}
public void setASN(long asn) {
this.asn = asn;
}
// 设置定位器并更新路由表
public void setLocator(IPv6AddressGroup locator) {
this.locator = locator;
updateRouteTabel();
}
// 插入SRH并路由数据包
public void insertSRHandRoutePacket(IPv6NetworkLink link, IPv6Packet ipp) {
insertHopByHopHeader(ipp);
insertSRHeader(ipp); // 插入段路由头
routePacket(link, ipp); // 路由数据包
}
private static final PadNHopByHopTLV pad4 = new PadNHopByHopTLV(4);
// 插入逐跳路由头
public boolean insertHopByHopHeader(IPv6Packet ipp) {
if (ipp.getHopByHopHeader() != null) {
return false;
}
IPv6HopByHopHeader hbh = new IPv6HopByHopHeader();
hbh.getTlvs().add(pad4);
UUID pid = KLALBUtils.createGlobalUUID();
hbh.getTlvs().add(new KLALBOAMHopByHopTLV(0, ipp.getHopLimit(), true, false, true, pid,
clock.getCurrentTimeNTP64().longValue()));
ipp.getHeaders().add(0, hbh); // 添加Hop头
ipp.setHopByHopHeader(hbh);
return true;
}
// 插入段路由头
public boolean insertSRHeader(IPv6Packet ipp) {
// 如果已有SRH,返回false
if (ipp.getSegmentRoutingHeader() != null) {
return false;
}
// 如果KLALB路由协议可用,创建段列表
if (klalbRouteProtol != null) {
IPv6SegmentRoutingHeader segs = klalbRouteProtol.createSegmentList(ipp.getDestinationAddress());
// System.out.println(segs);
if (segs != null && (!segs.getAddresses().isEmpty())) {
// 创建SRH头
ipp.getHeaders().add(segs); // 添加SRH头
ipp.setRoutingHeader(segs);
ipp.setDestinationAddress(segs.getAddresses().get(segs.getAddresses().size() - 1)); // 更新目的地址为最后一个段
return true;
}
}
return false;
}
private volatile List<RouteItem> routeTable0 = new ArrayList<>(); // 当前路由表
// 前缀长度索引的路由表
private volatile List<Map<IPv6Address, List<RouteItem>>> routeTabel1 = new ArrayList<Map<IPv6Address, List<RouteItem>>>(
IPv6_BITS + 1);
{
// 初始化索引路由表
for (int i = 0; i < IPv6_BITS + 1; i++) {
routeTabel1.add(new HashMap<IPv6Address, List<RouteItem>>(1024, 0.5f));
}
}
private void routePacket(IPv6Packet iPv6Packet) {
routePacket(null, iPv6Packet, false);
}
// 路由数据包(默认非重路由)
private void routePacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet) {
routePacket(linkfrom, iPv6Packet, false);
}
// 路由数据包主方法
private void routePacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, boolean reroute) {
StringBuilder dbg = null;
if (debug) {
dbg = new StringBuilder(); // 调试信息
}
try {
int hop = iPv6Packet.getHopLimit(); // 获取跳数限制
if (hop > 0) { // 检查TTL值,只有大于0才会被转发
// 搜索匹配的路由表项
IPv6Address dest=iPv6Packet.getDestinationAddress();
List<RouteItem> searchResult = getTabelByAddress(dest);
if (searchResult!=null&&(!searchResult.isEmpty())) {
// 匹配到路由表,执行负载均衡路由
routingLoadBalance(linkfrom, iPv6Packet, reroute, dbg, searchResult);
return;
}
if (debug)
dbg.append("noroute\n");
// 未找到路由,尝试FRR(快速重路由)保护
IPv6SegmentRoutingHeader srh = iPv6Packet.getSegmentRoutingHeader();
if (srh != null) {
System.out.println("原SRH" + srh);
int segmentsLeft = srh.getSegmentsLeft();
if (segmentsLeft > 0) {
srh.getAddresses().remove(segmentsLeft); // 移除当前故障段
segmentsLeft--;
}
// 创建修复段列表
IPv6SegmentRoutingHeader repairSegments = klalbRouteProtol
.createSegmentList(srh.getAddresses().get(segmentsLeft));
if (repairSegments == null ||repairSegments.getAddresses().isEmpty()) {
System.out.println("FRR保护失败");
return;
}
repairSegments.getAddresses().remove(0); // 移除第一个段(当前节点)
srh.getAddresses().addAll(segmentsLeft + 1, repairSegments.getAddresses()); // 添加修复段
segmentsLeft += repairSegments.getAddresses().size(); // 更新剩余段数
srh.setSegmentsLeft(segmentsLeft);
iPv6Packet.setDestinationAddress(srh.getAddresses().get(segmentsLeft)); // 更新目的地址
} else {
return;
}
System.out.println("FRR修复SRH" + srh);
// 重新搜索路由表
List<RouteItem> searchResult2 = getTabelByAddress(dest);
if (searchResult2!=null&&(!searchResult2.isEmpty())) {
routingLoadBalance(linkfrom, iPv6Packet, reroute, dbg, searchResult2);
return;
}
} else {
// TTL超时,发送ICMP超时消息
sendTTLExceedPacket(iPv6Packet);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (debug) {
System.out.println(dbg.toString()); // 输出调试信息
}
}
}
// 搜索路由表找到匹配的路由项
/*private List<RouteItem> searchTable(IPv6Packet iPv6Packet, StringBuilder dbg)
throws IllegalRawDataException, IOException {
if (debug) {
dbg.append("----------------------------------------\n");
dbg.append("packet:" + iPv6Packet.getSourceAddress() + " -> " + iPv6Packet.getDestinationAddress() + "\n");
}
IPv6Address rk6 = iPv6Packet.getDestinationAddress();
List<RouteItem> table = getTabelByAddress(rk6);
RouteItem prevr = null;
List<RouteItem> routes = new ArrayList<>();
if (table == null) {
return routes; // 无匹配路由
}
// 遍历路由表,筛选可用路由
for (RouteItem tri : table) {
// 检查ECMP(等价多路径)条件
if (prevr != null) {
if (!tri.ECMPequals(prevr)) {
return routes; // 非ECMP路由,返回当前结果
}
}
routes.add(tri); // 添加到可用路由列表
prevr = tri;
}
return routes;
}*/
private List<RouteItem> getTabelByAddress(IPv6Address rk6) {
List<RouteItem> table = null;
// 最长前缀匹配搜索
for (int i = 128; i >= 0; i--) {
rk6 = rk6.maskWith(IPv6Address.createMask(i)); // 应用掩码
table = routeTabel1.get(i).get(rk6); // 查找匹配的路由表
if (table != null) {
break; // 找到匹配
}
}
return table;
}
private ReentrantLock congressLock = new ReentrantLock(); // 拥塞锁
private Condition congressCondition = congressLock.newCondition(); // 拥塞条件
// 负载均衡路由
private boolean routingLoadBalance(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, boolean reroute,
StringBuilder dbg, List<RouteItem> routes) throws IllegalRawDataException, IOException {
if(routes==null||routes.isEmpty()) {
//System.out.println("Route not found:" + iPv6Packet);
return false;
}
for (double i = 1; i < 100; i += 0.1) {
if (loadBalance(linkfrom, iPv6Packet, reroute, dbg, routes, i)) {
return true;
}
iPv6Packet.markCE(); // 标记拥塞
if (debug) {
dbg.append("ECN enabled.\n");
}
}
//System.out.println("Send failed:" + iPv6Packet);
LosscountAdder.inc(1);
if (debug) {
dbg.append("miss.\n"); // 路由失败
}
return false; // 路由失败
}
private boolean loadBalance(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, boolean reroute, StringBuilder dbg,
List<RouteItem> routes, double cscale)
throws IllegalRawDataException, IOException {
// 遍历可用路由进行负载均衡
for (RouteItem tri : routes) {
IPv6NetworkLink link = tri.getDestlink();
if (!link.isUp()) { // 检查链路状态
if (debug) {
dbg.append(tri + "\n");
dbg.append("linkdown.\n");
}
continue; // 跳过断开链路
}
if (link instanceof ControlledIPv6NetworkLink) {
if (((ControlledIPv6NetworkLink) link).isCongestion(iPv6Packet, cscale)) { // 检查拥塞
if (debug) {
dbg.append(tri + "\n");
dbg.append("congress.\n");
}
continue; // 跳过拥塞链路
}
}
if (debug) {
dbg.append(tri + "\n");
dbg.append("matched.\n");
}
// 找到可用链路,处理数据包
processPacket(linkfrom, iPv6Packet, tri, reroute);
return true;
}
return false;
}
// 处理数据包转发
private void processPacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, RouteItem ri, boolean reroute)
throws IllegalRawDataException, IOException {
int hop = iPv6Packet.getHopLimit();
if (ri.getDestlink().isLoopBack()) { // 环回链路处理
IPv6SegmentRoutingHeader srhh = iPv6Packet.getSegmentRoutingHeader();
if (srhh != null) {
processSRv6Packet(linkfrom, iPv6Packet, ri, srhh, iPv6Packet.getHopByHopHeader(), reroute); // SRv6特殊处理
} else {
sendPacketToRouteItem(iPv6Packet, ri);
}
} else { // 普通链路处理
// 检查重路由计数
if (iPv6Packet.getRerouteCounter().getAndIncrement() >= MAX_REROUTE_COUNT) {
return; // 超过最大重路由次数,丢弃
}
if (!reroute) {
hop--; // 减少TTL(非重路由时)
}
if (hop > 0) { // TTL有效
iPv6Packet.setHopLimit(hop); // 更新TTL
sendPacketToRouteItem(iPv6Packet, ri); // 发送数据包
} else {
sendTTLExceedPacket(iPv6Packet); // TTL超时
}
}
}
private void sendPacketToRouteItem(IPv6Packet iPv6Packet, RouteItem ri) throws IOException {
if (iPv6Packet.getPayload() instanceof ICMPv6PostcardPacket && ri.getDestlink().isLoopBack()) {
onPostcardReceive(iPv6Packet);
} else {
ri.getDestlink().sendPacket(iPv6Packet, ri.getNexthop());
}
}
private void onPostcardReceive(IPv6Packet postcards) {
ICMPv6PostcardPacket postcardsi = (ICMPv6PostcardPacket) postcards.getPayload();
for (PostcardEntry postcard : postcardsi.getPostcards()) {
IPv6Address sid = postcard.getSID();
List<RouteItem> ris = getTabelByAddress(sid);
if (ris != null) {
for (RouteItem ri : ris) {
if (ri.getNexthop().equals(sid)) {
if (ri.getDestlink() instanceof KLALBRemoteLink) {
KLALBRemoteLink rem = (KLALBRemoteLink) ri.getDestlink();
rem.onPostcardReceive(postcard);
}
}
}
}
}
}
// 发送ICMP TTL超时消息
private void sendTTLExceedPacket(IPv6Packet iPv6Packet) throws IOException, IllegalRawDataException {
enqueuePacketSendTask(() -> {
// 构建IPv6数据包封装ICMP消息
IPv6Packet icmpv = new IPv6Packet();
icmpv.setSourceAddress(locator.getAddress());
icmpv.setDestinationAddress(iPv6Packet.getSourceAddress());
icmpv.setTrafficClass(iPv6Packet.getTrafficClass());
icmpv.setVersion(6);
icmpv.setFlowLabel(0);
icmpv.setHopLimit(255); // ICMP消息TTL设为最大值
ICMPv6TimeExceededPacket ipl = ICMPv6TimeExceededPacket.createHopLimitExceeded(iPv6Packet);
ipl.setParent(icmpv);
ipl.updateChecksum();
icmpv.setPayload(ipl);
return icmpv;
});
}
// 处理SRv6数据包
private void processSRv6Packet(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, RouteItem ri,
IPv6SegmentRoutingHeader srhh, IPv6HopByHopHeader iPv6HopByHopHeader, boolean reroute)
throws IllegalRawDataException, IOException {
if (srhh.getSegmentsLeft() <= 0) { // 所有段已处理完毕
if (iPv6HopByHopHeader != null) {
int sl = srhh.getSegmentsLeft();
// IPv6Address prevSID
// =sl+1>=srhh.getAddresses().size()?iPv6Packet.getSourceAddress():srhh.getAddresses().get(sl+1);
if (linkfrom instanceof KLALBRemoteLink) {
processKLALBOAM(iPv6Packet, linkfrom.getAddressGroups().get(0).getAddress(),
((KLALBRemoteLink) linkfrom).getRemoteVaddr().getAddress(), iPv6HopByHopHeader);
}
}
// System.out.println(iPv6HopByHopHeader);
sendPacketToRouteItem(iPv6Packet, ri);
} else {
if (reroute) {
// 重路由处理
} else {
int oldSL = srhh.getSegmentsLeft();
if (iPv6HopByHopHeader != null) {
// IPv6Address prevSID
// =oldSL+1>=srhh.getAddresses().size()?iPv6Packet.getSourceAddress():srhh.getAddresses().get(oldSL+1);
if (linkfrom instanceof KLALBRemoteLink) {
processKLALBOAM(iPv6Packet, linkfrom.getAddressGroups().get(0).getAddress(),
((KLALBRemoteLink) linkfrom).getRemoteVaddr().getAddress(), iPv6HopByHopHeader);
}
}
// 正常SRv6处理:移动到下一个段
int newSL = oldSL - 1;
srhh.setSegmentsLeft(newSL); // 更新剩余段数
iPv6Packet.setDestinationAddress(srhh.getAddresses().get(newSL)); // 更新目的地址
}
// 记录热点地址(用于流量工程)
if (iPv6Packet.getPayload().getProtocolNumber() != KLALBRoutingProtocol.DEFAULT_PROTOCOL_NUMBER)
klalbRouteProtol.putHotspotAddress(iPv6Packet.getSourceAddress());
routePacket(linkfrom, iPv6Packet, reroute); // 继续路由
}
}
private void processKLALBOAM(IPv6Packet iPv6Packet, IPv6Address sourceSID, IPv6Address prevSID,
IPv6HopByHopHeader iPv6HopByHopHeader) {
KLALBOAMHopByHopTLV oam = null;
List<IPv6HopByHopTLV> tlvs = iPv6HopByHopHeader.getTlvs();
KLALBPassportHopByHopTLV prevEndPassport = null;
for (IPv6HopByHopTLV tlv : tlvs) {
if (tlv instanceof KLALBOAMHopByHopTLV) {
oam = (KLALBOAMHopByHopTLV) tlv;
} else if (tlv instanceof KLALBPassportHopByHopTLV) {
prevEndPassport = (KLALBPassportHopByHopTLV) tlv;
}
}
if (oam != null) {
long timentp = clock.getCurrentTimeNTP64().longValue();
int packetLength = (int) iPv6Packet.getTotalLength();
long oamt = oam.getTimestamp();
long delta = timentp - oamt;
long prevhop = oamt;
if (prevEndPassport != null) {
prevhop += prevEndPassport.getTimestampOffsetLong();
}
if (oam.isRecordPassport()) {
tlvs.add(new KLALBPassportHopByHopTLV(packetLength, (int) (delta >> 4)));
}
if (iPv6Packet.getPayload() instanceof ICMPv6PostcardPacket) {
} else {
boolean phop = oam.isPostcardToPreviousHop();
boolean psrc = oam.isPostcardToSource();
// System.out.println(iPv6Packet.getPayload());
if (phop) {
putPostcard(locator.getAddress(), prevSID, sourceSID, oam.getUUID(), prevhop, timentp - prevhop,
packetLength);
}
if (psrc) {
putPostcard(locator.getAddress(), iPv6Packet.getSourceAddress(), sourceSID, oam.getUUID(), oamt,
delta, packetLength);
}
}
}
}
private TimeoutConcurrentHashMap<Pair<IPv6Address, IPv6Address>, MessageBatcher<PostcardEntry>> postcardBatch = new TimeoutConcurrentHashMap<>(
1000000000L);
private void putPostcard(IPv6Address src, IPv6Address dst, IPv6Address srcSID, UUID uuid, long timeStamp,
long delta, int packetLength) {
PostcardEntry pn = new PostcardEntry(srcSID, uuid, timeStamp, (int) (delta >> 4), packetLength);
/*Pair<IPv6Address, IPv6Address> addressPair = new Pair<IPv6Address, IPv6Address>(src, dst);
MessageBatcher<PostcardEntry> batch = postcardBatch.computeIfAbsent(addressPair, (k) -> {
MessageBatcher<PostcardEntry> mb = new ArrayListMessageBatcher<PostcardEntry>(30, 2000000L);
mb.setConsumer((list) -> {
enqueuePacketSendTask(() -> {
IPv6Packet icmpv = new IPv6Packet();
icmpv.setSourceAddress(k.first);
icmpv.setDestinationAddress(k.second);
icmpv.setTrafficClass(0);
icmpv.setVersion(6);
icmpv.setFlowLabel(0);
icmpv.setHopLimit(255); // ICMP消息TTL设为最大值
ICMPv6PostcardPacket ipl = new ICMPv6PostcardPacket();
ipl.getPostcards().addAll(list);
ipl.setParent(icmpv);
ipl.updateChecksum();
icmpv.setPayload(ipl);
return icmpv;
});
});
return mb;
});
postcardBatch.refresh(addressPair);
batch.putMessage(pn);*/
enqueuePacketSendTask(() -> {
IPv6Packet icmpv = new IPv6Packet();
icmpv.setSourceAddress(src);
icmpv.setDestinationAddress(dst);
icmpv.setTrafficClass(0);
icmpv.setVersion(6);
icmpv.setFlowLabel(0);
icmpv.setHopLimit(255); // ICMP消息TTL设为最大值
ICMPv6PostcardPacket ipl = new ICMPv6PostcardPacket();
ipl.getPostcards().addAll(List.of(pn));
ipl.setParent(icmpv);
ipl.updateChecksum();
icmpv.setPayload(ipl);
return icmpv;
});
}
private static HighPerformanceExecutor2 defaultExecutor = new HighPerformanceExecutor2(
(int) (Runtime.getRuntime().availableProcessors()), Thread.ofVirtual().name("SRv6 Routing").factory());
//private static HighPerformanceExecutor2 defaultExecutor = new HighPerformanceExecutor2(4, Thread.ofVirtual().name("SRv6 Routing").factory());
public static HighPerformanceExecutor2 getDefaultExecutor() {
return defaultExecutor;
}
// private ArrayBlockingQueue<Supplier<IPv6Packet>> packetQueue=new
// ArrayBlockingQueue<>(10000);
public void enqueuePacketSendTask(Supplier<IPv6Packet> sendTask) {
// packetQueue.add(object);
defaultExecutor.executeWithCongestionReport((state) -> {
try {
long start=System.nanoTime();
IPv6Packet packet=sendTask.get();
if(state) {
packet.markCE();
}
insertSRHandRoutePacket(null, packet); // 插入SRH并路由
long time=System.nanoTime()-start;
backplaneCount(time,state);
} catch (Exception e) {
e.printStackTrace();
}
},20);
}
public void runPacketSendTask(Supplier<IPv6Packet> sendTask) {
try {
boolean state=false;
long start=System.nanoTime();
IPv6Packet packet=sendTask.get();
if(state) {
packet.markCE();
}
insertSRHandRoutePacket(null, packet); // 插入SRH并路由
long time=System.nanoTime()-start;
backplaneCount(time,state);
} catch (Exception e) {
e.printStackTrace();
}
}
public void onReceive(IPv6NetworkLink link,IPv6Packet t){
if (unduplicate(t)) {
insertSRHandRoutePacket(link, t); // 插入SRH并路由数据包
}
}
public void enqueuePacketReceiveTask(IPv6NetworkLink link, Supplier<IPv6Packet> pack) {
defaultExecutor.executeWithCongestionReport((state) -> {
try {
long start=System.nanoTime();
IPv6Packet packet = pack.get();
if(state) {
packet.markCE();
}
onReceive(link ,packet);
long time=System.nanoTime()-start;
backplaneCount(time,state);
} catch (Exception e) {
e.printStackTrace();
}
},20);
}
public void enqueuePacket(IPv6Packet packet) {
enqueuePacketSendTask(() -> {
return packet;
});
}
//private BandwidthSampler sampler=new BandwidthSampler();
private FixedSizeStripedLongCounter timeAdder=KLALBUtils.createCounter();
private FixedSizeStripedLongCounter countAdder=KLALBUtils.createCounter();
private FixedSizeStripedLongCounter ECNcountAdder=KLALBUtils.createCounter();
private FixedSizeStripedLongCounter LosscountAdder=KLALBUtils.createCounter();
private void backplaneCount(long time,boolean ECN) {
timeAdder.inc(time);
countAdder.inc(1);
if(ECN) {
ECNcountAdder.inc(1);
}
}
private volatile long backplaneTime=0;
private volatile double ECNRate=0;
private volatile double LossRate=0;
private volatile long backplanePPS=0;
private volatile long backplanePPSMax=0;
private volatile long prevTime=System.nanoTime();
private Timer backplaneTimer=new Timer();
private void updateBackplaneCounter() {
long curr=System.nanoTime();
long totalTime=timeAdder.getAndReset();
long totalCount=countAdder.getAndReset();
long ECNCount=ECNcountAdder.getAndReset();
long LossCount=LosscountAdder.getAndReset();
if(totalCount!=0) {
backplaneTime=totalTime/totalCount;
ECNRate=((double)ECNCount)/totalCount;
LossRate=((double)LossCount)/totalCount;
}
backplanePPS=totalCount*1000000000L/(curr-prevTime);
if(backplanePPSMax<backplanePPS) {
backplanePPSMax=backplanePPS;
}else {
backplanePPSMax=(backplanePPSMax*999+backplanePPS)/1000;
}
prevTime=curr;
}
public long getBackplaneTime() {
return backplaneTime;
}
public long getBackplanePPS() {
return backplanePPS;
}
public long getBackplanePPSMax() {
return backplanePPSMax;
}
public double getECNRate() {
return ECNRate;
}
public double getLossRate() {
return LossRate;
}
// 构造函数
public SRv6Router(IPv6AddressGroup hostAddress, HighAccuracyClock clock) {
super();
this.locator = hostAddress;
this.clock = clock;
// initWorkerThreads();
// 创建环回链路
this.inLoopBack = new LoopbackIPv6NetworkLink(
List.of(new IPv6AddressGroup(IPv6Address.LOOPBACK, 128), hostAddress), this);
linkTabel.add(inLoopBack); // 添加到链路表
backplaneTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
updateBackplaneCounter();
}
}, 100, 100);
}
/*
* private void initWorkerThreads() { int
* threads=Runtime.getRuntime().availableProcessors()*4; for(int
* i=0;i<threads;i++) { ThreadTool.makeVThread("SRv6 Router Thread"+i,()->{
* while(true) { try { Supplier<IPv6Packet>packetSup= packetQueue.take();
* insertSRHandRoutePacket(packetSup.get()); // 插入SRH并路由 }catch(Exception e) {
* e.printStackTrace(); } } } ).start(); } }
*/
private KLALBRoutingProtocol klalbRouteProtol = null; // KLALB路由协议实例
// 启动KLALB路由协议
public void runKLALBRouteProtocol() {
if (klalbRouteProtol != null)
throw new IllegalStateException("KLALB routing protocol is already running!");
klalbRouteProtol = new KLALBRoutingProtocol(this);
klalbRouteProtol.start(); // 启动协议
}
public KLALBRoutingProtocol getKlalbRouteProtol() {
return klalbRouteProtol;
}
public LoopbackIPv6NetworkLink getinLoopback() {
return inLoopBack;
}
// 获取邻居信息
public List<Neighbor> getNeighbors() {
List<Neighbor> result = new ArrayList<>();
List<IPv6NetworkLink> links = getLinkTabel();
Object[] nls = links.toArray();
for (int i = 0; i < nls.length; i++) {
IPv6NetworkLink nl = (IPv6NetworkLink) nls[i];
if ((!nl.isLoopBack())&&nl.isUp()) { // 排除环回接口
List<Neighbor> neis = nl.getNeighborsInfo();
for (Iterator<Neighbor> iteratorx = neis.iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
result.add(addresses); // 添加邻居信息
}
}
}
return result;
}
// 获取所有SID
public Set<IPv6AddressGroup> getLocators() {
Set<IPv6AddressGroup> result = new HashSet<>();
List<IPv6NetworkLink> links = getLinkTabel();
Object[] nls = links.toArray();
for (int i = 0; i < nls.length; i++) {
IPv6NetworkLink nl = (IPv6NetworkLink) nls[i];
if (!nl.isLoopBack()) { // 排除环回接口
List<Neighbor> neis = nl.getNeighborsInfo();
for (Iterator<Neighbor> iteratorx = neis.iterator(); iteratorx.hasNext();) {
Neighbor addresses = (Neighbor) iteratorx.next();
if (addresses.getLocator() != null)
result.add(addresses.getLocator()); // 添加邻居SID
}
}
}
return result;
}
}