forked from KNEMC/KLALB
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21b975676d | ||
|
|
2c111770b3 | ||
|
|
52f44335e4
|
||
|
|
a06e1cb5eb | ||
|
|
58913254e0 | ||
|
|
02d7bcd93b | ||
|
|
1e52e82d6d | ||
|
|
3023fe5b2a |
+3
-1
@@ -4,7 +4,6 @@
|
|||||||
<classpathentry kind="lib" path="lib/gson-2.1.jar"/>
|
<classpathentry kind="lib" path="lib/gson-2.1.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/javassist.jar" sourcepath="C:/Users/ADMINI~1/AppData/Local/Temp/1/.org.sf.feeling.decompiler1686963856070/source/javassist-3.29.2-GA-sources.jar"/>
|
<classpathentry kind="lib" path="lib/javassist.jar" sourcepath="C:/Users/ADMINI~1/AppData/Local/Temp/1/.org.sf.feeling.decompiler1686963856070/source/javassist-3.29.2-GA-sources.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/ini4j.jar"/>
|
<classpathentry kind="lib" path="lib/ini4j.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/JFreeChart1.5.2.jar"/>
|
|
||||||
<classpathentry kind="lib" path="lib/toml4j-0.7.1.jar"/>
|
<classpathentry kind="lib" path="lib/toml4j-0.7.1.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/pcap4j-core-1.8.2.jar" sourcepath="C:/Users/ADMINI~1/AppData/Local/Temp/1/.org.sf.feeling.decompiler1725520274095/source/pcap4j-core-1.8.2-sources.jar"/>
|
<classpathentry kind="lib" path="lib/pcap4j-core-1.8.2.jar" sourcepath="C:/Users/ADMINI~1/AppData/Local/Temp/1/.org.sf.feeling.decompiler1725520274095/source/pcap4j-core-1.8.2-sources.jar"/>
|
||||||
<classpathentry kind="lib" path="lib/pcap4j-packetfactory-propertiesbased-1.8.2.jar"/>
|
<classpathentry kind="lib" path="lib/pcap4j-packetfactory-propertiesbased-1.8.2.jar"/>
|
||||||
@@ -29,5 +28,8 @@
|
|||||||
<attribute name="module" value="true"/>
|
<attribute name="module" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
|
<classpathentry kind="lib" path="lib/jfreechart-1.5.3.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/jfreechart-1.5.3-javadoc.jar"/>
|
||||||
|
<classpathentry kind="lib" path="lib/jfreechart-1.5.3-sources.jar"/>
|
||||||
<classpathentry kind="output" path="bin"/>
|
<classpathentry kind="output" path="bin"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|||||||
Generated
+38
@@ -0,0 +1,38 @@
|
|||||||
|
<component name="libraryTable">
|
||||||
|
<library name="jfreechart-1.5.3">
|
||||||
|
<CLASSES>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jfreechart-1.5.3.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/disruptor-4.0.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/gson-2.1.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/ini4j.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/javassist.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/JavaTUN0.3.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jctools-core-4.0.6.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/KNElib1.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/KNEOptimize.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/pcap4j-core-1.8.2.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/pcap4j-packetfactory-propertiesbased-1.8.2.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/pcap4j-packetfactory-static-1.8.2.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/pcap4j-packettest-1.8.2-tests.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/pcap4j-sample-1.8.2.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/slf4j-api-2.0.9.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/slf4j-api-2.0.9-tests.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/toml4j-0.7.1.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/uuid-creator-6.1.1.jar!/" />
|
||||||
|
</CLASSES>
|
||||||
|
<JAVADOC>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jctools-core-4.0.6-javadoc.jar!/" />
|
||||||
|
</JAVADOC>
|
||||||
|
<SOURCES>
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jfreechart-1.5.3-sources.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/disruptor-4.0.0-sources.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/ini4j.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/JavaTUN0.3.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/jctools-core-4.0.6-sources.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/KNElib1.0.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/slf4j-api-2.0.9-sources.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/toml4j-0.7.1.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/uuid-creator-6.1.1-sources.jar!/" />
|
||||||
|
</SOURCES>
|
||||||
|
</library>
|
||||||
|
</component>
|
||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_26" project-jdk-name="jdk-26.0.1" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/classes" />
|
<output url="file://$PROJECT_DIR$/classes" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -1,39 +1,101 @@
|
|||||||
# KLALB Repository Guide
|
# AGENTS.md
|
||||||
|
|
||||||
KLALB is a Java SRv6/load-balancing system. Start at `org.kne.cloud.network.klalb.KLALBMain`; runtime configuration is root-relative `klalb-config.json`.
|
KLALB ("KLALB Decentralized SRv6 Network") — Java load-balancing/tunnel system that merges multiple WAN links into one virtual IPv6/SRv6 network. Version constant lives in `src/org/kne/cloud/network/klalb/CONST.java`. Protocol specs and manuals are the Chinese `.docx` files in the repo root.
|
||||||
|
|
||||||
## Build And Run
|
## Build & run
|
||||||
|
|
||||||
- This is an Eclipse Java project, not Maven or Gradle: `src/` contains sources, `lib/` vendored dependencies, and `bin/` compiled output. `.classpath` targets Java 25.
|
No Maven/Gradle. Plain Eclipse/IntelliJ project: dependencies are vendored jars in `lib/`, output goes to `bin/` (gitignored). When adding a jar, update **both** `.classpath` and `KLALB.iml`.
|
||||||
- Source files contain Chinese text, so compile with UTF-8 from the repository root:
|
|
||||||
|
Compile (`javac` is NOT on PATH — use the full JDK path; `-encoding UTF-8` is mandatory because sources contain Chinese text):
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
& "C:\Program Files\Zulu\zulu-25\bin\javac.exe" -encoding UTF-8 -cp "lib/*" -d bin (Get-ChildItem -Recurse src -Filter *.java | ForEach-Object FullName)
|
& "C:\Program Files\Zulu\zulu-25\bin\javac.exe" -encoding UTF-8 -cp "lib/*" -d bin (Get-ChildItem -Recurse src -Filter *.java | ForEach-Object FullName)
|
||||||
```
|
```
|
||||||
|
|
||||||
- Run from the repository root. `src` must stay on the classpath because manual compilation does not copy resource bundles:
|
Warnings about `ThreadTool` varargs / deprecated `finalize` are pre-existing and expected — success = exit code 0. After recompiling, restart the running app (IDE-debugged JVMs keep old classes).
|
||||||
|
|
||||||
|
Run from the repo root — CWD matters:
|
||||||
|
- reads `klalb-config.json` from CWD
|
||||||
|
- loads native libs from CWD: `tuntap4j.dll/.so/.dylib`, `wintun.dll`, `fastcopy.dll` (TUN device support)
|
||||||
|
- classpath must include `src` as well as `bin`: i18n bundles (`/klalb_*.properties`) and images (`/assets/*`) are classpath resources that Eclipse copies to `bin` but manual `javac` does not
|
||||||
|
|
||||||
```powershell
|
```powershell
|
||||||
& "C:\Program Files\Zulu\zulu-25\bin\java.exe" --enable-native-access=ALL-UNNAMED "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" -cp "bin;src;lib/*" org.kne.cloud.network.klalb.KLALBMain
|
java --enable-native-access=ALL-UNNAMED "--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED" -cp "bin;src;lib/*" org.kne.cloud.network.klalb.KLALBMain
|
||||||
```
|
```
|
||||||
|
|
||||||
- Native libraries and `klalb-config.json` are resolved from the current directory; restart the JVM after recompiling. TUN creation requires elevation, so use `"enableTUN": false` for non-admin checks.
|
IDE metadata targets JDK 26 (`jdk-26.0.1`); the tree also compiles cleanly on JDK 25. `.classpath` now references the standard container `JavaSE-25` — an execution-environment spec that any JDK ≥25 satisfies, so it works unchanged on JDK 26 machines too (the original named `jdk-26.0.1` VM broke VS Code import on machines without it). `.vscode/settings.json` maps `JavaSE-25` to the locally installed Adoptium JDK; register every installed JDK there when adding another one. Keep compiler compliance ≤25 (`.settings` pins 19) so both JDKs stay usable.
|
||||||
|
|
||||||
## Dashboard
|
Runtime gotchas (all verified):
|
||||||
|
- On JDK 25, `KNEOptimize.jar`'s `FastLib` reflects into `jdk.internal.misc.Unsafe`; without the two JVM flags above it throws `InaccessibleObjectException` at startup (app still runs).
|
||||||
- `dashboard/` is a Git submodule. Commit dashboard changes in that repository, then update the parent submodule pointer.
|
- Creating the SRv6 TUN adapter (`WintunCreateAdapter`) requires an elevated shell; without admin rights it logs "创建虚拟网卡失败" and continues with only the `inLoopBack` interface — links/bridges still work.
|
||||||
- Run frontend commands from `dashboard/`: `pnpm install --frozen-lockfile`, `pnpm lint`, `pnpm typecheck`, and `pnpm build`. The build is `tsc -b && vite build` and produces `dashboard/dist`, which the Java server hosts.
|
- To disable TUN creation completely (e.g. for non-admin UI/routing testing), set `"enableTUN": false` in `klalb-config.json` or toggle off "启用 TUN 虚拟网卡" in GUI/Web settings.
|
||||||
- Vite proxies `/api` to `http://127.0.0.1:4665`; use `pnpm dev` only with the Java API running there.
|
- Routing broadcast (`RouterInfo`) transmits `deviceName`, which topology and node overview panels display. `deviceDescription` is NOT broadcast — it only leaves the node in full node-info query responses (see srv6 API below); `ExtraRoutes` remain local controller configs.
|
||||||
|
|
||||||
## Verification
|
## Verification
|
||||||
|
|
||||||
- No repository test runner or CI workflow is configured. For Java changes, compile and launch the app; for dashboard changes, run `pnpm typecheck` and `pnpm build`.
|
No test suite, no CI. Classes named `*Test*` (`nathole/`, `ntp/`) are manual `main()` harnesses requiring real network peers. Practical check = compile succeeds + app launches.
|
||||||
|
|
||||||
## Important Boundaries
|
## Architecture
|
||||||
|
|
||||||
- `KLALBConfigItem` is a polymorphic JSON array keyed by case-sensitive `Type`. New types need serializer and deserializer support; preserve unknown items' raw JSON.
|
- Entrypoint `org.kne.cloud.network.klalb.KLALBMain`: load config → build `KLALBProxySystem` → open Swing GUI (`KLALBStateGUI3`) unless `"nogui": true` → start `KLALBWebServer` (if `"webUI": true` or web server enabled, default port `4665`) → interactive console (`help`, `links-state`, `route`, `kperf`, ...).
|
||||||
- `/api/config` is field-by-field parsing, not whole-object Gson mapping. Keep legacy key aliases in sync with new fields.
|
- `org.kne.cloud.network.klalb.web.KLALBWebServer` — built-in HTTP/SSE server (JDK `HttpServer`):
|
||||||
- Vendored Gson is `2.1`: responses that are `JsonElement` instances must be serialized with `JsonElement.toString()`, not reflective `gson.toJson(Object)`.
|
- API endpoints: `/api/status`, `/api/events` (SSE stream, 200ms intervals), `/api/links`, `/api/links/action`, `/api/links/reconnect`, `/api/routing-table`, `/api/nodes` (topology graph), `/api/node-info?address=<ipv6>` (on-demand full node info), `/api/config`.
|
||||||
- UI strings use `UIEnv.getRsb()`; add keys to both `src/klalb_zh_CN.properties` and `src/klalb_en_US.properties`.
|
- Static file hosting / SPA fallback: serves `dashboard/dist/` assets directly.
|
||||||
- `KLALBController.PublishedNodeInfo` is the thread-safe node-info source. Publish profile, effective external endpoints, and extra routes through the controller so snapshots and update flags remain coherent. Peer queries are separate profile, endpoint, and extra-route requests; use `NodeInfoQueryCoordinator` when a consumer needs an aggregate detail result.
|
- `org.kne.cloud.network` — generic socket framework: `VirtualSocket*` hierarchy, `SocketBridge` port-forwarding proxies, `ProtocolDetector` (multi-protocol mux on one port), `MultiProtocolSocketAddress` = URI-style addresses (`tcp://`, `udp://`, `kltp://`, `ntp://`) dispatched through the `SocketType` registry.
|
||||||
- `RouterInfo` retains an empty legacy UTF slot. `RouterInfoPacket` appends optional update flags behind a marker; treat binary codec changes as mesh-compatibility work and preserve old-reader behavior.
|
- `...network.klalb` — app core: `KLALBController` (the virtual SRv6 network), `KLALBRemoteLink` (WAN lines), `*Packet` wire-format classes, virtual socket implementations.
|
||||||
|
- `...network.congestion` — pluggable congestion control (BBR, Vegas2, DCTCP...), chosen via `"congestionAlgorithm"` in config.
|
||||||
|
- `...network.kltp` — custom reliable transport protocol (packets/streams).
|
||||||
|
- `...network.ipv6`, `...network.srv6` — packet codecs, route table, Dijkstra path computation.
|
||||||
|
- **Node-info query API** (`...network.srv6`, JSON datagrams on `KLALBRoutingProtocol.DEFAULT_PORT=1001`): `KLALBRoutingProtocolAPIServer/Client` speak two request types —
|
||||||
|
- `nodeinfotinyreq/resp` → device name ONLY; never gated by any flag (name is public via broadcast anyway).
|
||||||
|
- `nodeinfofullreq/resp` → externalEndpoints + deviceName + deviceDescription. `denyExternalEndpointQuery=true` hides ONLY the endpoint list (`data=null`); name/description still answer.
|
||||||
|
- GUI rule: opening `NodeInformationPanel` = Full query; use `requestNodeInfoTiny` for lightweight/background lookups. Legacy `openlines*` message types were removed — mixed-version meshes get silence, so upgrade the whole network together.
|
||||||
|
- `JsonDataPacket` stores its UTF-8 payload length in a 2-byte header field: keep every JSON message under 64 KiB.
|
||||||
|
- `...network.frpc` — frp client integration.
|
||||||
|
- `...klalb.ui` — all Swing UI code.
|
||||||
|
|
||||||
|
## Frontend (Dashboard)
|
||||||
|
|
||||||
|
Located in `dashboard/`:
|
||||||
|
- **Git layout**: `dashboard/` is a separate git repo wired in as a submodule (own origin on `git.code.cq.cn`). Commit frontend changes inside `dashboard/` first, then bump the submodule pointer in the parent repo — parent-repo commits alone do not capture them.
|
||||||
|
- **Stack**: Vite + React 19 + TypeScript + Tailwind CSS v4 + `@base-ui/react` (style: `base-nova`, icons: `lucide-react`, toasts: `@base-ui/react/toast`).
|
||||||
|
- **Routing**: Hash-based routing (`#/overview`, `#/connections`, `#/routing-table`, `#/topology`, `#/settings`) for seamless SPA hosting under Java `KLALBWebServer`.
|
||||||
|
- **Package Manager**: `pnpm` (run all commands from `dashboard/` directory).
|
||||||
|
- **Component installation**: **Must** use CLI via `pnpm dlx shadcn@latest add <component>` (e.g. `pnpm dlx shadcn@latest add alert card badge toast`). Never create or fake shadcn components manually. Non-shadcn libs (`@xyflow/react`, `d3-force`) are installed via plain `pnpm add`.
|
||||||
|
- **Commands**:
|
||||||
|
- `pnpm dev` — Start Vite dev server (proxies `/api` to backend `http://127.0.0.1:4665`).
|
||||||
|
- `pnpm build` — Typecheck and build SPA to `dashboard/dist` (which Java `KLALBWebServer` serves directly).
|
||||||
|
- `pnpm lint` / `pnpm typecheck` — Verification.
|
||||||
|
- **Pages & data flow**:
|
||||||
|
- Overview / Connections read the SSE stream (`use-klalb-sse.ts`, 200ms pushes of status + links).
|
||||||
|
- Settings loads/saves `/api/config` (`use-klalb-config.ts`); save payload must keep legacy field aliases alongside new names for compatibility.
|
||||||
|
- Routing table polls `/api/routing-table` every 1s (`use-routing-table.ts`); `cost` is delay-derived and displayed in milliseconds.
|
||||||
|
- Topology polls `/api/nodes` every 1s (`use-topology.ts`) — SSE does NOT carry topology.
|
||||||
|
- Selecting a topology node queries `/api/node-info`; remote node descriptions require a full SRv6 node-info request and can time out after 3s.
|
||||||
|
- Topology layout: `d3-force` headless simulation (recomputed only when node/edge structure changes) rendered by `@xyflow/react` with custom `device-node` / `link-edge` components in `src/components/topology/`.
|
||||||
|
- React hooks lint rule forbids `setState` synchronously inside effects — initialize form state via component `key` remount + lazy `useState(() => ...)` initializers (see `SettingsForm` pattern).
|
||||||
|
|
||||||
|
## Config
|
||||||
|
|
||||||
|
`klalb-config.json` is an array of items discriminated by their `"Type"` field. Adding a new item type requires a `KLALBConfigItem` subclass **plus** new cases in both `KLALBConfigItem.getDefaultJsonDeserializer()` and `getDefaultJsonSerializer()`; unknown types are preserved as `UnknownKLALBConfigItem`. Any Gson instance handling config must register these adapters via `registerToGsonBuilder` (see `KLALBProxySystem`).
|
||||||
|
|
||||||
|
Key controller config fields:
|
||||||
|
- `externalEndpoints` / `autoConnections`: published vs auto-connect endpoint lists (renamed from `openConnections`, which itself replaced legacy `LineTable`; the old name was a developer naming mistake — these addresses are this node's externally published endpoints, not "connections").
|
||||||
|
- `ntpServers`: time server list (replaces `ntpServerTable`).
|
||||||
|
- `denyExternalEndpointQuery` / `denyExternalEndpointBroadcast`: safety flags — the query flag hides ONLY the external-endpoint list in full node-info responses (device name/description still answer; Tiny queries are never gated), the broadcast flag disables LAN multicast discovery (renamed from `denyConnectionQuery` / `denyConnectionBroadcast`, which replaced `denyLineTableQuery` / `denyLineTableBroadcast`).
|
||||||
|
- `enableTUN`: boolean flag for TUN interface creation (`"TUNName"` configures device name).
|
||||||
|
- `webListen`: Web API listen address, normally `http://0.0.0.0:4665`; legacy `webPort` is accepted on load/API input.
|
||||||
|
|
||||||
|
Legacy JSON keys are still accepted on load: `KLALBConfigItem.getDefaultJsonDeserializer()` normalizes old key names (`openConnections`/`LineTable`, `denyConnectionQuery`, `denyLineTable*`, ...) before reflective deserialization (manual rewrite because gson-2.1 has no `@SerializedName(alternate=...)`), and `handleConfig` in the web server accepts them too. New saves always write canonical names.
|
||||||
|
|
||||||
|
Gson quirks:
|
||||||
|
- **gson-2.1 (vendored) is ancient**: its `JSON_ELEMENT` adapter factory only matches exact `JsonElement.class`, NOT subclasses. Calling `gson.toJson(Object)` with a runtime `JsonObject`/`JsonArray` reflectively serializes the internal field as `{"members": {...}}`. `KLALBWebServer.sendJsonResponse` guards against this by using `JsonElement.toString()` for JsonElement instances — keep that guard when adding new response paths. SSE avoids the issue entirely via `JsonObject.toString()`.
|
||||||
|
- `/api/config` GET/POST is parsed field-by-field in `KLALBWebServer.handleConfig` (NOT whole-object Gson reflection) because polymorphic fields (`List<InetAddress>`, `List<MultiProtocolSocketAddress>`) break reflective mapping. Keep new config fields in sync there, accepting both legacy and new JSON key names.
|
||||||
|
- `InetAddress`, `MultiProtocolSocketAddress`, and `KLALBConfigItem` custom adapters are registered on the shared Gson in `KLALBProxySystem`; the web server reuses that instance via `proxySystem.getGson()`.
|
||||||
|
- Saving via web API persists through `KLALBProxySystem.saveConfigToFile()` (GUI save consumer takes precedence when present).
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- Sources are UTF-8; comments, log/UI strings, and commit messages are largely Chinese.
|
||||||
|
- UI strings go through `UIEnv.getRsb().getString(...)`; add keys to **both** `src/klalb_zh_CN.properties` and `src/klalb_en_US.properties`.
|
||||||
|
- `client.cfg`, `server.cfg`, `linetable.txt` at the root are example line-table/port-rule files loaded via the GUI file picker — not hardwired paths.
|
||||||
|
|||||||
@@ -249,5 +249,6 @@
|
|||||||
</library>
|
</library>
|
||||||
</orderEntry>
|
</orderEntry>
|
||||||
<orderEntry type="jdk" jdkName="jdk-26.0.1" jdkType="JavaSDK" />
|
<orderEntry type="jdk" jdkName="jdk-26.0.1" jdkType="JavaSDK" />
|
||||||
|
<orderEntry type="library" name="jfreechart-1.5.3" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
//加速线路
|
|
||||||
{KLALBRemote}->43.248.189.107:35000
|
|
||||||
{KLALBRemote}->cn-bj-bgp-3.openfrp.top:65529
|
|
||||||
{KLALBRemote}->180.76.147.250:65529
|
|
||||||
{KLALBRemote}->cn-ah-dx-1.natfrp.cloud:65529
|
|
||||||
{KLALBRemote}->cn-nn-dx-1.natfrp.cloud:65529
|
|
||||||
{KLALBRemote}->cn-wh-dx-1.natfrp.cloud:65529
|
|
||||||
{KLALBRemote}->cn-zz-bgp-10.natfrp.cloud:23330
|
|
||||||
{KLALBRemote}->cn-zz-bgp-7.natfrp.cloud:33336
|
|
||||||
{KLALBRemote}->43.143.109.64:49965
|
|
||||||
{KLALBRemote}->frp.104300.xyz:49965
|
|
||||||
{KLALBRemote}->us.afrps.cn:49966
|
|
||||||
{KLALBRemote}->hk.afrps.cn:49966
|
|
||||||
{KLALBRemote}->la.afrps.cn:49966
|
|
||||||
{KLALBRemote}->frp.freefrp.net:49965
|
|
||||||
{KLALBRemote}->frp1.freefrp.net:49965
|
|
||||||
{KLALBRemote}->frp2.freefrp.net:49965
|
|
||||||
{KLALBRemote}->frp4.freefrp.net:49965
|
|
||||||
|
|
||||||
0.0.0.0:25565->{KLALBVirtual}[171d:a999:e697:4b23:ae52:9f29:4532:e1ee]:25565
|
|
||||||
+1
-1
Submodule dashboard updated: 8c13af680a...885a0c2d89
Binary file not shown.
@@ -1,79 +0,0 @@
|
|||||||
[
|
|
||||||
{"Type":"KLALBController" ,
|
|
||||||
"TCPListen" : "0.0.0.0:4565",
|
|
||||||
"UDPListen" : "{UDP}0.0.0.0:4572",
|
|
||||||
"VirtualSocketName" : "KLALB_Stream",
|
|
||||||
"LineTable":["43.248.189.107:65529",
|
|
||||||
"cn-bj-bgp-3.openfrp.top:65529",
|
|
||||||
"180.76.147.250:65529",
|
|
||||||
"cn-ah-dx-1.natfrp.cloud:65529",
|
|
||||||
"cn-nn-dx-1.natfrp.cloud:65529",
|
|
||||||
"cn-wh-dx-1.natfrp.cloud:65529",
|
|
||||||
"cn-zz-bgp-10.natfrp.cloud:23330",
|
|
||||||
"cn-zz-bgp-7.natfrp.cloud:33336",
|
|
||||||
"43.143.109.64:49965",
|
|
||||||
"frp.104300.xyz:49965",
|
|
||||||
"us.afrps.cn:49966",
|
|
||||||
"hk.afrps.cn:49966",
|
|
||||||
"la.afrps.cn:49966",
|
|
||||||
"frp.freefrp.net:49965",
|
|
||||||
"frp1.freefrp.net:49965",
|
|
||||||
"frp2.freefrp.net:49965",
|
|
||||||
"frp4.freefrp.net:49965",
|
|
||||||
"cn-he-plc-2.openfrp.top:4572",
|
|
||||||
"{UDP}cn-he-plc-2.openfrp.top:4572",
|
|
||||||
"frp-mom.top:22226",
|
|
||||||
"frp-man.top:36555",
|
|
||||||
"us-sjc-bgp-2.openfrp.top:36555",
|
|
||||||
"us-sjc-bgp-1.openfrp.top:36555",
|
|
||||||
"[240e:340:d856:b700:6d02:6a6a:f9fc:865b]:4572"]
|
|
||||||
},
|
|
||||||
{"Type":"SocketBridge" ,
|
|
||||||
"Listen" : "0.0.0.0:4572",
|
|
||||||
"Bridge":{
|
|
||||||
"KLALB" : "SocketBridge",
|
|
||||||
"RDP":"SocketBridge",
|
|
||||||
"HTTP":"SocketBridge",
|
|
||||||
"HTTPS":"SocketBridge",
|
|
||||||
"DEFAULT":"MinecraftSocketBridge23332"
|
|
||||||
} ,
|
|
||||||
"Connect" : {
|
|
||||||
"KLALB" : "127.0.0.1:4565",
|
|
||||||
"RDP":"127.0.0.1:3389",
|
|
||||||
"HTTP":"127.0.0.1:5212",
|
|
||||||
"HTTPS":"192.168.1.235:443",
|
|
||||||
"DEFAULT":"127.0.0.1:36555"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{"Type":"SocketBridge" ,
|
|
||||||
"Listen" : "{KLALB_Stream}[::0]:23332",
|
|
||||||
"Bridge":"MinecraftSocketBridge23332",
|
|
||||||
"Connect" : "127.0.0.1:36555"
|
|
||||||
},
|
|
||||||
{ "Type":"SocketBridge" ,
|
|
||||||
"Listen" : "{KLALB_Stream}[::0]:23333",
|
|
||||||
"Bridge":"SocketBridge",
|
|
||||||
"Connect" : "127.0.0.1:5212"
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{"Type":"SocketBridge" ,
|
|
||||||
"Listen" : "0.0.0.0:25561",
|
|
||||||
"Bridge":{
|
|
||||||
"KLALB" : "SocketBridge",
|
|
||||||
"DEFAULT":"MinecraftSocketBridge23330"
|
|
||||||
} ,
|
|
||||||
"Connect" : {
|
|
||||||
"KLALB" : "127.0.0.1:4565",
|
|
||||||
"DEFAULT":"127.0.0.1:25562"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{"Type":"SocketBridge" ,
|
|
||||||
"Listen" : "{KLALB_Stream}[::0]:23330",
|
|
||||||
"Bridge":"MinecraftSocketBridge23330",
|
|
||||||
"Connect" : "127.0.0.1:25562"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,29 +0,0 @@
|
|||||||
0.0.0.0:35000(RDP)->192.168.1.233:3389
|
|
||||||
0.0.0.0:35000(HTTPS)->192.168.1.233:8444
|
|
||||||
0.0.0.0:35000(HTTP)->192.168.1.233:5212
|
|
||||||
0.0.0.0:35000(SSH)->192.168.1.236:22
|
|
||||||
0.0.0.0:35000(KLALB)->{KLALBRemote}
|
|
||||||
0.0.0.0:35000->127.0.0.1:35001 //Winds服(普通线路)
|
|
||||||
|
|
||||||
{KLALBVirtual}[::0]:25565->127.0.0.1:35001 //Winds服(加速线路)
|
|
||||||
|
|
||||||
//加速线路
|
|
||||||
{KLALBRemote}->43.248.189.107:35000
|
|
||||||
{KLALBRemote}->cn-bj-bgp-3.openfrp.top:65529
|
|
||||||
{KLALBRemote}->180.76.147.250:65529
|
|
||||||
{KLALBRemote}->cn-ah-dx-1.natfrp.cloud:65529
|
|
||||||
{KLALBRemote}->cn-nn-dx-1.natfrp.cloud:65529
|
|
||||||
{KLALBRemote}->cn-wh-dx-1.natfrp.cloud:65529
|
|
||||||
{KLALBRemote}->cn-zz-bgp-10.natfrp.cloud:23330
|
|
||||||
{KLALBRemote}->cn-zz-bgp-7.natfrp.cloud:33336
|
|
||||||
{KLALBRemote}->43.143.109.64:49965
|
|
||||||
{KLALBRemote}->frp.104300.xyz:49965
|
|
||||||
{KLALBRemote}->us.afrps.cn:49966
|
|
||||||
{KLALBRemote}->hk.afrps.cn:49966
|
|
||||||
{KLALBRemote}->la.afrps.cn:49966
|
|
||||||
{KLALBRemote}->frp.freefrp.net:49965
|
|
||||||
{KLALBRemote}->frp1.freefrp.net:49965
|
|
||||||
{KLALBRemote}->frp2.freefrp.net:49965
|
|
||||||
{KLALBRemote}->frp4.freefrp.net:49965
|
|
||||||
|
|
||||||
0.0.0.0:25565->{KLALBVirtual}[171d:a999:e697:4b23:ae52:9f29:4532:e1ee]:25565
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
43.248.189.107:65529
|
|
||||||
cn-bj-bgp-3.openfrp.top:65529
|
|
||||||
180.76.147.250:65529
|
|
||||||
cn-ah-dx-1.natfrp.cloud:65529
|
|
||||||
cn-nn-dx-1.natfrp.cloud:65529
|
|
||||||
cn-wh-dx-1.natfrp.cloud:65529
|
|
||||||
cn-zz-bgp-10.natfrp.cloud:23330
|
|
||||||
cn-zz-bgp-7.natfrp.cloud:33336
|
|
||||||
43.143.109.64:49965
|
|
||||||
frp.104300.xyz:49965
|
|
||||||
us.afrps.cn:49966
|
|
||||||
hk.afrps.cn:49966
|
|
||||||
la.afrps.cn:49966
|
|
||||||
frp.freefrp.net:49965
|
|
||||||
frp1.freefrp.net:49965
|
|
||||||
frp2.freefrp.net:49965
|
|
||||||
frp4.freefrp.net:49965
|
|
||||||
cn-he-plc-2.openfrp.top:4569
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
0.0.0.0:35000(RDP)->192.168.1.233:3389
|
|
||||||
0.0.0.0:35000(HTTPS)->192.168.1.233:8444
|
|
||||||
0.0.0.0:35000(HTTP)->192.168.1.233:5212
|
|
||||||
0.0.0.0:35000(SSH)->192.168.1.236:22
|
|
||||||
0.0.0.0:35000(KLALB)->{KLALBRemote}
|
|
||||||
0.0.0.0:35000->127.0.0.1:35001 //Winds服(普通线路)
|
|
||||||
|
|
||||||
{KLALBVirtual}[::0]:25565->127.0.0.1:35001 //Winds服(加速线路)
|
|
||||||
@@ -7,7 +7,6 @@ devicename=Device name
|
|||||||
devicedescription=Device description
|
devicedescription=Device description
|
||||||
dnsserver=DNS server
|
dnsserver=DNS server
|
||||||
extraroutes=Extra routes
|
extraroutes=Extra routes
|
||||||
noextraroutes=No extra routes
|
|
||||||
asnumber=AS number
|
asnumber=AS number
|
||||||
tcplistening=TCP listening
|
tcplistening=TCP listening
|
||||||
udplistening=UDP listening
|
udplistening=UDP listening
|
||||||
@@ -118,3 +117,8 @@ enablewebapi=Enable Web API
|
|||||||
weblistenaddr=Web API listen address
|
weblistenaddr=Web API listen address
|
||||||
invaildweblistenaddr=Invalid Web API listen address
|
invaildweblistenaddr=Invalid Web API listen address
|
||||||
enabletun=Enable TUN adapter
|
enabletun=Enable TUN adapter
|
||||||
|
congestionmonitor=Congestion control monitor
|
||||||
|
rttbaseline=RTT baseline
|
||||||
|
rtt=RTT
|
||||||
|
rttmax=RTT max
|
||||||
|
rttmin=RTT min
|
||||||
@@ -7,7 +7,6 @@ devicename=设备名称
|
|||||||
devicedescription=设备描述
|
devicedescription=设备描述
|
||||||
dnsserver=DNS服务器
|
dnsserver=DNS服务器
|
||||||
extraroutes=额外路由
|
extraroutes=额外路由
|
||||||
noextraroutes=暂无额外路由
|
|
||||||
asnumber=AS号码
|
asnumber=AS号码
|
||||||
tcplistening=TCP监听端口
|
tcplistening=TCP监听端口
|
||||||
udplistening=UDP监听端口
|
udplistening=UDP监听端口
|
||||||
@@ -118,3 +117,8 @@ enablewebapi=启用 Web API
|
|||||||
weblistenaddr=Web API 监听地址:端口
|
weblistenaddr=Web API 监听地址:端口
|
||||||
invaildweblistenaddr=无效的 Web API 监听地址:端口
|
invaildweblistenaddr=无效的 Web API 监听地址:端口
|
||||||
enabletun=启用TUN虚拟网卡
|
enabletun=启用TUN虚拟网卡
|
||||||
|
congestionmonitor=拥塞控制监视器
|
||||||
|
rttbaseline=往返延迟基线
|
||||||
|
rtt=往返延迟
|
||||||
|
rttmax=往返延迟上限
|
||||||
|
rttmin=往返延迟下限
|
||||||
@@ -136,4 +136,19 @@ public class BBRCongestionAlgorithm implements CongestionAlgorithm ,DetnetConges
|
|||||||
return "BBR";
|
return "BBR";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getUpperDelayBound() {
|
||||||
|
return MAX_GAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLowerDelayBound() {
|
||||||
|
return MIN_GAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBurstLimit() {
|
||||||
|
return burstLimit;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public class DCTCPCongestionAlgorithm implements CongestionAlgorithm {
|
|||||||
}
|
}
|
||||||
}else {
|
}else {
|
||||||
if(windowUsed*3L>=congressWindowSize) {
|
if(windowUsed*3L>=congressWindowSize) {
|
||||||
congressWindowSize+=4000;
|
congressWindowSize+=4096;
|
||||||
updateWindowSize();
|
updateWindowSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,4 +4,7 @@ public interface DetnetCongestionAlgorithm extends CongestionAlgorithm {
|
|||||||
public void setUpperDelayBound(double upper);
|
public void setUpperDelayBound(double upper);
|
||||||
public void setLowerDelayBound(double lower);
|
public void setLowerDelayBound(double lower);
|
||||||
public void setBurstLimit(double limit);
|
public void setBurstLimit(double limit);
|
||||||
|
public double getUpperDelayBound( );
|
||||||
|
public double getLowerDelayBound();
|
||||||
|
public double getBurstLimit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package org.kne.cloud.network.congestion;
|
|||||||
|
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.kne.cloud.network.monitor.DelaySampler;
|
||||||
|
|
||||||
public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCongestionAlgorithm {
|
public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCongestionAlgorithm {
|
||||||
|
|
||||||
// 可配置的时延膨胀比上下限 - Vegas2.0核心参数
|
// 可配置的时延膨胀比上下限 - Vegas2.0核心参数
|
||||||
@@ -17,6 +19,7 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
private Consumer<Long> windowControlConsumer;
|
private Consumer<Long> windowControlConsumer;
|
||||||
|
|
||||||
private long MIN_RTTVAR = 30000000L;
|
private long MIN_RTTVAR = 30000000L;
|
||||||
|
private volatile long RTTCurr = 1000000000L; // RTT
|
||||||
private volatile long RTTMin = 1000000000L; // BaseRTT
|
private volatile long RTTMin = 1000000000L; // BaseRTT
|
||||||
private volatile long RTTVar = 1000000000L;
|
private volatile long RTTVar = 1000000000L;
|
||||||
private volatile long RTTAvg = 1000000000L;
|
private volatile long RTTAvg = 1000000000L;
|
||||||
@@ -26,11 +29,6 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
private volatile long RTO = 1000000000L;
|
private volatile long RTO = 1000000000L;
|
||||||
|
|
||||||
|
|
||||||
private volatile long OWDTotal = 0;
|
|
||||||
private volatile long OWDCount = 0;
|
|
||||||
private volatile long OWDAvg2 = 1000000000L; // 当前平滑OWD
|
|
||||||
private volatile long OWDMin = 1000000000L; // BaseRTT
|
|
||||||
|
|
||||||
private volatile long window = MIN_WINDOW;
|
private volatile long window = MIN_WINDOW;
|
||||||
private volatile long window2 = MIN_WINDOW;
|
private volatile long window2 = MIN_WINDOW;
|
||||||
private volatile long maxwindow = 99999999999L;
|
private volatile long maxwindow = 99999999999L;
|
||||||
@@ -58,106 +56,14 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
private DelaySampler dsp=new DelaySampler();
|
||||||
public void putAck(long packetSize, long RTTns, long OWDup, boolean ecn) {
|
|
||||||
if(RTTns<0) {
|
|
||||||
throw new IllegalArgumentException("RTT:"+ RTTns+" is negative!");
|
|
||||||
}
|
|
||||||
// 处理ECN信号 - 将其视为强烈的拥塞信号
|
|
||||||
if (ecn) {
|
|
||||||
// 当收到ECN时,更激进地减少窗口
|
|
||||||
window2 = Math.max(0, window2 * 3 / 4);
|
|
||||||
if (windowControlConsumer != null) {
|
|
||||||
windowControlConsumer.accept(window2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新最小RTT(BaseRTT)
|
|
||||||
if (RTTns <= RTTMin) {
|
|
||||||
RTTMin = RTTns;
|
|
||||||
} else {
|
|
||||||
// 缓慢适应:当网络路径真正变化时,BaseRTT应能缓慢更新
|
|
||||||
// 这里使用极慢的衰减因子,只有在持续观测到更低RTT时才快速更新
|
|
||||||
RTTMin = (RTTMin * 999 + RTTns) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新最小OWD(BaseOWD)
|
|
||||||
if (OWDup <= OWDMin) {
|
|
||||||
OWDMin = OWDup;
|
|
||||||
} else {
|
|
||||||
// 缓慢适应:当网络路径真正变化时,BaseRTT应能缓慢更新
|
|
||||||
// 这里使用极慢的衰减因子,只有在持续观测到更低RTT时才快速更新
|
|
||||||
OWDMin = (OWDMin * 999 + OWDup) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新平滑RTT估计
|
|
||||||
|
|
||||||
RTTVar = (RTTVar * 3 + Math.abs(RTTAvg - RTTns)) / 4;
|
|
||||||
RTTAvg = (RTTAvg * 7 + RTTns) / 8;
|
|
||||||
|
|
||||||
|
|
||||||
RTO = RTTAvg + Math.max(MIN_RTTVAR, RTTVar * 4);
|
|
||||||
|
|
||||||
RTTTotal += RTTns;
|
|
||||||
RTTCount++;
|
|
||||||
|
|
||||||
OWDTotal += OWDup;
|
|
||||||
OWDCount++;
|
|
||||||
|
|
||||||
long curr = System.nanoTime();
|
|
||||||
// 每个RTT周期调整一次窗口(使用当前估计的RTT)
|
|
||||||
if (curr - RTTstartTime > Math.max(BIAS, 2*RTTMin)) {
|
|
||||||
long RTTCountx=RTTCount;
|
|
||||||
if (RTTCountx > 0) {
|
|
||||||
long currentRTT = RTTTotal / RTTCountx;
|
|
||||||
//RTTAvg2 = (RTTAvg2 * 3 + currentRTT) / 4; // 平滑当前RTT
|
|
||||||
RTTAvg2=currentRTT;
|
|
||||||
RTTTotal = 0;
|
|
||||||
RTTCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
long OWDCountx=OWDCount;
|
|
||||||
if (OWDCountx > 0) {
|
|
||||||
long currentOWD = OWDTotal / OWDCountx;
|
|
||||||
OWDAvg2=currentOWD;
|
|
||||||
OWDTotal = 0;
|
|
||||||
OWDCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ================== Vegas2.0核心逻辑 ==================
|
|
||||||
// 1. 计算时延膨胀比
|
|
||||||
double delayRatio = (double) OWDAvg2 / (double) Math.max(BIAS, OWDMin);
|
|
||||||
//System.out.println(delayRatio+" "+RTTAvg2/1000000.0+" "+RTTMin/1000000.0);
|
|
||||||
// 2. 基于比值的窗口调整(取代原来的基于差值的调整)
|
|
||||||
if (delayRatio > delayUpperBound) {
|
|
||||||
// 时延过高:减小窗口,减少幅度与超标程度成正比
|
|
||||||
window2 -= 4096;
|
|
||||||
} else if (delayRatio < delayLowerBound) {
|
|
||||||
// 时延过低:增大窗口,增加幅度与低于目标程度成正比
|
|
||||||
window2 += 4096;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
// ===================================================
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
updateWindowSize();
|
|
||||||
RTTstartTime = curr;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void putAck(long packetSize, long RTTns, boolean ecn) {
|
public void putAck(long packetSize, long RTTns, boolean ecn) {
|
||||||
if(RTTns<0) {
|
if(RTTns<0) {
|
||||||
throw new IllegalArgumentException("RTT:"+ RTTns+" is negative!");
|
throw new IllegalArgumentException("RTT:"+ RTTns+" is negative!");
|
||||||
}
|
}
|
||||||
|
this.RTTCurr=RTTns;
|
||||||
// 处理ECN信号 - 将其视为强烈的拥塞信号
|
// 处理ECN信号 - 将其视为强烈的拥塞信号
|
||||||
if (ecn) {
|
if (ecn) {
|
||||||
// 当收到ECN时,更激进地减少窗口
|
// 当收到ECN时,更激进地减少窗口
|
||||||
@@ -167,14 +73,7 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新最小RTT(BaseRTT)
|
dsp.recordDelay(RTTns);
|
||||||
if (RTTns <= RTTMin) {
|
|
||||||
RTTMin = RTTns;
|
|
||||||
} else {
|
|
||||||
// 缓慢适应:当网络路径真正变化时,BaseRTT应能缓慢更新
|
|
||||||
// 这里使用极慢的衰减因子,只有在持续观测到更低RTT时才快速更新
|
|
||||||
RTTMin = (RTTMin * 999 + RTTns) / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 更新平滑RTT估计
|
// 更新平滑RTT估计
|
||||||
|
|
||||||
@@ -190,6 +89,15 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
long curr = System.nanoTime();
|
long curr = System.nanoTime();
|
||||||
// 每个RTT周期调整一次窗口(使用当前估计的RTT)
|
// 每个RTT周期调整一次窗口(使用当前估计的RTT)
|
||||||
if (curr - RTTstartTime > Math.max(BIAS, 2*RTTMin)) {
|
if (curr - RTTstartTime > Math.max(BIAS, 2*RTTMin)) {
|
||||||
|
dsp.update();
|
||||||
|
long rmin=dsp.getMinDelayNanos();
|
||||||
|
if(rmin<=RTTMin) {
|
||||||
|
RTTMin=rmin;
|
||||||
|
}else {
|
||||||
|
RTTMin=Math.min(rmin, RTTMin+1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
long RTTCountx=RTTCount;
|
long RTTCountx=RTTCount;
|
||||||
if (RTTCountx > 0) {
|
if (RTTCountx > 0) {
|
||||||
long currentRTT = RTTTotal / RTTCountx;
|
long currentRTT = RTTTotal / RTTCountx;
|
||||||
@@ -206,12 +114,12 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
// 2. 基于比值的窗口调整(取代原来的基于差值的调整)
|
// 2. 基于比值的窗口调整(取代原来的基于差值的调整)
|
||||||
if (delayRatio > delayUpperBound) {
|
if (delayRatio > delayUpperBound) {
|
||||||
// 时延过高:减小窗口,减少幅度与超标程度成正比
|
// 时延过高:减小窗口,减少幅度与超标程度成正比
|
||||||
window2 -= 4096;
|
window2 =window2-4096;
|
||||||
} else if (delayRatio < delayLowerBound) {
|
} else if (delayRatio < delayLowerBound) {
|
||||||
// 时延过低:增大窗口,增加幅度与低于目标程度成正比
|
// 时延过低:增大窗口,增加幅度与低于目标程度成正比
|
||||||
window2 += 4096;
|
window2 =window2+4096;
|
||||||
} else {
|
} else {
|
||||||
|
//window2=window2+4096
|
||||||
}
|
}
|
||||||
// ===================================================
|
// ===================================================
|
||||||
|
|
||||||
@@ -271,10 +179,12 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
public long getBaseRTT() {
|
public long getBaseRTT() {
|
||||||
return RTTMin;
|
return RTTMin;
|
||||||
}
|
}
|
||||||
|
public long getAvgRTT() {
|
||||||
public long getCurrentRTT() {
|
|
||||||
return RTTAvg2;
|
return RTTAvg2;
|
||||||
}
|
}
|
||||||
|
public long getCurrentRTT() {
|
||||||
|
return RTTCurr;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUpperDelayBound(double upper) {
|
public void setUpperDelayBound(double upper) {
|
||||||
@@ -295,4 +205,19 @@ public class Vegas2CongestionAlgorithm implements CongestionAlgorithm,DetnetCong
|
|||||||
return "Vegas2";
|
return "Vegas2";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getUpperDelayBound() {
|
||||||
|
return delayUpperBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getLowerDelayBound() {
|
||||||
|
return delayLowerBound;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBurstLimit() {
|
||||||
|
return burstLimit;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
package org.kne.cloud.network.ipv6;
|
package org.kne.cloud.network.ipv6;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
@@ -10,8 +13,15 @@ public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
|
|||||||
private CopyOnWriteArraySet<IPv6LinkStateListener> listeners = new CopyOnWriteArraySet<>();
|
private CopyOnWriteArraySet<IPv6LinkStateListener> listeners = new CopyOnWriteArraySet<>();
|
||||||
|
|
||||||
private SRv6Router srv6Router;
|
private SRv6Router srv6Router;
|
||||||
|
private final boolean loopback;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractIPv6NetworkLink(boolean loopback) {
|
||||||
|
super();
|
||||||
|
this.loopback = loopback;
|
||||||
|
}
|
||||||
|
|
||||||
public SRv6Router getSrv6Router() {
|
public SRv6Router getSrv6Router() {
|
||||||
return srv6Router;
|
return srv6Router;
|
||||||
}
|
}
|
||||||
@@ -53,8 +63,49 @@ public abstract class AbstractIPv6NetworkLink implements IPv6NetworkLink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> receiveConsumer;
|
private BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> receiveConsumer;
|
||||||
|
|
||||||
|
private Supplier<Long> costSupplier;
|
||||||
@Override
|
@Override
|
||||||
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> receiveConsumer) {
|
public void setReceiveConsumer(BiConsumer<IPv6NetworkLink,Supplier< IPv6Packet>> receiveConsumer) {
|
||||||
this.receiveConsumer = receiveConsumer;
|
this.receiveConsumer = receiveConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLoopBack() {
|
||||||
|
return loopback;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Supplier<Long> getCostSupplier() {
|
||||||
|
return costSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCostSupplier(Supplier<Long> costSupplier) {
|
||||||
|
this.costSupplier = costSupplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RouteItem> getRouteItems() {
|
||||||
|
List<RouteItem> rlist = new ArrayList<>();
|
||||||
|
if(isLoopBack()) {
|
||||||
|
for(IPv6AddressGroup group:getAddressGroups()) {
|
||||||
|
rlist.add(new RouteItem(new IPv6AddressGroup(group.getAddress(), 128),
|
||||||
|
group.getAddress(), this, RouteItem.DIRECT, 0, 0, null, "D"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(isUp()) {
|
||||||
|
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext();) {
|
||||||
|
Neighbor addresses = (Neighbor) iteratorx.next();
|
||||||
|
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
||||||
|
addresses.getAddress().getAddress(), this,RouteItem.SRv6_ENDXSID, 0, 128, costSupplier, "D");
|
||||||
|
rlist.add(ri);
|
||||||
|
|
||||||
|
RouteItem ris = new RouteItem(addresses.getLocator(),
|
||||||
|
addresses.getLocator().getAddress(), this, RouteItem.SRv6_ENDSID, 13, 128,
|
||||||
|
costSupplier, "D");
|
||||||
|
rlist.add(ris);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rlist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ public final class IPv6Address implements Comparable<IPv6Address> {
|
|||||||
((long)(bytes[15] & 0xFF));
|
((long)(bytes[15] & 0xFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IPv6Address(String string) throws UnknownHostException {
|
||||||
|
this((Inet6Address) Inet6Address.getByName(string));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从两个long创建IPv6地址
|
* 从两个long创建IPv6地址
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -67,7 +67,16 @@ public class IPv6AddressGroup implements Comparable<IPv6AddressGroup>{
|
|||||||
prefixLength=in.read();
|
prefixLength=in.read();
|
||||||
}
|
}
|
||||||
public boolean checkMatch(IPv6Address address2) {
|
public boolean checkMatch(IPv6Address address2) {
|
||||||
return address2.equals(address.maskWith(IPv6Address.createMask(prefixLength)));
|
IPv6Address cmsk= IPv6Address.createMask(prefixLength);
|
||||||
|
return address2.maskWith(cmsk).equals(address.maskWith(cmsk));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 返回裁剪后的路由表地址(主机位清零)。
|
||||||
|
* 例如 2001:db8:1::100/64 → 2001:db8:1::/64
|
||||||
|
*/
|
||||||
|
public IPv6AddressGroup toNetworkRoute() {
|
||||||
|
IPv6Address mask = IPv6Address.createMask(prefixLength);
|
||||||
|
IPv6Address maskedAddr = address.maskWith(mask);
|
||||||
|
return new IPv6AddressGroup(maskedAddr, prefixLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1378,7 +1378,7 @@ public class IPv6Packet extends NetworkPacket {
|
|||||||
// 重路由计数器
|
// 重路由计数器
|
||||||
private AtomicInteger rerouteCounter = new AtomicInteger(0);
|
private AtomicInteger rerouteCounter = new AtomicInteger(0);
|
||||||
|
|
||||||
public AtomicInteger getRerouteCounter() {
|
public AtomicInteger getRouteCounter() {
|
||||||
return rerouteCounter;
|
return rerouteCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink
|
|||||||
private Lock slok = new SpinLock();
|
private Lock slok = new SpinLock();
|
||||||
|
|
||||||
public IPv6TUNLoopbackNetworkLink(String name,IPv6AddressGroup hostAddress, int mtu, List<InetAddress> dns) throws IOException {
|
public IPv6TUNLoopbackNetworkLink(String name,IPv6AddressGroup hostAddress, int mtu, List<InetAddress> dns) throws IOException {
|
||||||
|
super(true);
|
||||||
if (tun != null)
|
if (tun != null)
|
||||||
throw new IllegalStateException("already open!");
|
throw new IllegalStateException("already open!");
|
||||||
try {
|
try {
|
||||||
@@ -204,13 +205,6 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink
|
|||||||
LockSupport.unpark(tr);
|
LockSupport.unpark(tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoopBack() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Neighbor> getNeighborsInfo() {
|
public List<Neighbor> getNeighborsInfo() {
|
||||||
List<Neighbor> hs = new ArrayList<>();
|
List<Neighbor> hs = new ArrayList<>();
|
||||||
@@ -219,10 +213,6 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink
|
|||||||
return hs;
|
return hs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @Override public boolean isCongress(IPv6Packet iPv6Packet,double scale) {
|
|
||||||
* return sendQueue.size() > 1000*scale; }
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -255,27 +245,4 @@ public class IPv6TUNLoopbackNetworkLink extends AbstractIPv6NetworkLink
|
|||||||
return List.of(hostAddress);
|
return List.of(hostAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<RouteItem> getRouteItems() {
|
|
||||||
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();) {
|
|
||||||
Neighbor addresses = (Neighbor) iteratorx.next();
|
|
||||||
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
|
||||||
addresses.getAddress().getAddress(), this, "Direct", 0, 128, null, "D", false);
|
|
||||||
rlist.add(ri);
|
|
||||||
|
|
||||||
RouteItem ris = new RouteItem(addresses.getLocator(), addresses.getLocator().getAddress(), this,
|
|
||||||
"KLALB SRv6", 13, 128, null, "D", false);
|
|
||||||
rlist.add(ris);
|
|
||||||
|
|
||||||
}
|
|
||||||
return rlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
|||||||
|
|
||||||
//new Inet6AddressGroup(loopbackAddress, 128) new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("::1"), 128)
|
//new Inet6AddressGroup(loopbackAddress, 128) new Inet6AddressGroup((Inet6Address) Inet6Address.getByName("::1"), 128)
|
||||||
public LoopbackIPv6NetworkLink(List<IPv6AddressGroup> addressGroupsx,SRv6Router router) {
|
public LoopbackIPv6NetworkLink(List<IPv6AddressGroup> addressGroupsx,SRv6Router router) {
|
||||||
|
super(true);
|
||||||
this.addressGroups .addAll( addressGroupsx);
|
this.addressGroups .addAll( addressGroupsx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +55,7 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoopBack() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Neighbor> getNeighborsInfo() {
|
public List<Neighbor> getNeighborsInfo() {
|
||||||
@@ -93,29 +91,6 @@ public class LoopbackIPv6NetworkLink extends AbstractIPv6NetworkLink implements
|
|||||||
return rerouteConsumer;
|
return rerouteConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<RouteItem> getRouteItems() {
|
|
||||||
List<RouteItem> rlist = new ArrayList<>();
|
|
||||||
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 IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
|
||||||
addresses.getAddress().getAddress(), this, "Direct", 0, 128, null, "D",
|
|
||||||
false);
|
|
||||||
rlist.add(ri);
|
|
||||||
|
|
||||||
RouteItem ris = new RouteItem(addresses.getLocator(),
|
|
||||||
addresses.getLocator().getAddress(), this, "KLALB SRv6", 13, 128,
|
|
||||||
null, "D", false);
|
|
||||||
rlist.add(ris);
|
|
||||||
|
|
||||||
}
|
|
||||||
return rlist;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public SRv6Router getRouter() {
|
public SRv6Router getRouter() {
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import java.util.Objects;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
||||||
|
public static final String DIRECT="Direct";
|
||||||
|
public static final String SRv6_ENDSID="SRv6 ENDSID";
|
||||||
|
public static final String SRv6_ENDXSID="SRv6 ENDXSID";
|
||||||
|
public static final String KLALB_SRv6 = "KLALB_SRv6";
|
||||||
|
|
||||||
private IPv6AddressGroup destination;
|
private IPv6AddressGroup destination;
|
||||||
private IPv6Address nexthop;
|
private IPv6Address nexthop;
|
||||||
private IPv6NetworkLink destlink;
|
private IPv6NetworkLink destlink;
|
||||||
@@ -12,7 +17,6 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
|||||||
private long cost;
|
private long cost;
|
||||||
private String flag;
|
private String flag;
|
||||||
private Supplier<Long> costSupplier;
|
private Supplier<Long> costSupplier;
|
||||||
private boolean isLoopback;
|
|
||||||
public String getFlag() {
|
public String getFlag() {
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
@@ -34,21 +38,20 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
|||||||
&& pre == other.pre && Objects.equals(proto, other.proto);
|
&& pre == other.pre && Objects.equals(proto, other.proto);
|
||||||
}
|
}
|
||||||
public RouteItem(IPv6AddressGroup destination, IPv6Address 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) {
|
long cost,String flag) {
|
||||||
super();
|
super();
|
||||||
this.destination = destination;
|
this.destination = destination.toNetworkRoute();
|
||||||
this.nexthop = nexthop;
|
this.nexthop = nexthop;
|
||||||
this.destlink = destlink;
|
this.destlink = destlink;
|
||||||
this.proto = proto;
|
this.proto = proto;
|
||||||
this.pre = pre;
|
this.pre = pre;
|
||||||
this.cost = cost;
|
this.cost = cost;
|
||||||
this.flag=flag;
|
this.flag=flag;
|
||||||
this.isLoopback=isLoopback;
|
|
||||||
}
|
}
|
||||||
public RouteItem(IPv6AddressGroup destination, IPv6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
|
public RouteItem(IPv6AddressGroup destination, IPv6Address nexthop, IPv6NetworkLink destlink, String proto, int pre,
|
||||||
long cost,Supplier<Long> costSupplier,String flag,boolean isLoopback) {
|
long cost,Supplier<Long> costSupplier,String flag) {
|
||||||
super();
|
super();
|
||||||
this.destination = destination;
|
this.destination = destination.toNetworkRoute();
|
||||||
this.nexthop = nexthop;
|
this.nexthop = nexthop;
|
||||||
this.destlink = destlink;
|
this.destlink = destlink;
|
||||||
this.proto = proto;
|
this.proto = proto;
|
||||||
@@ -56,7 +59,6 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
|||||||
this.cost = cost;
|
this.cost = cost;
|
||||||
this.costSupplier=costSupplier;
|
this.costSupplier=costSupplier;
|
||||||
this.flag=flag;
|
this.flag=flag;
|
||||||
this.isLoopback=isLoopback;
|
|
||||||
}
|
}
|
||||||
public IPv6AddressGroup getDestination() {
|
public IPv6AddressGroup getDestination() {
|
||||||
return destination;
|
return destination;
|
||||||
@@ -73,9 +75,6 @@ public class RouteItem implements Comparable<RouteItem>,Cloneable{
|
|||||||
public int getPre() {
|
public int getPre() {
|
||||||
return pre;
|
return pre;
|
||||||
}
|
}
|
||||||
public boolean isLoopback() {
|
|
||||||
return isLoopback;
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop()+"\t"+getDestlink().getName();
|
return getDestination()+"\t"+getProto()+"\t"+getPre()+"\t"+getCost()+"\t"+getFlag()+"\t"+getNexthop()+"\t"+getDestlink().getName();
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import org.kne.cloud.network.ipv6.RouteItem;
|
|||||||
|
|
||||||
public abstract class AbstractControlledIPv6NetworkLink extends AbstractIPv6NetworkLink implements ControlledIPv6NetworkLink{
|
public abstract class AbstractControlledIPv6NetworkLink extends AbstractIPv6NetworkLink implements ControlledIPv6NetworkLink{
|
||||||
|
|
||||||
|
public AbstractControlledIPv6NetworkLink(boolean loopback) {
|
||||||
|
super(loopback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class CONST {
|
|||||||
|
|
||||||
public static final String KLALB_S_RV6 = "KLALB_SRv6";
|
public static final String KLALB_S_RV6 = "KLALB_SRv6";
|
||||||
|
|
||||||
|
public static final String KLTP_VIRTUAL_SOCKET_NAME="kltp";
|
||||||
|
|
||||||
public static final int itemwidth = 1000;
|
public static final int itemwidth = 1000;
|
||||||
public static final int linepanelheight = 41;
|
public static final int linepanelheight = 41;
|
||||||
|
|||||||
@@ -11,13 +11,11 @@ import java.net.SocketException;
|
|||||||
import java.net.SocketTimeoutException;
|
import java.net.SocketTimeoutException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
@@ -56,7 +54,6 @@ import org.kne.cloud.network.ntp.NTPv4Protocol.NTPPeer;
|
|||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIServer;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIServer;
|
||||||
import org.kne.cloud.network.srv6.NodeInfoQueryStatus;
|
|
||||||
import org.kne.cloud.network.srv6.SRv6Router;
|
import org.kne.cloud.network.srv6.SRv6Router;
|
||||||
import org.kne.cloud.network.srv6.SRv6RouterListener;
|
import org.kne.cloud.network.srv6.SRv6RouterListener;
|
||||||
import org.kne.cloud.network.tcp.UDPPacket;
|
import org.kne.cloud.network.tcp.UDPPacket;
|
||||||
@@ -80,49 +77,6 @@ public class KLALBController {
|
|||||||
new HashMapTimestampMonitor<UUID>(HighAccuracyClock.SYSTEM_CLOCK, "down", 100, TIME_WINDOW));
|
new HashMapTimestampMonitor<UUID>(HighAccuracyClock.SYSTEM_CLOCK, "down", 100, TIME_WINDOW));
|
||||||
|
|
||||||
private List<MultiProtocolSocketAddress> externalEndpoints = new ArrayList<>();
|
private List<MultiProtocolSocketAddress> externalEndpoints = new ArrayList<>();
|
||||||
private List<MultiProtocolSocketAddress> configuredExternalEndpoints = new ArrayList<>();
|
|
||||||
private List<MultiProtocolSocketAddress> discoveredExternalEndpoints = new ArrayList<>();
|
|
||||||
|
|
||||||
public static final class PublishedNodeInfo {
|
|
||||||
private final String deviceName;
|
|
||||||
private final String deviceDescription;
|
|
||||||
private final List<MultiProtocolSocketAddress> externalEndpoints;
|
|
||||||
private final List<String> extraRoutes;
|
|
||||||
private final long fullRevision;
|
|
||||||
|
|
||||||
private PublishedNodeInfo(String deviceName, String deviceDescription,
|
|
||||||
List<MultiProtocolSocketAddress> externalEndpoints, List<String> extraRoutes, long fullRevision) {
|
|
||||||
this.deviceName = deviceName;
|
|
||||||
this.deviceDescription = deviceDescription;
|
|
||||||
this.externalEndpoints = Collections.unmodifiableList(
|
|
||||||
new ArrayList<MultiProtocolSocketAddress>(externalEndpoints));
|
|
||||||
this.extraRoutes = Collections.unmodifiableList(new ArrayList<String>(extraRoutes));
|
|
||||||
this.fullRevision = fullRevision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceName() {
|
|
||||||
return deviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceDescription() {
|
|
||||||
return deviceDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MultiProtocolSocketAddress> getExternalEndpoints() {
|
|
||||||
return externalEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getExtraRoutes() {
|
|
||||||
return extraRoutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getFullRevision() {
|
|
||||||
return fullRevision;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private volatile PublishedNodeInfo publishedNodeInfo = new PublishedNodeInfo(null, null,
|
|
||||||
Collections.<MultiProtocolSocketAddress>emptyList(), Collections.<String>emptyList(), 0L);
|
|
||||||
|
|
||||||
private List<MultiProtocolSocketAddress> listensSocketAddress = new CopyOnWriteArrayList<>();
|
private List<MultiProtocolSocketAddress> listensSocketAddress = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
@@ -132,7 +86,7 @@ public class KLALBController {
|
|||||||
private static final boolean debug=false;
|
private static final boolean debug=false;
|
||||||
private static final boolean showpacket = false;
|
private static final boolean showpacket = false;
|
||||||
|
|
||||||
private static final int PREFIX = 128;// 112
|
private static final int PREFIX = 128;
|
||||||
private static final int DISCOVERY_PORT = 4569;
|
private static final int DISCOVERY_PORT = 4569;
|
||||||
|
|
||||||
private static List<IPMulticastDiscovery> ipmd = new ArrayList<>();
|
private static List<IPMulticastDiscovery> ipmd = new ArrayList<>();
|
||||||
@@ -172,7 +126,6 @@ public class KLALBController {
|
|||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
List<InetAddress> localaddress = networkInterfaceManager.getAllNetworkInterfaceAddress();
|
List<InetAddress> localaddress = networkInterfaceManager.getAllNetworkInterfaceAddress();
|
||||||
List<MultiProtocolSocketAddress> currentDiscoveredExternalEndpoints = new ArrayList<>();
|
|
||||||
|
|
||||||
for (InetAddress inetAddress : localaddress) {
|
for (InetAddress inetAddress : localaddress) {
|
||||||
for (Iterator<MultiProtocolSocketAddress> iterator = listensSocketAddress.iterator(); iterator.hasNext();) {
|
for (Iterator<MultiProtocolSocketAddress> iterator = listensSocketAddress.iterator(); iterator.hasNext();) {
|
||||||
@@ -184,8 +137,10 @@ public class KLALBController {
|
|||||||
MultiProtocolSocketAddress bind = new MultiProtocolSocketAddress(tcpl.getProtocol(),
|
MultiProtocolSocketAddress bind = new MultiProtocolSocketAddress(tcpl.getProtocol(),
|
||||||
inetAddress.getHostAddress(), tcpl.getPort());
|
inetAddress.getHostAddress(), tcpl.getPort());
|
||||||
// System.out.println(bind);
|
// System.out.println(bind);
|
||||||
if (!currentDiscoveredExternalEndpoints.contains(bind)) {
|
synchronized (externalEndpoints) {
|
||||||
currentDiscoveredExternalEndpoints.add(bind);
|
if (!externalEndpoints.contains(bind)) {
|
||||||
|
externalEndpoints.add(bind);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
@@ -195,12 +150,6 @@ public class KLALBController {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
synchronized (externalEndpoints) {
|
|
||||||
if (!discoveredExternalEndpoints.equals(currentDiscoveredExternalEndpoints)) {
|
|
||||||
discoveredExternalEndpoints = currentDiscoveredExternalEndpoints;
|
|
||||||
publishDiscoveredExternalEndpointLocked();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lineslock.writeLock().lock();
|
lineslock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
@@ -350,7 +299,7 @@ public class KLALBController {
|
|||||||
private boolean checkIsSelf(MultiProtocolSocketAddress inetAddress) throws UnknownHostException {
|
private boolean checkIsSelf(MultiProtocolSocketAddress inetAddress) throws UnknownHostException {
|
||||||
|
|
||||||
return inetAddress.getInetAddress().isAnyLocalAddress() || inetAddress.getInetAddress().isLoopbackAddress()
|
return inetAddress.getInetAddress().isAnyLocalAddress() || inetAddress.getInetAddress().isLoopbackAddress()
|
||||||
|| publishedNodeInfo.getExternalEndpoints().contains(inetAddress);
|
|| externalEndpoints.contains(inetAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkIsSelfLocator(InetAddress inetAddress) {
|
private boolean checkIsSelfLocator(InetAddress inetAddress) {
|
||||||
@@ -390,11 +339,9 @@ public class KLALBController {
|
|||||||
try {
|
try {
|
||||||
InetSocketAddress iaddr = new InetSocketAddress(neighbor.getAddress().toInet6Address(),
|
InetSocketAddress iaddr = new InetSocketAddress(neighbor.getAddress().toInet6Address(),
|
||||||
KLALBRoutingProtocol.DEFAULT_PORT);
|
KLALBRoutingProtocol.DEFAULT_PORT);
|
||||||
apiClient.requestExternalEndpoints(iaddr, (v) -> {
|
apiClient.requestNodeInfoFull(iaddr, (v) -> {
|
||||||
if (v == null || v.getStatus() != NodeInfoQueryStatus.OK) return;
|
|
||||||
ThreadTool.makeVDaemonThreadIfSupport("线路添加任务", () -> {
|
ThreadTool.makeVDaemonThreadIfSupport("线路添加任务", () -> {
|
||||||
if (v.getExternalEndpoints() == null) return;
|
for (MultiProtocolSocketAddress msa : v.getOpenLines()) {
|
||||||
for (MultiProtocolSocketAddress msa : v.getExternalEndpoints()) {
|
|
||||||
// System.out.print(msa);
|
// System.out.print(msa);
|
||||||
addRemoteLines(msa);
|
addRemoteLines(msa);
|
||||||
}
|
}
|
||||||
@@ -455,102 +402,7 @@ public class KLALBController {
|
|||||||
|
|
||||||
|
|
||||||
public List<MultiProtocolSocketAddress> getExternalEndpoints() {
|
public List<MultiProtocolSocketAddress> getExternalEndpoints() {
|
||||||
return publishedNodeInfo.getExternalEndpoints();
|
return externalEndpoints;
|
||||||
}
|
|
||||||
|
|
||||||
public List<MultiProtocolSocketAddress> getExternalEndpointsSnapshot() {
|
|
||||||
return new ArrayList<MultiProtocolSocketAddress>(publishedNodeInfo.getExternalEndpoints());
|
|
||||||
}
|
|
||||||
|
|
||||||
public PublishedNodeInfo getPublishedNodeInfo() {
|
|
||||||
return publishedNodeInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MultiProtocolSocketAddress> createEffectiveExternalEndpointsLocked() {
|
|
||||||
List<MultiProtocolSocketAddress> effective = new ArrayList<MultiProtocolSocketAddress>();
|
|
||||||
for (MultiProtocolSocketAddress endpoint : configuredExternalEndpoints) {
|
|
||||||
if (!effective.contains(endpoint)) {
|
|
||||||
effective.add(endpoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (MultiProtocolSocketAddress endpoint : discoveredExternalEndpoints) {
|
|
||||||
if (!effective.contains(endpoint)) {
|
|
||||||
effective.add(endpoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return effective;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void publishNodeInfoLocked(String deviceName, String deviceDescription,
|
|
||||||
List<MultiProtocolSocketAddress> configEndpoints, List<String> extraRoutes) {
|
|
||||||
configuredExternalEndpoints = configEndpoints == null
|
|
||||||
? new ArrayList<MultiProtocolSocketAddress>()
|
|
||||||
: new ArrayList<MultiProtocolSocketAddress>(configEndpoints);
|
|
||||||
List<String> publishedExtraRoutes = extraRoutes == null
|
|
||||||
? new ArrayList<String>() : new ArrayList<String>(extraRoutes);
|
|
||||||
List<MultiProtocolSocketAddress> effective = createEffectiveExternalEndpointsLocked();
|
|
||||||
PublishedNodeInfo previous = publishedNodeInfo;
|
|
||||||
boolean nameChanged = !Objects.equals(previous.getDeviceName(), deviceName);
|
|
||||||
boolean fullChanged = !Objects.equals(previous.getDeviceDescription(), deviceDescription)
|
|
||||||
|| !previous.getExternalEndpoints().equals(effective)
|
|
||||||
|| !previous.getExtraRoutes().equals(publishedExtraRoutes);
|
|
||||||
|
|
||||||
externalEndpoints.clear();
|
|
||||||
externalEndpoints.addAll(effective);
|
|
||||||
if (srv6Router != null) {
|
|
||||||
srv6Router.setDeviceName(deviceName);
|
|
||||||
}
|
|
||||||
long fullRevision = previous.getFullRevision() + (fullChanged ? 1L : 0L);
|
|
||||||
publishedNodeInfo = new PublishedNodeInfo(deviceName, deviceDescription, effective, publishedExtraRoutes,
|
|
||||||
fullRevision);
|
|
||||||
if (routingProtocol != null) {
|
|
||||||
if (nameChanged) {
|
|
||||||
routingProtocol.announceNodeInfoUpdate(
|
|
||||||
org.kne.cloud.network.srv6.RouterInfoPacket.NODE_INFO_TINY_UPDATE_REQUIRED);
|
|
||||||
}
|
|
||||||
if (fullChanged) {
|
|
||||||
routingProtocol.announceNodeInfoUpdate(
|
|
||||||
org.kne.cloud.network.srv6.RouterInfoPacket.NODE_INFO_FULL_UPDATE_REQUIRED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void publishNodeInfo(String deviceName, String deviceDescription,
|
|
||||||
List<MultiProtocolSocketAddress> configEndpoints, List<String> extraRoutes) {
|
|
||||||
synchronized (externalEndpoints) {
|
|
||||||
if (configItem != null) {
|
|
||||||
configItem.setDeviceName(deviceName);
|
|
||||||
configItem.setDeviceDescription(deviceDescription);
|
|
||||||
configItem.setExternalEndpoints(new ArrayList<MultiProtocolSocketAddress>(configEndpoints == null
|
|
||||||
? Collections.<MultiProtocolSocketAddress>emptyList() : configEndpoints));
|
|
||||||
configItem.setExtraRoutes(new ArrayList<String>(extraRoutes == null
|
|
||||||
? Collections.<String>emptyList() : extraRoutes));
|
|
||||||
}
|
|
||||||
publishNodeInfoLocked(deviceName, deviceDescription, configEndpoints, extraRoutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void publishDiscoveredExternalEndpointLocked() {
|
|
||||||
List<MultiProtocolSocketAddress> effective = createEffectiveExternalEndpointsLocked();
|
|
||||||
if (new HashSet<MultiProtocolSocketAddress>(effective)
|
|
||||||
.equals(new HashSet<MultiProtocolSocketAddress>(externalEndpoints))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
externalEndpoints.clear();
|
|
||||||
externalEndpoints.addAll(effective);
|
|
||||||
PublishedNodeInfo previous = publishedNodeInfo;
|
|
||||||
publishedNodeInfo = new PublishedNodeInfo(previous.getDeviceName(), previous.getDeviceDescription(), effective,
|
|
||||||
previous.getExtraRoutes(), previous.getFullRevision() + 1L);
|
|
||||||
if (routingProtocol != null) {
|
|
||||||
routingProtocol.announceNodeInfoUpdate(
|
|
||||||
org.kne.cloud.network.srv6.RouterInfoPacket.NODE_INFO_FULL_UPDATE_REQUIRED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replaceExternalEndpoints(List<MultiProtocolSocketAddress> endpoints) {
|
|
||||||
PublishedNodeInfo published = publishedNodeInfo;
|
|
||||||
publishNodeInfo(published.getDeviceName(), published.getDeviceDescription(), endpoints,
|
|
||||||
published.getExtraRoutes());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -752,7 +604,8 @@ public class KLALBController {
|
|||||||
|
|
||||||
private String generateExternalEndpointsString() {
|
private String generateExternalEndpointsString() {
|
||||||
StringBuilder sbd = new StringBuilder();
|
StringBuilder sbd = new StringBuilder();
|
||||||
for (MultiProtocolSocketAddress klalbRemoteLine : publishedNodeInfo.getExternalEndpoints()) {
|
for (Iterator<MultiProtocolSocketAddress> iterator = externalEndpoints.iterator(); iterator.hasNext();) {
|
||||||
|
MultiProtocolSocketAddress klalbRemoteLine = (MultiProtocolSocketAddress) iterator.next();
|
||||||
sbd.append(klalbRemoteLine.toString());
|
sbd.append(klalbRemoteLine.toString());
|
||||||
sbd.append('\n');
|
sbd.append('\n');
|
||||||
}
|
}
|
||||||
@@ -781,7 +634,8 @@ public class KLALBController {
|
|||||||
|
|
||||||
private void loadSRv6ProtocolStack(IPv6AddressGroup selfx, boolean enableVirtualAdapter) {
|
private void loadSRv6ProtocolStack(IPv6AddressGroup selfx, boolean enableVirtualAdapter) {
|
||||||
networkInterfaceManager.getInetAddressesExcept().add(selfx.getAddress().toInet6Address());
|
networkInterfaceManager.getInetAddressesExcept().add(selfx.getAddress().toInet6Address());
|
||||||
srv6Router = new SRv6Router(selfx, clock);
|
IPv6AddressGroup group=new IPv6AddressGroup(selfx.getAddress(),32);
|
||||||
|
srv6Router = new SRv6Router(selfx,group, clock);
|
||||||
if(configItem!=null) {
|
if(configItem!=null) {
|
||||||
srv6Router.setPerformanceStrategy(PerformanceStrategy.fromDescription(configItem.getPerformanceStrategy()));
|
srv6Router.setPerformanceStrategy(PerformanceStrategy.fromDescription(configItem.getPerformanceStrategy()));
|
||||||
srv6Router.setDeviceName(configItem.getDeviceName());
|
srv6Router.setDeviceName(configItem.getDeviceName());
|
||||||
@@ -800,8 +654,7 @@ public class KLALBController {
|
|||||||
if (enableTUN) {
|
if (enableTUN) {
|
||||||
Thread t=new Thread(()->{
|
Thread t=new Thread(()->{
|
||||||
try {
|
try {
|
||||||
IPv6TUNLoopbackNetworkLink tunlink = new IPv6TUNLoopbackNetworkLink(name.trim(),
|
IPv6TUNLoopbackNetworkLink tunlink = new IPv6TUNLoopbackNetworkLink(name.trim(),group, SRv6Router.MTU, dnsAddresses);
|
||||||
new IPv6AddressGroup(srv6Router.getLocator().getAddress(), 32), SRv6Router.MTU, dnsAddresses);
|
|
||||||
tunlink.setMonitor(datatMonitor);
|
tunlink.setMonitor(datatMonitor);
|
||||||
// srv6Router.getLinkTabel().add(tunlink);
|
// srv6Router.getLinkTabel().add(tunlink);
|
||||||
srv6Router.getinLoopback().setFallbackLink(tunlink);
|
srv6Router.getinLoopback().setFallbackLink(tunlink);
|
||||||
@@ -834,7 +687,7 @@ public class KLALBController {
|
|||||||
// System.out.println(context);
|
// System.out.println(context);
|
||||||
try {
|
try {
|
||||||
NTPv4Protocol nvc = new NTPv4Protocol(context,
|
NTPv4Protocol nvc = new NTPv4Protocol(context,
|
||||||
new MultiProtocolSocketAddress(iproxyname + "_Datagram","0.0.0.0",123));
|
new MultiProtocolSocketAddress(iproxyname + "datagram","0.0.0.0",123));
|
||||||
srv6Router.addSRv6RouterListener(new SRv6RouterListener() {
|
srv6Router.addSRv6RouterListener(new SRv6RouterListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -845,7 +698,7 @@ public class KLALBController {
|
|||||||
for (Neighbor neighbor : nb) {
|
for (Neighbor neighbor : nb) {
|
||||||
if (neighbor.getLocator() != null)
|
if (neighbor.getLocator() != null)
|
||||||
sp.add(new NTPPeer(
|
sp.add(new NTPPeer(
|
||||||
new MultiProtocolSocketAddress(iproxyname + "_Datagram",
|
new MultiProtocolSocketAddress(iproxyname + "datagram",
|
||||||
neighbor.getLocator().getAddress().toString(), 123),
|
neighbor.getLocator().getAddress().toString(), 123),
|
||||||
NTPv4Packet.NTP_SYMMETRIC_ACTIVE));
|
NTPv4Packet.NTP_SYMMETRIC_ACTIVE));
|
||||||
|
|
||||||
@@ -912,9 +765,6 @@ public class KLALBController {
|
|||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
loadSRv6ProtocolStack(selfg, enableVirtualAdapter);
|
loadSRv6ProtocolStack(selfg, enableVirtualAdapter);
|
||||||
if (configItem == null) {
|
|
||||||
publishNodeInfo(srv6Router.getDeviceName(), null, null, null);
|
|
||||||
}
|
|
||||||
loadController();
|
loadController();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -952,8 +802,9 @@ public class KLALBController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<MultiProtocolSocketAddress> linele = configItem.getExternalEndpoints();
|
List<MultiProtocolSocketAddress> linele = configItem.getExternalEndpoints();
|
||||||
publishNodeInfo(configItem.getDeviceName(), configItem.getDeviceDescription(), linele,
|
if (linele != null) {
|
||||||
configItem.getExtraRoutes());
|
getExternalEndpoints().addAll(linele);
|
||||||
|
}
|
||||||
List<MultiProtocolSocketAddress> linetoc = configItem.getAutoConnections();
|
List<MultiProtocolSocketAddress> linetoc = configItem.getAutoConnections();
|
||||||
if (linetoc != null) {
|
if (linetoc != null) {
|
||||||
linetoc.forEach((aline) -> {
|
linetoc.forEach((aline) -> {
|
||||||
@@ -1127,8 +978,8 @@ public class KLALBController {
|
|||||||
|
|
||||||
|
|
||||||
public void registerToProxyTypeAs(String proxyname) {
|
public void registerToProxyTypeAs(String proxyname) {
|
||||||
MultiProtocolSocketAddress.getSocketTypeRegister().put(proxyname + "_Stream", streamSocketType);
|
MultiProtocolSocketAddress.getSocketTypeRegister().put(proxyname + "stream", streamSocketType);
|
||||||
MultiProtocolSocketAddress.getSocketTypeRegister().put(proxyname + "_Datagram", datagramSocketType);
|
MultiProtocolSocketAddress.getSocketTypeRegister().put(proxyname + "datagram", datagramSocketType);
|
||||||
// ProxyProfileEntry.getRegister().put(proxyname, this);
|
// ProxyProfileEntry.getRegister().put(proxyname, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ import org.kne.cloud.network.klalb.ui.UIEnv;
|
|||||||
import org.kne.cloud.network.perf.Kperf;
|
import org.kne.cloud.network.perf.Kperf;
|
||||||
import org.kne.cloud.network.perf.NodeBenchmark;
|
import org.kne.cloud.network.perf.NodeBenchmark;
|
||||||
import org.kne.debug.TimeDebugger;
|
import org.kne.debug.TimeDebugger;
|
||||||
import org.kne.membandboost.MembandBenchmark;
|
import org.kne.membandboost.benchmark.*;;
|
||||||
import org.kne.membandboost.ObjectPoolBandwidthTest;
|
|
||||||
|
|
||||||
public class KLALBMain {
|
public class KLALBMain {
|
||||||
public static KLALBStateGUI3 ksg;
|
public static KLALBStateGUI3 ksg;
|
||||||
@@ -239,10 +238,6 @@ public class KLALBMain {
|
|||||||
case "membandbenchmark":
|
case "membandbenchmark":
|
||||||
MembandBenchmark.main(args);
|
MembandBenchmark.main(args);
|
||||||
break;
|
break;
|
||||||
case "memqueuebenchmark":
|
|
||||||
|
|
||||||
ObjectPoolBandwidthTest.main(args);
|
|
||||||
break;
|
|
||||||
//case "$$SYSTEM:":
|
//case "$$SYSTEM:":
|
||||||
//System.out.println();
|
//System.out.println();
|
||||||
//break;
|
//break;
|
||||||
|
|||||||
@@ -168,9 +168,11 @@ public class KLALBProxySystem {
|
|||||||
|
|
||||||
|
|
||||||
String vsne=kcci.getVirtualSocketName();
|
String vsne=kcci.getVirtualSocketName();
|
||||||
//if(vsne!=null) {
|
if(vsne!=null) {
|
||||||
MultiProtocolSocketAddress.getSocketTypeRegister().put(vsne, klalbController.getStreamSocketType());
|
MultiProtocolSocketAddress.getSocketTypeRegister().put(vsne, klalbController.getStreamSocketType());
|
||||||
//}
|
}else{
|
||||||
|
MultiProtocolSocketAddress.getSocketTypeRegister().put(CONST.KLTP_VIRTUAL_SOCKET_NAME, klalbController.getStreamSocketType());
|
||||||
|
}
|
||||||
MultiProtocolSocketAddress tcple=kcci.getTCPListen();
|
MultiProtocolSocketAddress tcple=kcci.getTCPListen();
|
||||||
if(tcple!=null) {
|
if(tcple!=null) {
|
||||||
|
|
||||||
|
|||||||
@@ -142,15 +142,18 @@ public class KLALBRemoteLink extends AbstractControlledIPv6NetworkLink implement
|
|||||||
}
|
}
|
||||||
|
|
||||||
public KLALBRemoteLink(KLALBController controller,KLALBPacketLink kpl, IPv6AddressGroup address) {
|
public KLALBRemoteLink(KLALBController controller,KLALBPacketLink kpl, IPv6AddressGroup address) {
|
||||||
|
super(false);
|
||||||
this.klalbController=controller;
|
this.klalbController=controller;
|
||||||
sysclk = klalbController.getClock();
|
sysclk = klalbController.getClock();
|
||||||
this.kplink = kpl;
|
this.kplink = kpl;
|
||||||
this.addressGroup = address;
|
this.addressGroup = address;
|
||||||
monitor=new SpeedAndTrafficAndDelayMonitorDataImpl(sysclk);
|
monitor=new SpeedAndTrafficAndDelayMonitorDataImpl(sysclk);
|
||||||
name=kpl.toString();
|
name=kpl.toString();
|
||||||
|
setCostSupplier( CostSupplierFactory.owdSupplier(monitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
private KLALBRemoteLink(KLALBController controller, MultiProtocolSocketAddress mpa, MultiProtocolSocketAddress bindaddr, IPv6AddressGroup address) {
|
private KLALBRemoteLink(KLALBController controller, MultiProtocolSocketAddress mpa, MultiProtocolSocketAddress bindaddr, IPv6AddressGroup address) {
|
||||||
|
super(false);
|
||||||
this.klalbController=controller;
|
this.klalbController=controller;
|
||||||
sysclk = klalbController.getClock();
|
sysclk = klalbController.getClock();
|
||||||
this.socketAddress = mpa;
|
this.socketAddress = mpa;
|
||||||
@@ -162,6 +165,7 @@ public class KLALBRemoteLink extends AbstractControlledIPv6NetworkLink implement
|
|||||||
} else {
|
} else {
|
||||||
name=bindaddr.toString() + "→" + mpa.toString();
|
name=bindaddr.toString() + "→" + mpa.toString();
|
||||||
}
|
}
|
||||||
|
setCostSupplier( CostSupplierFactory.owdSupplier( monitor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -854,10 +858,6 @@ public class KLALBRemoteLink extends AbstractControlledIPv6NetworkLink implement
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoopBack() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
BandwidthDistributer bandwidthDistributer=new BandwidthDistributer<>();
|
BandwidthDistributer bandwidthDistributer=new BandwidthDistributer<>();
|
||||||
@Override
|
@Override
|
||||||
public List<Neighbor> getNeighborsInfo() {
|
public List<Neighbor> getNeighborsInfo() {
|
||||||
@@ -946,31 +946,28 @@ public class KLALBRemoteLink extends AbstractControlledIPv6NetworkLink implement
|
|||||||
return (!isClosed()) && (status.getState() == LinkStatus.UP) ;
|
return (!isClosed()) && (status.getState() == LinkStatus.UP) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/*@Override
|
||||||
public List<RouteItem> getRouteItems() {
|
public List<RouteItem> getRouteItems() {
|
||||||
List<RouteItem> rlist = new ArrayList<>();
|
List<RouteItem> rlist = new ArrayList<>();
|
||||||
|
|
||||||
if(isUp()) {
|
if(isUp()) {
|
||||||
IPv6AddressGroup adg = addressGroup;
|
|
||||||
/*if (adg != null)
|
|
||||||
rlist.add(new RouteItem(new IPv6AddressGroup(adg.getAddress(), 128), adg.getAddress(), this, "Direct", 0, 0,
|
|
||||||
null, "D", true));*/
|
|
||||||
|
|
||||||
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext(); ) {
|
for (Iterator<Neighbor> iteratorx = getNeighborsInfo().iterator(); iteratorx.hasNext(); ) {
|
||||||
Neighbor addresses = (Neighbor) iteratorx.next();
|
Neighbor addresses = (Neighbor) iteratorx.next();
|
||||||
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
RouteItem ri = new RouteItem(new IPv6AddressGroup(addresses.getAddress().getAddress(), 128),
|
||||||
addresses.getAddress().getAddress(), this, "Direct", 0, 128, CostSupplierFactory.expectedDelaySupplier((DelayMonitorData) addresses.getMonitor(), status, algorithm::getRTO), "D", false);
|
addresses.getAddress().getAddress(), this, RouteItem.SRv6_ENDXSID, 0, 128, CostSupplierFactory.expectedDelaySupplier((DelayMonitorData) addresses.getMonitor(), status, algorithm::getRTO), "D");
|
||||||
rlist.add(ri);
|
rlist.add(ri);
|
||||||
|
|
||||||
if (addresses.getLocator() != null) {
|
if (addresses.getLocator() != null) {
|
||||||
RouteItem ris = new RouteItem(addresses.getLocator(), addresses.getLocator().getAddress(), this,
|
RouteItem ris = new RouteItem(addresses.getLocator(), addresses.getLocator().getAddress(), this,
|
||||||
"KLALB SRv6", 13, 128, CostSupplierFactory.expectedDelaySupplier((DelayMonitorData) addresses.getMonitor(), status, algorithm::getRTO), "D", false);
|
RouteItem.SRv6_ENDSID, 13, 128, CostSupplierFactory.expectedDelaySupplier((DelayMonitorData) addresses.getMonitor(), status, algorithm::getRTO), "D");
|
||||||
rlist.add(ris);
|
rlist.add(ris);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rlist;
|
return rlist;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCongressCondition(Lock lock, Condition condition) {
|
public void setCongressCondition(Lock lock, Condition condition) {
|
||||||
|
|||||||
@@ -1,211 +0,0 @@
|
|||||||
package org.kne.cloud.network.klalb;
|
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
|
||||||
import org.kne.cloud.network.srv6.ExternalEndpointsResult;
|
|
||||||
import org.kne.cloud.network.srv6.ExtraRoutesResult;
|
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
|
||||||
import org.kne.cloud.network.srv6.NodeInfoQueryStatus;
|
|
||||||
import org.kne.cloud.network.srv6.NodeProfile;
|
|
||||||
|
|
||||||
/** Coordinates the three independent sections of a remote node-info query. */
|
|
||||||
public final class NodeInfoQueryCoordinator {
|
|
||||||
private static final long DEADLINE_MILLIS = 3000L;
|
|
||||||
private static final ExecutorService REQUEST_EXECUTOR = Executors.newVirtualThreadPerTaskExecutor();
|
|
||||||
private static final ScheduledExecutorService DEADLINE_EXECUTOR = Executors
|
|
||||||
.newSingleThreadScheduledExecutor(r -> {
|
|
||||||
Thread thread = new Thread(r, "KLALB-node-info-deadline");
|
|
||||||
thread.setDaemon(true);
|
|
||||||
return thread;
|
|
||||||
});
|
|
||||||
|
|
||||||
private final KLALBRoutingProtocolAPIClient client;
|
|
||||||
|
|
||||||
public NodeInfoQueryCoordinator(KLALBRoutingProtocolAPIClient client) {
|
|
||||||
this.client = Objects.requireNonNull(client, "client");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Starts all section requests and completes at the first all-sections response or the shared deadline. */
|
|
||||||
public CompletableFuture<Result> query(SocketAddress address) {
|
|
||||||
Objects.requireNonNull(address, "address");
|
|
||||||
Pending pending = new Pending();
|
|
||||||
pending.result.whenComplete((ignored, error) -> {
|
|
||||||
if (pending.result.isCancelled()) pending.cancel();
|
|
||||||
});
|
|
||||||
pending.deadline = DEADLINE_EXECUTOR.schedule(pending::timeout, DEADLINE_MILLIS, TimeUnit.MILLISECONDS);
|
|
||||||
|
|
||||||
issue(pending, () -> client.requestNodeProfile(address, pending::profile), pending::profileFailed);
|
|
||||||
issue(pending, () -> client.requestExternalEndpoints(address, pending::externalEndpoints),
|
|
||||||
pending::externalEndpointsFailed);
|
|
||||||
issue(pending, () -> client.requestExtraRoutes(address, pending::extraRoutes), pending::extraRoutesFailed);
|
|
||||||
return pending.result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void issue(Pending pending, ThrowingRequest request, Runnable failure) {
|
|
||||||
REQUEST_EXECUTOR.execute(() -> pending.issue(request, failure));
|
|
||||||
}
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
private interface ThrowingRequest {
|
|
||||||
void run() throws Exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Section<T> {
|
|
||||||
private final boolean received;
|
|
||||||
private final Optional<T> value;
|
|
||||||
private final Optional<NodeInfoQueryStatus> status;
|
|
||||||
|
|
||||||
private Section(boolean received, T value, NodeInfoQueryStatus status) {
|
|
||||||
this.received = received;
|
|
||||||
this.value = Optional.ofNullable(value);
|
|
||||||
this.status = Optional.ofNullable(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReceived() {
|
|
||||||
return received;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<T> getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Optional<NodeInfoQueryStatus> getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> Section<T> missing() {
|
|
||||||
return new Section<T>(false, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> Section<T> received(T value, NodeInfoQueryStatus status) {
|
|
||||||
return new Section<T>(true, value, status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Result {
|
|
||||||
private final Section<NodeProfile> profile;
|
|
||||||
private final Section<List<MultiProtocolSocketAddress>> externalEndpoints;
|
|
||||||
private final Section<List<String>> extraRoutes;
|
|
||||||
|
|
||||||
private Result(Section<NodeProfile> profile,
|
|
||||||
Section<List<MultiProtocolSocketAddress>> externalEndpoints,
|
|
||||||
Section<List<String>> extraRoutes) {
|
|
||||||
this.profile = profile;
|
|
||||||
this.externalEndpoints = externalEndpoints;
|
|
||||||
this.extraRoutes = extraRoutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Section<NodeProfile> getProfile() {
|
|
||||||
return profile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Section<List<MultiProtocolSocketAddress>> getExternalEndpoints() {
|
|
||||||
return externalEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Section<List<String>> getExtraRoutes() {
|
|
||||||
return extraRoutes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final class Pending {
|
|
||||||
private final CompletableFuture<Result> result = new CompletableFuture<>();
|
|
||||||
private final AtomicBoolean finished = new AtomicBoolean();
|
|
||||||
private int remaining = 3;
|
|
||||||
private Section<NodeProfile> profile = Section.missing();
|
|
||||||
private Section<List<MultiProtocolSocketAddress>> externalEndpoints = Section.missing();
|
|
||||||
private Section<List<String>> extraRoutes = Section.missing();
|
|
||||||
private java.util.concurrent.ScheduledFuture<?> deadline;
|
|
||||||
|
|
||||||
private synchronized void profile(NodeProfile value) {
|
|
||||||
if (profile.isReceived()) return;
|
|
||||||
profile = Section.received(value, NodeInfoQueryStatus.OK);
|
|
||||||
completeSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void profileFailed() {
|
|
||||||
if (profile.isReceived()) return;
|
|
||||||
profile = Section.missing();
|
|
||||||
completeSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void externalEndpoints(ExternalEndpointsResult value) {
|
|
||||||
if (externalEndpoints.isReceived()) return;
|
|
||||||
if (value == null) {
|
|
||||||
externalEndpoints = Section.missing();
|
|
||||||
} else {
|
|
||||||
List<MultiProtocolSocketAddress> endpoints = value.getExternalEndpoints();
|
|
||||||
externalEndpoints = Section.received(endpoints == null
|
|
||||||
? Collections.<MultiProtocolSocketAddress>emptyList()
|
|
||||||
: Collections.unmodifiableList(new ArrayList<MultiProtocolSocketAddress>(endpoints)),
|
|
||||||
value.getStatus());
|
|
||||||
}
|
|
||||||
completeSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void externalEndpointsFailed() {
|
|
||||||
if (externalEndpoints.isReceived()) return;
|
|
||||||
externalEndpoints = Section.missing();
|
|
||||||
completeSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void extraRoutes(ExtraRoutesResult value) {
|
|
||||||
if (extraRoutes.isReceived()) return;
|
|
||||||
if (value == null) {
|
|
||||||
extraRoutes = Section.missing();
|
|
||||||
} else {
|
|
||||||
List<String> routes = value.getExtraRoutes();
|
|
||||||
extraRoutes = Section.received(routes == null
|
|
||||||
? Collections.<String>emptyList()
|
|
||||||
: Collections.unmodifiableList(new ArrayList<String>(routes)), value.getStatus());
|
|
||||||
}
|
|
||||||
completeSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void extraRoutesFailed() {
|
|
||||||
if (extraRoutes.isReceived()) return;
|
|
||||||
extraRoutes = Section.missing();
|
|
||||||
completeSection();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void issue(ThrowingRequest request, Runnable failure) {
|
|
||||||
if (finished.get() || result.isDone() || result.isCancelled()) return;
|
|
||||||
try {
|
|
||||||
request.run();
|
|
||||||
} catch (Exception e) {
|
|
||||||
failure.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void cancel() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void completeSection() {
|
|
||||||
remaining--;
|
|
||||||
if (remaining == 0) finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized void timeout() {
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void finish() {
|
|
||||||
if (!finished.compareAndSet(false, true)) return;
|
|
||||||
if (deadline != null) deadline.cancel(false);
|
|
||||||
result.complete(new Result(profile, externalEndpoints, extraRoutes));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,6 @@ import java.io.IOException;
|
|||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -1064,17 +1063,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
for (KLALBConfigItem item : config) {
|
for (KLALBConfigItem item : config) {
|
||||||
if (item instanceof KLALBControllerConfigItem) {
|
if (item instanceof KLALBControllerConfigItem) {
|
||||||
KLALBControllerConfigItem kck = (KLALBControllerConfigItem) item;
|
KLALBControllerConfigItem kck = (KLALBControllerConfigItem) item;
|
||||||
String oldDeviceName = kck.getDeviceName();
|
|
||||||
String oldDeviceDescription = kck.getDeviceDescription();
|
|
||||||
List<MultiProtocolSocketAddress> oldExternalEndpoints = kck.getExternalEndpoints() == null
|
|
||||||
? null
|
|
||||||
: new ArrayList<MultiProtocolSocketAddress>(kck.getExternalEndpoints());
|
|
||||||
List<String> oldExtraRoutes = kck.getExtraRoutes() == null
|
|
||||||
? null : new ArrayList<String>(kck.getExtraRoutes());
|
|
||||||
String newDeviceName;
|
|
||||||
String newDeviceDescription;
|
|
||||||
List<String> newExtraRoutes;
|
|
||||||
List<MultiProtocolSocketAddress> newExternalEndpoints;
|
|
||||||
|
|
||||||
// 保存语言设置
|
// 保存语言设置
|
||||||
kck.setLanguage(((Language) comboLang.getSelectedItem()).name());
|
kck.setLanguage(((Language) comboLang.getSelectedItem()).name());
|
||||||
@@ -1084,16 +1072,20 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
// 保存设备名称
|
// 保存设备名称
|
||||||
String dnametext = deviceNameSet.getText().trim();
|
String dnametext = deviceNameSet.getText().trim();
|
||||||
if (dnametext.equals("")) {
|
if (dnametext.equals("")) {
|
||||||
newDeviceName = null;
|
kck.setDeviceName(null);
|
||||||
} else {
|
} else {
|
||||||
newDeviceName = dnametext;
|
kck.setDeviceName(dnametext);
|
||||||
}
|
}
|
||||||
|
if (kcontroller != null && kcontroller.getIpv6Router() != null) {
|
||||||
|
kcontroller.getIpv6Router().setDeviceName(kck.getDeviceName());
|
||||||
|
}
|
||||||
|
|
||||||
// 保存设备描述
|
// 保存设备描述
|
||||||
String ddesctext = deviceDescriptionSet.getText().trim();
|
String ddesctext = deviceDescriptionSet.getText().trim();
|
||||||
if (ddesctext.equals("")) {
|
if (ddesctext.equals("")) {
|
||||||
newDeviceDescription = null;
|
kck.setDeviceDescription(null);
|
||||||
} else {
|
} else {
|
||||||
newDeviceDescription = ddesctext;
|
kck.setDeviceDescription(ddesctext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1149,7 +1141,7 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newExtraRoutes = eroutes;
|
kck.setExtraRoutes(eroutes);
|
||||||
|
|
||||||
// 保存ASN
|
// 保存ASN
|
||||||
String asntext = asnFieldSet.getText();
|
String asntext = asnFieldSet.getText();
|
||||||
@@ -1240,7 +1232,7 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newExternalEndpoints = iaddr1;
|
kck.setExternalEndpoints(iaddr1);
|
||||||
|
|
||||||
// 保存自动连接线路表
|
// 保存自动连接线路表
|
||||||
String[] splt11 = connectLineTabelSet.getText().split("\n");
|
String[] splt11 = connectLineTabelSet.getText().split("\n");
|
||||||
@@ -1313,22 +1305,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
kck.setNagleDelayTime(nagleDelayTime.getSlider().getValue()*100000L);
|
kck.setNagleDelayTime(nagleDelayTime.getSlider().getValue()*100000L);
|
||||||
|
|
||||||
kck.setLinkNagleDelayTime(linkNagleDelayTime.getSlider().getValue()*100000L);
|
kck.setLinkNagleDelayTime(linkNagleDelayTime.getSlider().getValue()*100000L);
|
||||||
|
|
||||||
boolean deviceNameChanged = !Objects.equals(oldDeviceName, newDeviceName);
|
|
||||||
boolean deviceDescriptionChanged = !Objects.equals(oldDeviceDescription, newDeviceDescription);
|
|
||||||
boolean externalEndpointsChanged = !Objects.equals(oldExternalEndpoints, newExternalEndpoints);
|
|
||||||
boolean extraRoutesChanged = !Objects.equals(oldExtraRoutes, newExtraRoutes);
|
|
||||||
if (deviceNameChanged || deviceDescriptionChanged || externalEndpointsChanged || extraRoutesChanged) {
|
|
||||||
if (kcontroller != null) {
|
|
||||||
kcontroller.publishNodeInfo(newDeviceName, newDeviceDescription, newExternalEndpoints,
|
|
||||||
newExtraRoutes);
|
|
||||||
} else {
|
|
||||||
kck.setDeviceName(newDeviceName);
|
|
||||||
kck.setDeviceDescription(newDeviceDescription);
|
|
||||||
kck.setExternalEndpoints(newExternalEndpoints);
|
|
||||||
kck.setExtraRoutes(newExtraRoutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1430,19 +1406,17 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
tsk5 = new TimerTask() {
|
tsk5 = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
SwingUtilities.invokeLater(() -> {
|
if (isVisible()) {
|
||||||
if (isVisible()) {
|
graph.loadNodes();
|
||||||
graph.loadNodes();
|
for (int i = 0; i < 100; i++) {
|
||||||
for (int i = 0; i < 100; i++) {
|
graph.runPhy();
|
||||||
graph.runPhy();
|
|
||||||
}
|
|
||||||
graph.repaint();
|
|
||||||
graph.revalidate();
|
|
||||||
}
|
}
|
||||||
});
|
graph.repaint();
|
||||||
|
graph.revalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
t.scheduleAtFixedRate(tsk5, 0, 1000);
|
t.scheduleAtFixedRate(tsk5, 1000, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1788,15 +1762,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
* 关闭窗口并清理资源
|
* 关闭窗口并清理资源
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
|
|
||||||
Component component = tabbedPane.getComponentAt(i);
|
|
||||||
if (component instanceof NodeInformationPanel) {
|
|
||||||
((NodeInformationPanel) component).close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (graph != null) {
|
|
||||||
graph.close();
|
|
||||||
}
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
if (tsk != null) {
|
if (tsk != null) {
|
||||||
tsk.cancel();
|
tsk.cancel();
|
||||||
|
|||||||
@@ -18,7 +18,10 @@ import org.jfree.chart.JFreeChart;
|
|||||||
import org.jfree.data.time.Millisecond;
|
import org.jfree.data.time.Millisecond;
|
||||||
import org.jfree.data.time.TimeSeries;
|
import org.jfree.data.time.TimeSeries;
|
||||||
import org.jfree.data.time.TimeSeriesCollection;
|
import org.jfree.data.time.TimeSeriesCollection;
|
||||||
|
import org.kne.cloud.network.congestion.CongestionAlgorithm;
|
||||||
|
import org.kne.cloud.network.congestion.DetnetCongestionAlgorithm;
|
||||||
import org.kne.cloud.network.congestion.SendPacketSlidingWindow;
|
import org.kne.cloud.network.congestion.SendPacketSlidingWindow;
|
||||||
|
import org.kne.cloud.network.congestion.Vegas2CongestionAlgorithm;
|
||||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||||
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
||||||
import org.kne.cloud.network.ipv6.IPv6Packet;
|
import org.kne.cloud.network.ipv6.IPv6Packet;
|
||||||
@@ -42,12 +45,14 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
private Timer timer1;
|
private Timer timer1;
|
||||||
private Timer timer2;
|
private Timer timer2;
|
||||||
private Timer timer3;
|
private Timer timer3;
|
||||||
|
private Timer timer4;
|
||||||
private TimerTask tsk3;
|
private TimerTask tsk3;
|
||||||
|
|
||||||
private TimerTask tsk4, tsk5,tsk6;
|
private TimerTask tsk4, tsk5,tsk6,tsk7;
|
||||||
private TimerTask d1;
|
private TimerTask d1;
|
||||||
private TimerTask d2;
|
private TimerTask d2;
|
||||||
private TimerTask d3;
|
private TimerTask d3;
|
||||||
|
private TimerTask d4;
|
||||||
|
|
||||||
private TimeSeries spdup = new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
|
private TimeSeries spdup = new TimeSeries(UIEnv.getRsb().getString("uploadspeed"));
|
||||||
private TimeSeries spddown = new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
|
private TimeSeries spddown = new TimeSeries(UIEnv.getRsb().getString("downloadspeed"));
|
||||||
@@ -62,13 +67,21 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
private TimeSeries queueused = new TimeSeries(UIEnv.getRsb().getString("queueused"));
|
private TimeSeries queueused = new TimeSeries(UIEnv.getRsb().getString("queueused"));
|
||||||
private TimeSeries buffermax = new TimeSeries(UIEnv.getRsb().getString("maxbuffer"));
|
private TimeSeries buffermax = new TimeSeries(UIEnv.getRsb().getString("maxbuffer"));
|
||||||
|
|
||||||
|
|
||||||
|
private TimeSeries rttbaseline = new TimeSeries(UIEnv.getRsb().getString("rttbaseline"));
|
||||||
|
private TimeSeries rtt = new TimeSeries(UIEnv.getRsb().getString("rtt"));
|
||||||
|
private TimeSeries rttmin=new TimeSeries(UIEnv.getRsb().getString("rttmin"));
|
||||||
|
private TimeSeries rttmax=new TimeSeries(UIEnv.getRsb().getString("rttmax"));
|
||||||
|
|
||||||
private KLALBRemoteLink tr;
|
private KLALBRemoteLink tr;
|
||||||
private JFreeChart jfc;
|
private JFreeChart jfc;
|
||||||
private JFreeChart jfce;
|
private JFreeChart jfce;
|
||||||
private JFreeChart jbfc;
|
private JFreeChart jbfc;
|
||||||
|
private JFreeChart jbfcv;
|
||||||
private JLabel spdp;
|
private JLabel spdp;
|
||||||
private JLabel delp;
|
private JLabel delp;
|
||||||
private JLabel sbpdp;
|
private JLabel sbpdp;
|
||||||
|
private JLabel sbpdpv;
|
||||||
private long timeRange = 5000;
|
private long timeRange = 5000;
|
||||||
private long[] values = new long[] { 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000 };
|
private long[] values = new long[] { 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000 };
|
||||||
private JPanel panel_1;
|
private JPanel panel_1;
|
||||||
@@ -155,6 +168,22 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
jp.add(sbpdp);
|
jp.add(sbpdp);
|
||||||
|
|
||||||
|
|
||||||
|
TimeSeriesCollection tbsc1 = new TimeSeriesCollection();
|
||||||
|
tbsc1.addSeries(rttbaseline);
|
||||||
|
tbsc1.addSeries(rtt);
|
||||||
|
tbsc1.addSeries(rttmax);
|
||||||
|
tbsc1.addSeries(rttmin);
|
||||||
|
jbfcv = ChartFactory.createTimeSeriesChart(UIEnv.getRsb().getString("congestionmonitor"),
|
||||||
|
UIEnv.getRsb().getString("time") + "(s)", UIEnv.getRsb().getString("delay") + "(ms)", tbsc1);
|
||||||
|
jbfcv.getXYPlot().setBackgroundPaint(Color.BLACK);
|
||||||
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(0, Color.CYAN);
|
||||||
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(1, Color.YELLOW);
|
||||||
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(2, Color.GREEN);
|
||||||
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(3, Color.RED);
|
||||||
|
changeFont(jbfcv);
|
||||||
|
sbpdpv = new JLabel();
|
||||||
|
sbpdpv.setBorder(new LineBorder(Color.DARK_GRAY));
|
||||||
|
jp.add(sbpdpv);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -262,6 +291,14 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
buffermax.setMaximumItemCount((int) timeRange/5);
|
buffermax.setMaximumItemCount((int) timeRange/5);
|
||||||
queueused.setMaximumItemCount((int) timeRange/5);
|
queueused.setMaximumItemCount((int) timeRange/5);
|
||||||
}
|
}
|
||||||
|
synchronized (jbfcv) {
|
||||||
|
|
||||||
|
jbfcv.getXYPlot().getDomainAxis().setFixedAutoRange(timeRange);
|
||||||
|
bufferused.setMaximumItemCount((int) timeRange/5);
|
||||||
|
buffermax.setMaximumItemCount((int) timeRange/5);
|
||||||
|
queueused.setMaximumItemCount((int) timeRange/5);
|
||||||
|
}
|
||||||
|
|
||||||
windowSelect.setText(timeRange / 1000 + "s");
|
windowSelect.setText(timeRange / 1000 + "s");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,6 +365,24 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private void recordCongestionData() {
|
||||||
|
if (isVisible()) {
|
||||||
|
Millisecond ms = new Millisecond(
|
||||||
|
new Date(tr.getMonitor().getClock().getCurrentTimeMillis()));
|
||||||
|
synchronized (jbfcv) {
|
||||||
|
CongestionAlgorithm window=tr.getWindow().getAlgorithm();
|
||||||
|
if(window !=null&&window instanceof DetnetCongestionAlgorithm) {
|
||||||
|
Vegas2CongestionAlgorithm deta=(Vegas2CongestionAlgorithm) window;
|
||||||
|
double baseRTT=deta.getBaseRTT();
|
||||||
|
rttbaseline.addOrUpdate(ms, baseRTT / 1000000.0);
|
||||||
|
rtt.addOrUpdate(ms, deta.getCurrentRTT() / 1000000.0);
|
||||||
|
rttmax.addOrUpdate(ms, baseRTT*deta.getUpperDelayBound() / 1000000.0);
|
||||||
|
rttmin.addOrUpdate(ms, baseRTT*deta.getLowerDelayBound() / 1000000.0);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void setVisible(boolean b) {
|
public void setVisible(boolean b) {
|
||||||
if (b) {
|
if (b) {
|
||||||
@@ -336,6 +391,7 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
timer1 = new Timer();
|
timer1 = new Timer();
|
||||||
timer2 = new Timer();
|
timer2 = new Timer();
|
||||||
timer3 = new Timer();
|
timer3 = new Timer();
|
||||||
|
timer4 = new Timer();
|
||||||
tsk3 = new TimerTask() {
|
tsk3 = new TimerTask() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -365,6 +421,13 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
recordBufferData();
|
recordBufferData();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
tsk7 = new TimerTask() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
recordCongestionData();
|
||||||
|
}
|
||||||
|
};
|
||||||
d1 = new TimerTask() {
|
d1 = new TimerTask() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -406,6 +469,20 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
d4 = new TimerTask() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (isVisible()) {
|
||||||
|
synchronized (jbfcv) {
|
||||||
|
ImageIcon i3 = new ImageIcon(
|
||||||
|
jbfcv.createBufferedImage(sbpdpv.getWidth(), sbpdpv.getHeight()));
|
||||||
|
sbpdpv.setIcon(i3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
timer.scheduleAtFixedRate(tsk3, 25, 25);
|
timer.scheduleAtFixedRate(tsk3, 25, 25);
|
||||||
timer1.scheduleAtFixedRate(tsk4, 10, 10);
|
timer1.scheduleAtFixedRate(tsk4, 10, 10);
|
||||||
timer1.scheduleAtFixedRate(d1, 25, 25);
|
timer1.scheduleAtFixedRate(d1, 25, 25);
|
||||||
@@ -413,6 +490,8 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
timer2.scheduleAtFixedRate(d2, 25, 25);
|
timer2.scheduleAtFixedRate(d2, 25, 25);
|
||||||
timer3.scheduleAtFixedRate(tsk6, 10, 10);
|
timer3.scheduleAtFixedRate(tsk6, 10, 10);
|
||||||
timer3.scheduleAtFixedRate(d3, 25, 25);
|
timer3.scheduleAtFixedRate(d3, 25, 25);
|
||||||
|
timer4.scheduleAtFixedRate(tsk7, 25, 25);
|
||||||
|
timer4.scheduleAtFixedRate(d4, 25, 25);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -422,12 +501,18 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
tsk4.cancel();
|
tsk4.cancel();
|
||||||
if (tsk5 != null)
|
if (tsk5 != null)
|
||||||
tsk5.cancel();
|
tsk5.cancel();
|
||||||
|
if (tsk6 != null)
|
||||||
|
tsk6.cancel();
|
||||||
|
if (tsk7 != null)
|
||||||
|
tsk7.cancel();
|
||||||
if (d1 != null)
|
if (d1 != null)
|
||||||
d1.cancel();
|
d1.cancel();
|
||||||
if (d2 != null)
|
if (d2 != null)
|
||||||
d2.cancel();
|
d2.cancel();
|
||||||
if (d3 != null)
|
if (d3 != null)
|
||||||
d3.cancel();
|
d3.cancel();
|
||||||
|
if (d4 != null)
|
||||||
|
d4.cancel();
|
||||||
if (timer != null)
|
if (timer != null)
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
if (timer1 != null)
|
if (timer1 != null)
|
||||||
@@ -438,6 +523,9 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
|
|
||||||
if (timer3 != null)
|
if (timer3 != null)
|
||||||
timer3.cancel();
|
timer3.cancel();
|
||||||
|
|
||||||
|
if (timer4 != null)
|
||||||
|
timer4.cancel();
|
||||||
timer = null;
|
timer = null;
|
||||||
}
|
}
|
||||||
super.setVisible(b);
|
super.setVisible(b);
|
||||||
|
|||||||
@@ -8,58 +8,28 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
|
|
||||||
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
||||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||||
import org.kne.cloud.network.klalb.KLALBController;
|
import org.kne.cloud.network.klalb.KLALBController;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
|
||||||
import org.kne.cloud.network.srv6.NodeProfile;
|
|
||||||
import org.kne.cloud.network.srv6.RouterInfoPacket;
|
|
||||||
|
|
||||||
public class NetworkGraphPanel extends GraphPanel {
|
public class NetworkGraphPanel extends GraphPanel {
|
||||||
private KLALBController controller;
|
private KLALBController controller;
|
||||||
private KLALBStateGUI3 klbgui;
|
private KLALBStateGUI3 klbgui;
|
||||||
private final KLALBRoutingProtocolAPIClient nodeInfoClient;
|
|
||||||
private final KLALBRoutingProtocol nodeInfoRoutingProtocol;
|
|
||||||
private final BiConsumer<IPv6Address, Integer> nodeInfoUpdateListener;
|
|
||||||
private final Object nodeInfoLock = new Object();
|
|
||||||
private final Map<IPv6Address, String> nodeNameCache = new HashMap<IPv6Address, String>();
|
|
||||||
private final Map<IPv6Address, Long> nodeNameCacheTimes = new HashMap<IPv6Address, Long>();
|
|
||||||
private final Map<IPv6Address, Long> nodeInfoRequestTimes = new HashMap<IPv6Address, Long>();
|
|
||||||
private final Map<IPv6Address, Long> nodeInfoRequestGenerations = new HashMap<IPv6Address, Long>();
|
|
||||||
private static final long NODE_INFO_REQUEST_TIMEOUT = 3000L;
|
|
||||||
private static final long NODE_INFO_CACHE_TTL = 60000L;
|
|
||||||
private long nextNodeInfoRequestGeneration;
|
|
||||||
private volatile boolean nodeInfoClosed;
|
|
||||||
|
|
||||||
public NetworkGraphPanel(KLALBController controller,KLALBStateGUI3 klbgui) {
|
public NetworkGraphPanel(KLALBController controller,KLALBStateGUI3 klbgui) {
|
||||||
super();
|
super();
|
||||||
this.controller = controller;
|
this.controller = controller;
|
||||||
this.klbgui=klbgui;
|
this.klbgui=klbgui;
|
||||||
this.nodeInfoRoutingProtocol = controller.getIpv6Router().getKlalbRouteProtol();
|
|
||||||
this.nodeInfoClient = new KLALBRoutingProtocolAPIClient(nodeInfoRoutingProtocol);
|
|
||||||
this.nodeInfoUpdateListener = (address, flags) -> {
|
|
||||||
if ((flags & RouterInfoPacket.NODE_INFO_TINY_UPDATE_REQUIRED) != 0) {
|
|
||||||
SwingUtilities.invokeLater(() -> invalidateTinyNodeInfo(address));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
nodeInfoRoutingProtocol.addNodeInfoUpdateListener(nodeInfoUpdateListener);
|
|
||||||
cacheLocalNodeName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetworkGraphPanel(KLALBController kc) {
|
public NetworkGraphPanel(KLALBController kc) {
|
||||||
@@ -112,8 +82,8 @@ public class NetworkGraphPanel extends GraphPanel {
|
|||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
KperfGUI kpfg=new KperfGUI();
|
KperfGUI kpfg=new KperfGUI();
|
||||||
kpfg.setVisible(true);
|
kpfg.setVisible(true);
|
||||||
MultiProtocolSocketAddress source=new MultiProtocolSocketAddress("KLALB_Stream",controller.getIpv6Router().getLocator().getAddress().toString(),0);
|
MultiProtocolSocketAddress source=new MultiProtocolSocketAddress("kltp",controller.getIpv6Router().getLocator().getAddress().toString(),0);
|
||||||
MultiProtocolSocketAddress target=new MultiProtocolSocketAddress("KLALB_Stream", address.toString(), 4564);
|
MultiProtocolSocketAddress target=new MultiProtocolSocketAddress("kltp", address.toString(), 4564);
|
||||||
kpfg.setTarget(target,source);
|
kpfg.setTarget(target,source);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -183,145 +153,17 @@ public class NetworkGraphPanel extends GraphPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 节点标签:显示 Tiny API 查询的设备名称(若有)+IP地址
|
* 节点标签:显示广播得知的设备名称(若有)+IP地址
|
||||||
*/
|
*/
|
||||||
private String getNodeText(IPv6Address address) {
|
private String getNodeText(IPv6Address address) {
|
||||||
StringBuilder sb=new StringBuilder();
|
StringBuilder sb=new StringBuilder();
|
||||||
String dname;
|
String dname=controller.getIpv6Router().getKlalbRouteProtol().getDeviceName(address);
|
||||||
synchronized (nodeInfoLock) {
|
if(dname!=null)
|
||||||
dname = nodeNameCache.get(address);
|
|
||||||
}
|
|
||||||
if(dname!=null&&!dname.isEmpty())
|
|
||||||
sb.append(dname).append('\n');
|
sb.append(dname).append('\n');
|
||||||
sb.append(InetGraphNode.getText(address));
|
sb.append(InetGraphNode.getText(address));
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cacheLocalNodeName() {
|
|
||||||
IPv6Address localAddress = controller.getIpv6Router().getLocator().getAddress();
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
nodeNameCache.put(localAddress, controller.getIpv6Router().getDeviceName());
|
|
||||||
nodeNameCacheTimes.put(localAddress, System.currentTimeMillis());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestNodeProfile(final IPv6Address address) {
|
|
||||||
final long requestTime = System.currentTimeMillis();
|
|
||||||
final long requestGeneration;
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
if (nodeInfoClosed)
|
|
||||||
return;
|
|
||||||
Long cachedAt = nodeNameCacheTimes.get(address);
|
|
||||||
if (nodeNameCache.containsKey(address) && cachedAt != null
|
|
||||||
&& requestTime - cachedAt < NODE_INFO_CACHE_TTL)
|
|
||||||
return;
|
|
||||||
nodeNameCache.remove(address);
|
|
||||||
nodeNameCacheTimes.remove(address);
|
|
||||||
Long previousRequestTime = nodeInfoRequestTimes.get(address);
|
|
||||||
if (previousRequestTime != null && requestTime - previousRequestTime < NODE_INFO_REQUEST_TIMEOUT)
|
|
||||||
return;
|
|
||||||
nodeInfoRequestTimes.put(address, requestTime);
|
|
||||||
requestGeneration = ++nextNodeInfoRequestGeneration;
|
|
||||||
nodeInfoRequestGenerations.put(address, requestGeneration);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
nodeInfoClient.requestNodeProfile(
|
|
||||||
new InetSocketAddress(address.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT),
|
|
||||||
(profile) -> SwingUtilities.invokeLater(() -> handleNodeProfile(address, requestGeneration, profile)));
|
|
||||||
} catch (IOException e) {
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
if (nodeInfoRequestGenerations.get(address) != null
|
|
||||||
&& nodeInfoRequestGenerations.get(address).longValue() == requestGeneration) {
|
|
||||||
nodeInfoRequestTimes.remove(address);
|
|
||||||
nodeInfoRequestGenerations.remove(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleNodeProfile(IPv6Address address, long requestGeneration, NodeProfile profile) {
|
|
||||||
if (nodeInfoClosed)
|
|
||||||
return;
|
|
||||||
boolean currentRequest;
|
|
||||||
boolean nodeExists = getNodes().containsKey(address);
|
|
||||||
String deviceName = profile == null ? "" : profile.getDeviceName();
|
|
||||||
if (deviceName == null || deviceName.isEmpty())
|
|
||||||
deviceName = "";
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
if (nodeInfoClosed)
|
|
||||||
return;
|
|
||||||
Long activeRequestGeneration = nodeInfoRequestGenerations.get(address);
|
|
||||||
currentRequest = activeRequestGeneration != null
|
|
||||||
&& activeRequestGeneration.longValue() == requestGeneration;
|
|
||||||
if (currentRequest) {
|
|
||||||
nodeInfoRequestTimes.remove(address);
|
|
||||||
nodeInfoRequestGenerations.remove(address);
|
|
||||||
if (nodeExists)
|
|
||||||
nodeNameCache.put(address, deviceName);
|
|
||||||
else
|
|
||||||
nodeNameCache.remove(address);
|
|
||||||
if (nodeExists)
|
|
||||||
nodeNameCacheTimes.put(address, System.currentTimeMillis());
|
|
||||||
else
|
|
||||||
nodeNameCacheTimes.remove(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (currentRequest && nodeExists) {
|
|
||||||
((InetGraphNode) getNodes().get(address)).updateLabel();
|
|
||||||
repaint();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeNodeInfoState(IPv6Address address) {
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
nodeNameCache.remove(address);
|
|
||||||
nodeNameCacheTimes.remove(address);
|
|
||||||
nodeInfoRequestTimes.remove(address);
|
|
||||||
nodeInfoRequestGenerations.remove(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void invalidateTinyNodeInfo(IPv6Address address) {
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
if (nodeInfoClosed)
|
|
||||||
return;
|
|
||||||
nodeNameCache.remove(address);
|
|
||||||
nodeNameCacheTimes.remove(address);
|
|
||||||
nodeInfoRequestTimes.remove(address);
|
|
||||||
nodeInfoRequestGenerations.remove(address);
|
|
||||||
}
|
|
||||||
InetGraphNode node = (InetGraphNode) getNodes().get(address);
|
|
||||||
if (node != null) {
|
|
||||||
node.updateLabel();
|
|
||||||
}
|
|
||||||
repaint();
|
|
||||||
requestNodeProfile(address);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
synchronized (nodeInfoLock) {
|
|
||||||
if (nodeInfoClosed)
|
|
||||||
return;
|
|
||||||
nodeInfoClosed = true;
|
|
||||||
nodeNameCache.clear();
|
|
||||||
nodeNameCacheTimes.clear();
|
|
||||||
nodeInfoRequestTimes.clear();
|
|
||||||
nodeInfoRequestGenerations.clear();
|
|
||||||
}
|
|
||||||
nodeInfoRoutingProtocol.removeNodeInfoUpdateListener(nodeInfoUpdateListener);
|
|
||||||
nodeInfoClient.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeNotify() {
|
|
||||||
super.removeNotify();
|
|
||||||
SwingUtilities.invokeLater(() -> {
|
|
||||||
if (!isDisplayable() && getParent() == null) {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private double nsPerPixel=5000L;
|
private double nsPerPixel=5000L;
|
||||||
private class InetGraphEdgeGroup extends GraphEdgeGroup{
|
private class InetGraphEdgeGroup extends GraphEdgeGroup{
|
||||||
public InetGraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) {
|
public InetGraphEdgeGroup(GraphNode nodeA, GraphNode nodeB) {
|
||||||
@@ -339,8 +181,6 @@ public class NetworkGraphPanel extends GraphPanel {
|
|||||||
}
|
}
|
||||||
protected void loadNodes() {
|
protected void loadNodes() {
|
||||||
Map<IPv6Address, Long> addr= controller.getIpv6Router().getKlalbRouteProtol().getAddresses();
|
Map<IPv6Address, Long> addr= controller.getIpv6Router().getKlalbRouteProtol().getAddresses();
|
||||||
IPv6Address localAddress = controller.getIpv6Router().getLocator().getAddress();
|
|
||||||
cacheLocalNodeName();
|
|
||||||
Set<IPv6Address> ks=addr.keySet();
|
Set<IPv6Address> ks=addr.keySet();
|
||||||
for (Iterator<IPv6Address> iterator = ks.iterator(); iterator.hasNext();) {
|
for (Iterator<IPv6Address> iterator = ks.iterator(); iterator.hasNext();) {
|
||||||
IPv6Address inet6Address = (IPv6Address) iterator.next();
|
IPv6Address inet6Address = (IPv6Address) iterator.next();
|
||||||
@@ -348,15 +188,12 @@ public class NetworkGraphPanel extends GraphPanel {
|
|||||||
Vector2 v2pos=super.getRandomPos();
|
Vector2 v2pos=super.getRandomPos();
|
||||||
getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(controller.getIpv6Router().getLocator().getAddress())));
|
getNodes().put(inet6Address,new InetGraphNode(inet6Address,Color.BLACK,v2pos.x,v2pos.y,inet6Address.equals(controller.getIpv6Router().getLocator().getAddress())));
|
||||||
}
|
}
|
||||||
if(!inet6Address.equals(localAddress))
|
|
||||||
requestNodeProfile(inet6Address);
|
|
||||||
}
|
}
|
||||||
Set<IPv6Address> kns=getNodes().keySet();
|
Set<IPv6Address> kns=getNodes().keySet();
|
||||||
for (Iterator<IPv6Address> iterator = kns.iterator(); iterator.hasNext();) {
|
for (Iterator<IPv6Address> iterator = kns.iterator(); iterator.hasNext();) {
|
||||||
IPv6Address inet6Address = (IPv6Address) iterator.next();
|
IPv6Address inet6Address = (IPv6Address) iterator.next();
|
||||||
if(!addr.containsKey(inet6Address)) {
|
if(!addr.containsKey(inet6Address)) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
removeNodeInfoState(inet6Address);
|
|
||||||
}else {
|
}else {
|
||||||
((InetGraphNode)getNodes().get(inet6Address)).updateLabel();
|
((InetGraphNode)getNodes().get(inet6Address)).updateLabel();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import java.awt.BorderLayout;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.Toolkit;
|
import java.awt.Toolkit;
|
||||||
import java.awt.datatransfer.StringSelection;
|
import java.awt.datatransfer.StringSelection;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
@@ -24,11 +24,8 @@ import org.kne.cloud.klalb.uitool.XDefaultListModel;
|
|||||||
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
||||||
import org.kne.cloud.network.ipv6.IPv6Address;
|
import org.kne.cloud.network.ipv6.IPv6Address;
|
||||||
import org.kne.cloud.network.klalb.KLALBController;
|
import org.kne.cloud.network.klalb.KLALBController;
|
||||||
import org.kne.cloud.network.klalb.NodeInfoQueryCoordinator;
|
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
||||||
import org.kne.cloud.network.srv6.NodeInfoQueryStatus;
|
|
||||||
import org.kne.cloud.network.srv6.NodeProfile;
|
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.JTabbedPane;
|
||||||
import javax.swing.JList;
|
import javax.swing.JList;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
@@ -37,20 +34,14 @@ import java.awt.event.ActionListener;
|
|||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
public class NodeInformationPanel extends JPanel {
|
public class NodeInformationPanel extends JPanel {
|
||||||
private IPv6Address address;
|
private IPv6Address address;
|
||||||
private KLALBRoutingProtocolAPIClient client;
|
private KLALBRoutingProtocolAPIClient client;
|
||||||
private NodeInfoQueryCoordinator queryCoordinator;
|
|
||||||
private KLALBController controller;
|
private KLALBController controller;
|
||||||
private Image image;
|
private Image image;
|
||||||
|
|
||||||
private XDefaultListModel<MultiProtocolSocketAddress> listModel=new XDefaultListModel<>();
|
private XDefaultListModel<MultiProtocolSocketAddress> listModel=new XDefaultListModel<>();
|
||||||
private XDefaultListModel<String> extraRoutesModel=new XDefaultListModel<>();
|
|
||||||
private volatile boolean active=true;
|
|
||||||
private final AtomicLong fullInfoGeneration=new AtomicLong();
|
|
||||||
private final java.util.function.BiConsumer<IPv6Address,Integer> nodeInfoUpdateListener;
|
|
||||||
public KLALBController getController() {
|
public KLALBController getController() {
|
||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
@@ -82,21 +73,17 @@ public class NodeInformationPanel extends JPanel {
|
|||||||
overviewArea.setWrapStyleWord(true);
|
overviewArea.setWrapStyleWord(true);
|
||||||
overviewArea.setFont(UIEnv.getFont().deriveFont(14.0f));
|
overviewArea.setFont(UIEnv.getFont().deriveFont(14.0f));
|
||||||
overviewArea.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
overviewArea.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||||
overviewArea.setText(buildOverviewText(null, null));
|
String dname=controller.getIpv6Router().getKlalbRouteProtol().getDeviceName(address);
|
||||||
|
String ddesc=null;
|
||||||
|
if(address.equals(controller.getIpv6Router().getLocator().getAddress())&&controller.getConfigItem()!=null) {
|
||||||
|
ddesc=controller.getConfigItem().getDeviceDescription();
|
||||||
|
if(ddesc!=null&&ddesc.isEmpty()) {
|
||||||
|
ddesc=null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overviewArea.setText(buildOverviewText(dname, ddesc));
|
||||||
panel.add(new JScrollPane(overviewArea), BorderLayout.CENTER);
|
panel.add(new JScrollPane(overviewArea), BorderLayout.CENTER);
|
||||||
|
|
||||||
JPanel extraRoutesPanel = new JPanel(new BorderLayout());
|
|
||||||
JList<String> extraRoutesList = new JList<String>(extraRoutesModel);
|
|
||||||
extraRoutesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
extraRoutesList.setFont(UIEnv.getFont().deriveFont(14.0f));
|
|
||||||
extraRoutesPanel.add(new JScrollPane(extraRoutesList), BorderLayout.CENTER);
|
|
||||||
javax.swing.JLabel extraRoutesEmptyLabel=new javax.swing.JLabel(UIEnv.getRsb().getString("noextraroutes"));
|
|
||||||
extraRoutesEmptyLabel.setText("...");
|
|
||||||
extraRoutesEmptyLabel.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
|
||||||
extraRoutesEmptyLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
|
|
||||||
extraRoutesPanel.add(extraRoutesEmptyLabel, BorderLayout.SOUTH);
|
|
||||||
tabbedPane.addTab(UIEnv.getRsb().getString("extraroutes"), null, extraRoutesPanel, null);
|
|
||||||
|
|
||||||
JPanel panel_1 = new JPanel();
|
JPanel panel_1 = new JPanel();
|
||||||
panel_1.setLayout(new BorderLayout(0, 0));
|
panel_1.setLayout(new BorderLayout(0, 0));
|
||||||
panel_1.add(scrollPane);
|
panel_1.add(scrollPane);
|
||||||
@@ -176,111 +163,29 @@ public class NodeInformationPanel extends JPanel {
|
|||||||
|
|
||||||
panel_1.add(btnNewButton, BorderLayout.SOUTH);
|
panel_1.add(btnNewButton, BorderLayout.SOUTH);
|
||||||
|
|
||||||
KLALBRoutingProtocol routingProtocol=controller.getIpv6Router().getKlalbRouteProtol();
|
client=new KLALBRoutingProtocolAPIClient(controller.getIpv6Router().getKlalbRouteProtol());
|
||||||
client=new KLALBRoutingProtocolAPIClient(routingProtocol);
|
|
||||||
queryCoordinator=new NodeInfoQueryCoordinator(client);
|
|
||||||
nodeInfoUpdateListener=(updatedAddress, flags) -> {
|
|
||||||
if(active && address.equals(updatedAddress)
|
|
||||||
&& (flags & org.kne.cloud.network.srv6.RouterInfoPacket.NODE_INFO_FULL_UPDATE_REQUIRED) != 0) {
|
|
||||||
requestFullInfo(overviewArea, extraRoutesEmptyLabel);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
routingProtocol.addNodeInfoUpdateListener(nodeInfoUpdateListener);
|
|
||||||
requestFullInfo(overviewArea, extraRoutesEmptyLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void requestFullInfo(JTextArea overviewArea, javax.swing.JLabel extraRoutesEmptyLabel) {
|
|
||||||
final long generation=fullInfoGeneration.incrementAndGet();
|
|
||||||
if (controller.getIpv6Router().getLocator().getAddress().equals(address)) {
|
|
||||||
KLALBController.PublishedNodeInfo published=controller.getPublishedNodeInfo();
|
|
||||||
applyNodeInfo(overviewArea, extraRoutesEmptyLabel, published.getDeviceName(),
|
|
||||||
published.getDeviceDescription(), published.getExternalEndpoints(), published.getExtraRoutes());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
queryCoordinator.query(new InetSocketAddress(address.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT)).whenComplete((info, error)->{
|
client.requestNodeInfoFull(new InetSocketAddress( address.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT), (info)->{
|
||||||
if(!active || generation!=fullInfoGeneration.get()) return;
|
listModel.clear();
|
||||||
javax.swing.SwingUtilities.invokeLater(() -> {
|
for (MultiProtocolSocketAddress multiProtocolSocketAddress : info.getOpenLines()) {
|
||||||
if(!active || generation!=fullInfoGeneration.get()) return;
|
listModel.addElement(multiProtocolSocketAddress);
|
||||||
if (error != null || info == null) {
|
}
|
||||||
return;
|
// 用对端返回的设备名称/描述更新概览(旧版本节点无该字段时保留原显示)
|
||||||
}
|
String dn=info.getDeviceName();
|
||||||
applyRemoteNodeInfo(overviewArea, extraRoutesEmptyLabel, info);
|
if(dn==null||dn.isEmpty()) {
|
||||||
});
|
dn=controller.getIpv6Router().getKlalbRouteProtol().getDeviceName(address);
|
||||||
|
}
|
||||||
|
String dd=info.getDeviceDescription();
|
||||||
|
if(dd!=null&&dd.isEmpty()) {
|
||||||
|
dd=null;
|
||||||
|
}
|
||||||
|
overviewArea.setText(buildOverviewText(dn, dd));
|
||||||
});
|
});
|
||||||
} catch (RuntimeException e) {
|
} catch (IOException e) {
|
||||||
if(active) e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyNodeInfo(JTextArea overviewArea, javax.swing.JLabel extraRoutesEmptyLabel,
|
|
||||||
String deviceName, String deviceDescription, List<MultiProtocolSocketAddress> endpoints,
|
|
||||||
List<String> routes) {
|
|
||||||
applyProfile(overviewArea, deviceName, deviceDescription);
|
|
||||||
applyEndpoints(endpoints == null ? Collections.<MultiProtocolSocketAddress>emptyList() : endpoints);
|
|
||||||
applyRoutes(extraRoutesEmptyLabel, routes == null ? Collections.<String>emptyList() : routes);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyRemoteNodeInfo(JTextArea overviewArea, javax.swing.JLabel extraRoutesEmptyLabel,
|
|
||||||
NodeInfoQueryCoordinator.Result info) {
|
|
||||||
if (info.getProfile().isReceived()) {
|
|
||||||
NodeProfile profile=info.getProfile().getValue().orElse(null);
|
|
||||||
applyProfile(overviewArea, profile == null ? null : profile.getDeviceName(),
|
|
||||||
profile == null ? null : profile.getDeviceDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.getExternalEndpoints().isReceived()) {
|
|
||||||
List<MultiProtocolSocketAddress> endpoints=info.getExternalEndpoints().getStatus()
|
|
||||||
.filter(NodeInfoQueryStatus.OK::equals).isPresent()
|
|
||||||
? info.getExternalEndpoints().getValue().orElse(Collections.<MultiProtocolSocketAddress>emptyList())
|
|
||||||
: Collections.<MultiProtocolSocketAddress>emptyList();
|
|
||||||
applyEndpoints(endpoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.getExtraRoutes().isReceived()) {
|
|
||||||
List<String> routes=info.getExtraRoutes().getStatus().filter(NodeInfoQueryStatus.OK::equals).isPresent()
|
|
||||||
? info.getExtraRoutes().getValue().orElse(Collections.<String>emptyList())
|
|
||||||
: Collections.<String>emptyList();
|
|
||||||
applyRoutes(extraRoutesEmptyLabel, routes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyProfile(JTextArea overviewArea, String deviceName, String deviceDescription) {
|
|
||||||
overviewArea.setText(buildOverviewText(deviceName,
|
|
||||||
deviceDescription == null || deviceDescription.isEmpty() ? null : deviceDescription));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyEndpoints(List<MultiProtocolSocketAddress> endpoints) {
|
|
||||||
listModel.clear();
|
|
||||||
if (endpoints != null) for (MultiProtocolSocketAddress item : endpoints) listModel.addElement(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyRoutes(javax.swing.JLabel extraRoutesEmptyLabel, List<String> routes) {
|
|
||||||
extraRoutesModel.clear();
|
|
||||||
if (routes != null) for (String route : routes) extraRoutesModel.addElement(route);
|
|
||||||
extraRoutesEmptyLabel.setText(UIEnv.getRsb().getString("noextraroutes"));
|
|
||||||
extraRoutesEmptyLabel.setVisible(extraRoutesModel.isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void close() {
|
|
||||||
if (!active)
|
|
||||||
return;
|
|
||||||
active=false;
|
|
||||||
fullInfoGeneration.incrementAndGet();
|
|
||||||
KLALBRoutingProtocol routingProtocol=controller.getIpv6Router().getKlalbRouteProtol();
|
|
||||||
routingProtocol.removeNodeInfoUpdateListener(nodeInfoUpdateListener);
|
|
||||||
if(client!=null) {
|
|
||||||
client.close();
|
|
||||||
client=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeNotify() {
|
|
||||||
close();
|
|
||||||
super.removeNotify();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String buildOverviewText(String dname,String ddesc) {
|
private String buildOverviewText(String dname,String ddesc) {
|
||||||
StringBuilder sb=new StringBuilder();
|
StringBuilder sb=new StringBuilder();
|
||||||
sb.append(UIEnv.getRsb().getString("ipv6addr")).append(": ").append(address.toCompressedString()).append('\n');
|
sb.append(UIEnv.getRsb().getString("ipv6addr")).append(": ").append(address.toCompressedString()).append('\n');
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import java.nio.file.*;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
|
|
||||||
import com.sun.net.httpserver.*;
|
import com.sun.net.httpserver.*;
|
||||||
import com.google.gson.*;
|
import com.google.gson.*;
|
||||||
@@ -20,14 +19,12 @@ import org.kne.cloud.network.ipv6.IPv6NetworkLink;
|
|||||||
import org.kne.cloud.network.ipv6.RouteItem;
|
import org.kne.cloud.network.ipv6.RouteItem;
|
||||||
import org.kne.cloud.network.klalb.*;
|
import org.kne.cloud.network.klalb.*;
|
||||||
import org.kne.cloud.network.monitor.LinkStatus;
|
import org.kne.cloud.network.monitor.LinkStatus;
|
||||||
|
import org.kne.cloud.network.srv6.KLALBNodeInformation;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocol;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocol.LinkDirection;
|
||||||
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
import org.kne.cloud.network.srv6.KLALBRoutingProtocolAPIClient;
|
||||||
import org.kne.cloud.network.srv6.NodeInfoQueryStatus;
|
|
||||||
import org.kne.cloud.network.srv6.NodeProfile;
|
|
||||||
import org.kne.cloud.network.srv6.NeighborInfo;
|
import org.kne.cloud.network.srv6.NeighborInfo;
|
||||||
import org.kne.cloud.network.srv6.RouterInfo;
|
import org.kne.cloud.network.srv6.RouterInfo;
|
||||||
import org.kne.cloud.network.srv6.RouterInfoPacket;
|
|
||||||
import org.kne.cloud.network.srv6.SRv6Router;
|
import org.kne.cloud.network.srv6.SRv6Router;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,12 +35,14 @@ public class KLALBWebServer {
|
|||||||
private final KLALBProxySystem proxySystem;
|
private final KLALBProxySystem proxySystem;
|
||||||
private final MultiProtocolSocketAddress listen;
|
private final MultiProtocolSocketAddress listen;
|
||||||
private HttpServer server;
|
private HttpServer server;
|
||||||
private ExecutorService httpExecutor;
|
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
private ScheduledExecutorService sseExecutor = createSseExecutor();
|
private final ScheduledExecutorService sseExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||||
|
Thread t = new Thread(r, "KLALB-Web-SSE");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
private final Set<HttpExchange> sseClients = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
private final Set<HttpExchange> sseClients = Collections.newSetFromMap(new ConcurrentHashMap<>());
|
||||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||||
private final Object configUpdateLock = new Object();
|
|
||||||
|
|
||||||
public KLALBWebServer(KLALBProxySystem proxySystem, int port) {
|
public KLALBWebServer(KLALBProxySystem proxySystem, int port) {
|
||||||
this(proxySystem, new MultiProtocolSocketAddress("http", "0.0.0.0", port));
|
this(proxySystem, new MultiProtocolSocketAddress("http", "0.0.0.0", port));
|
||||||
@@ -53,36 +52,15 @@ public class KLALBWebServer {
|
|||||||
this.proxySystem = proxySystem;
|
this.proxySystem = proxySystem;
|
||||||
this.listen = listen;
|
this.listen = listen;
|
||||||
this.gson = proxySystem.getGson();
|
this.gson = proxySystem.getGson();
|
||||||
this.nodeInfoUpdateListener = (address, flags) -> {
|
|
||||||
if ((flags & RouterInfoPacket.NODE_INFO_FULL_UPDATE_REQUIRED) != 0) {
|
|
||||||
nodeInfoRevisions.merge(address, 1L, Long::sum);
|
|
||||||
}
|
|
||||||
if ((flags & RouterInfoPacket.NODE_INFO_TINY_UPDATE_REQUIRED) != 0) {
|
|
||||||
long lifecycleGeneration;
|
|
||||||
synchronized (this) {
|
|
||||||
lifecycleGeneration = nodeInfoLifecycleGeneration;
|
|
||||||
}
|
|
||||||
invalidateTinyDeviceName(address);
|
|
||||||
KLALBController kc = this.proxySystem.getKlalbController();
|
|
||||||
if (kc != null && kc.getIpv6Router() != null
|
|
||||||
&& kc.getIpv6Router().getKlalbRouteProtol() != null) {
|
|
||||||
refreshTinyDeviceNameAsync(kc, address, lifecycleGeneration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void start() throws IOException {
|
public synchronized void start() throws IOException {
|
||||||
if (running.get()) return;
|
if (running.get()) return;
|
||||||
if (sseExecutor == null || sseExecutor.isShutdown()) {
|
|
||||||
sseExecutor = createSseExecutor();
|
|
||||||
}
|
|
||||||
|
|
||||||
InetSocketAddress socketAddress = "0.0.0.0".equals(listen.getHost())
|
InetSocketAddress socketAddress = "0.0.0.0".equals(listen.getHost())
|
||||||
? new InetSocketAddress(listen.getPort()) : listen.getSocketAddress();
|
? new InetSocketAddress(listen.getPort()) : listen.getSocketAddress();
|
||||||
server = HttpServer.create(socketAddress, 0);
|
server = HttpServer.create(socketAddress, 0);
|
||||||
ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();
|
server.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
|
||||||
server.setExecutor(executor);
|
|
||||||
|
|
||||||
// API Contexts
|
// API Contexts
|
||||||
server.createContext("/api/status", this::handleStatus);
|
server.createContext("/api/status", this::handleStatus);
|
||||||
@@ -98,13 +76,7 @@ public class KLALBWebServer {
|
|||||||
// Static Files / SPA Fallback Handler
|
// Static Files / SPA Fallback Handler
|
||||||
server.createContext("/", this::handleStatic);
|
server.createContext("/", this::handleStatic);
|
||||||
|
|
||||||
try {
|
server.start();
|
||||||
server.start();
|
|
||||||
httpExecutor = executor;
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
executor.shutdownNow();
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
running.set(true);
|
running.set(true);
|
||||||
startSseBroadcaster();
|
startSseBroadcaster();
|
||||||
|
|
||||||
@@ -112,11 +84,7 @@ public class KLALBWebServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void stop() {
|
public synchronized void stop() {
|
||||||
if (!running.get()) {
|
if (!running.get()) return;
|
||||||
closeHttpExecutor();
|
|
||||||
closeNodeInfoClient();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
running.set(false);
|
running.set(false);
|
||||||
sseExecutor.shutdownNow();
|
sseExecutor.shutdownNow();
|
||||||
for (HttpExchange client : sseClients) {
|
for (HttpExchange client : sseClients) {
|
||||||
@@ -129,18 +97,9 @@ public class KLALBWebServer {
|
|||||||
server.stop(1);
|
server.stop(1);
|
||||||
server = null;
|
server = null;
|
||||||
}
|
}
|
||||||
closeHttpExecutor();
|
|
||||||
closeNodeInfoClient();
|
|
||||||
System.out.println("KLALB Web Dashboard stopped.");
|
System.out.println("KLALB Web Dashboard stopped.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void closeHttpExecutor() {
|
|
||||||
if (httpExecutor != null) {
|
|
||||||
httpExecutor.shutdownNow();
|
|
||||||
httpExecutor = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRunning() {
|
public boolean isRunning() {
|
||||||
return running.get();
|
return running.get();
|
||||||
}
|
}
|
||||||
@@ -497,159 +456,14 @@ public class KLALBWebServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private KLALBRoutingProtocolAPIClient nodeInfoClient;
|
private KLALBRoutingProtocolAPIClient nodeInfoClient;
|
||||||
private static final long TINY_NAME_REQUEST_TIMEOUT_MS = 3000L;
|
|
||||||
private final ConcurrentMap<IPv6Address, String> tinyDeviceNameCache = new ConcurrentHashMap<>();
|
|
||||||
private final ConcurrentMap<IPv6Address, Long> tinyDeviceNameCacheTimes = new ConcurrentHashMap<>();
|
|
||||||
private final Set<IPv6Address> tinyNameRequestsInFlight = ConcurrentHashMap.newKeySet();
|
|
||||||
private final ConcurrentMap<IPv6Address, Long> tinyNameRequestTimes = new ConcurrentHashMap<>();
|
|
||||||
private final ConcurrentMap<IPv6Address, Long> tinyNameRequestGenerations = new ConcurrentHashMap<>();
|
|
||||||
private final ConcurrentMap<IPv6Address, Long> nodeInfoRevisions = new ConcurrentHashMap<>();
|
|
||||||
private final Object tinyNameStateLock = new Object();
|
|
||||||
private static final long TINY_NAME_CACHE_TTL_MS = 60000L;
|
|
||||||
private long nextTinyNameRequestGeneration;
|
|
||||||
private KLALBRoutingProtocol nodeInfoRoutingProtocol;
|
|
||||||
private final BiConsumer<IPv6Address, Integer> nodeInfoUpdateListener;
|
|
||||||
private long nodeInfoLifecycleGeneration;
|
|
||||||
|
|
||||||
private static ScheduledExecutorService createSseExecutor() {
|
|
||||||
return Executors.newSingleThreadScheduledExecutor(r -> {
|
|
||||||
Thread t = new Thread(r, "KLALB-Web-SSE");
|
|
||||||
t.setDaemon(true);
|
|
||||||
return t;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized KLALBRoutingProtocolAPIClient getNodeInfoClient(KLALBController kc) {
|
private synchronized KLALBRoutingProtocolAPIClient getNodeInfoClient(KLALBController kc) {
|
||||||
return getNodeInfoClient(kc, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private synchronized KLALBRoutingProtocolAPIClient getNodeInfoClient(KLALBController kc,
|
|
||||||
long expectedLifecycleGeneration) {
|
|
||||||
if (!running.get() || (expectedLifecycleGeneration >= 0
|
|
||||||
&& expectedLifecycleGeneration != nodeInfoLifecycleGeneration)
|
|
||||||
|| kc == null || kc.getIpv6Router() == null
|
|
||||||
|| kc.getIpv6Router().getKlalbRouteProtol() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (nodeInfoClient == null) {
|
if (nodeInfoClient == null) {
|
||||||
nodeInfoRoutingProtocol = kc.getIpv6Router().getKlalbRouteProtol();
|
nodeInfoClient = new KLALBRoutingProtocolAPIClient(kc.getIpv6Router().getKlalbRouteProtol());
|
||||||
nodeInfoClient = new KLALBRoutingProtocolAPIClient(nodeInfoRoutingProtocol);
|
|
||||||
nodeInfoRoutingProtocol.addNodeInfoUpdateListener(nodeInfoUpdateListener);
|
|
||||||
}
|
}
|
||||||
return nodeInfoClient;
|
return nodeInfoClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void closeNodeInfoClient() {
|
|
||||||
nodeInfoLifecycleGeneration++;
|
|
||||||
if (nodeInfoRoutingProtocol != null) {
|
|
||||||
nodeInfoRoutingProtocol.removeNodeInfoUpdateListener(nodeInfoUpdateListener);
|
|
||||||
nodeInfoRoutingProtocol = null;
|
|
||||||
}
|
|
||||||
if (nodeInfoClient != null) {
|
|
||||||
nodeInfoClient.close();
|
|
||||||
nodeInfoClient = null;
|
|
||||||
}
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
tinyDeviceNameCache.clear();
|
|
||||||
tinyDeviceNameCacheTimes.clear();
|
|
||||||
tinyNameRequestsInFlight.clear();
|
|
||||||
tinyNameRequestTimes.clear();
|
|
||||||
tinyNameRequestGenerations.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTinyDeviceName(KLALBController kc, IPv6Address addr) {
|
|
||||||
return getTinyDeviceName(kc, addr, -1L);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTinyDeviceName(KLALBController kc, IPv6Address addr, long lifecycleGeneration) {
|
|
||||||
String cachedName;
|
|
||||||
long requestStartedAt = 0L;
|
|
||||||
long requestGeneration;
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
cachedName = tinyDeviceNameCache.get(addr);
|
|
||||||
Long cachedAt = tinyDeviceNameCacheTimes.get(addr);
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
if (cachedName != null && cachedAt != null && now - cachedAt < TINY_NAME_CACHE_TTL_MS) return cachedName;
|
|
||||||
tinyDeviceNameCache.remove(addr);
|
|
||||||
tinyDeviceNameCacheTimes.remove(addr);
|
|
||||||
|
|
||||||
if (tinyNameRequestsInFlight.contains(addr)) {
|
|
||||||
Long requestedAt = tinyNameRequestTimes.get(addr);
|
|
||||||
if (requestedAt != null && now - requestedAt < TINY_NAME_REQUEST_TIMEOUT_MS) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
tinyNameRequestsInFlight.remove(addr);
|
|
||||||
tinyNameRequestTimes.remove(addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tinyNameRequestsInFlight.add(addr)) return "";
|
|
||||||
requestStartedAt = now;
|
|
||||||
tinyNameRequestTimes.put(addr, requestStartedAt);
|
|
||||||
requestGeneration = ++nextTinyNameRequestGeneration;
|
|
||||||
tinyNameRequestGenerations.put(addr, requestGeneration);
|
|
||||||
}
|
|
||||||
|
|
||||||
final long requestGenerationToken = requestGeneration;
|
|
||||||
try {
|
|
||||||
KLALBRoutingProtocolAPIClient client = lifecycleGeneration < 0
|
|
||||||
? getNodeInfoClient(kc) : getNodeInfoClient(kc, lifecycleGeneration);
|
|
||||||
if (client == null) {
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
if (Long.valueOf(requestGenerationToken).equals(tinyNameRequestGenerations.get(addr))) {
|
|
||||||
tinyNameRequestsInFlight.remove(addr);
|
|
||||||
tinyNameRequestTimes.remove(addr);
|
|
||||||
tinyNameRequestGenerations.remove(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
client.requestNodeProfile(
|
|
||||||
new InetSocketAddress(addr.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT),
|
|
||||||
profile -> {
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
Long activeRequestGeneration = tinyNameRequestGenerations.get(addr);
|
|
||||||
if (!Long.valueOf(requestGenerationToken).equals(activeRequestGeneration)) return;
|
|
||||||
tinyDeviceNameCache.put(addr,
|
|
||||||
profile != null && profile.getDeviceName() != null ? profile.getDeviceName() : "");
|
|
||||||
tinyDeviceNameCacheTimes.put(addr, System.currentTimeMillis());
|
|
||||||
tinyNameRequestsInFlight.remove(addr);
|
|
||||||
tinyNameRequestTimes.remove(addr);
|
|
||||||
tinyNameRequestGenerations.remove(addr);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
Long activeRequestGeneration = tinyNameRequestGenerations.get(addr);
|
|
||||||
if (Long.valueOf(requestGenerationToken).equals(activeRequestGeneration)) {
|
|
||||||
tinyNameRequestsInFlight.remove(addr);
|
|
||||||
tinyNameRequestTimes.remove(addr);
|
|
||||||
tinyNameRequestGenerations.remove(addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
private void refreshTinyDeviceNameAsync(KLALBController kc, IPv6Address address, long lifecycleGeneration) {
|
|
||||||
CompletableFuture.runAsync(() -> {
|
|
||||||
synchronized (this) {
|
|
||||||
if (!running.get() || nodeInfoLifecycleGeneration != lifecycleGeneration) return;
|
|
||||||
getTinyDeviceName(kc, address, lifecycleGeneration);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void invalidateTinyDeviceName(IPv6Address address) {
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
tinyDeviceNameCache.remove(address);
|
|
||||||
tinyDeviceNameCacheTimes.remove(address);
|
|
||||||
tinyNameRequestsInFlight.remove(address);
|
|
||||||
tinyNameRequestTimes.remove(address);
|
|
||||||
tinyNameRequestGenerations.remove(address);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleNodeInfo(HttpExchange exchange) throws IOException {
|
private void handleNodeInfo(HttpExchange exchange) throws IOException {
|
||||||
if (handleCorsPreflight(exchange)) return;
|
if (handleCorsPreflight(exchange)) return;
|
||||||
if (!"GET".equalsIgnoreCase(exchange.getRequestMethod())) {
|
if (!"GET".equalsIgnoreCase(exchange.getRequestMethod())) {
|
||||||
@@ -686,70 +500,56 @@ public class KLALBWebServer {
|
|||||||
|
|
||||||
if (isSelf) {
|
if (isSelf) {
|
||||||
// 本机:描述直接取本地控制器配置
|
// 本机:描述直接取本地控制器配置
|
||||||
KLALBController.PublishedNodeInfo published = kc.getPublishedNodeInfo();
|
KLALBControllerConfigItem cfg = proxySystem.getControllerConfig();
|
||||||
resp.addProperty("isSelf", true);
|
resp.addProperty("isSelf", true);
|
||||||
resp.addProperty("reachable", true);
|
String dname = router.getDeviceName() != null ? router.getDeviceName()
|
||||||
resp.addProperty("deviceName", published.getDeviceName() != null ? published.getDeviceName() : "");
|
: (cfg != null && cfg.getDeviceName() != null ? cfg.getDeviceName() : "");
|
||||||
|
resp.addProperty("deviceName", dname);
|
||||||
resp.addProperty("deviceDescription",
|
resp.addProperty("deviceDescription",
|
||||||
published.getDeviceDescription() != null ? published.getDeviceDescription() : "");
|
cfg != null && cfg.getDeviceDescription() != null ? cfg.getDeviceDescription() : "");
|
||||||
JsonArray lines = new JsonArray();
|
JsonArray lines = new JsonArray();
|
||||||
for (MultiProtocolSocketAddress mpsa : published.getExternalEndpoints()) {
|
for (MultiProtocolSocketAddress mpsa : kc.getExternalEndpoints()) {
|
||||||
lines.add(new JsonPrimitive(mpsa.toString()));
|
lines.add(new JsonPrimitive(mpsa.toString()));
|
||||||
}
|
}
|
||||||
resp.add("openLines", lines);
|
resp.add("openLines", lines);
|
||||||
JsonArray extraRoutes = new JsonArray();
|
|
||||||
if (published.getExtraRoutes() != null) {
|
|
||||||
for (String route : published.getExtraRoutes()) {
|
|
||||||
extraRoutes.add(new JsonPrimitive(route != null ? route : ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resp.add("extraRoutes", extraRoutes);
|
|
||||||
sendJsonResponse(exchange, 200, resp);
|
sendJsonResponse(exchange, 200, resp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 远端节点:经 SRv6 虚拟网络发送完整节点信息查询(异步回调,限时等待)
|
// 远端节点:经 SRv6 虚拟网络发送完整节点信息查询(异步回调,限时等待)
|
||||||
resp.addProperty("isSelf", false);
|
resp.addProperty("isSelf", false);
|
||||||
|
CompletableFuture<KLALBNodeInformation> future = new CompletableFuture<>();
|
||||||
try {
|
try {
|
||||||
KLALBRoutingProtocolAPIClient client = getNodeInfoClient(kc);
|
getNodeInfoClient(kc).requestNodeInfoFull(
|
||||||
if (client == null) {
|
new InetSocketAddress(target.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT),
|
||||||
sendError(exchange, 503, "Node info service stopped");
|
info -> future.complete(info));
|
||||||
return;
|
|
||||||
|
KLALBNodeInformation info;
|
||||||
|
try {
|
||||||
|
info = future.get(3, TimeUnit.SECONDS);
|
||||||
|
} catch (TimeoutException te) {
|
||||||
|
info = null;
|
||||||
}
|
}
|
||||||
NodeInfoQueryCoordinator.Result info = new NodeInfoQueryCoordinator(client)
|
|
||||||
.query(new InetSocketAddress(target.toInet6Address(), KLALBRoutingProtocol.DEFAULT_PORT)).get();
|
String dname = info != null && info.getDeviceName() != null && !info.getDeviceName().isEmpty()
|
||||||
NodeInfoQueryCoordinator.Section<NodeProfile> profile = info.getProfile();
|
? info.getDeviceName()
|
||||||
NodeProfile nodeProfile = profile.getValue().orElse(null);
|
: router.getKlalbRouteProtol().getDeviceName(target);
|
||||||
String dname = nodeProfile != null && nodeProfile.getDeviceName() != null
|
resp.addProperty("deviceName", dname != null ? dname : "");
|
||||||
&& !nodeProfile.getDeviceName().isEmpty() ? nodeProfile.getDeviceName() : "";
|
|
||||||
resp.addProperty("deviceName", dname);
|
|
||||||
resp.addProperty("deviceDescription",
|
resp.addProperty("deviceDescription",
|
||||||
nodeProfile != null && nodeProfile.getDeviceDescription() != null
|
info != null && info.getDeviceDescription() != null ? info.getDeviceDescription() : "");
|
||||||
? nodeProfile.getDeviceDescription() : "");
|
resp.addProperty("reachable", info != null);
|
||||||
resp.addProperty("reachable", profile.isReceived()
|
|
||||||
|| info.getExternalEndpoints().isReceived() || info.getExtraRoutes().isReceived());
|
|
||||||
JsonArray lines = new JsonArray();
|
JsonArray lines = new JsonArray();
|
||||||
if (info.getExternalEndpoints().getStatus().filter(NodeInfoQueryStatus.OK::equals).isPresent()
|
if (info != null && info.getOpenLines() != null) {
|
||||||
&& info.getExternalEndpoints().getValue().isPresent()) {
|
for (MultiProtocolSocketAddress mpsa : info.getOpenLines()) {
|
||||||
for (MultiProtocolSocketAddress mpsa : info.getExternalEndpoints().getValue().get()) {
|
|
||||||
lines.add(new JsonPrimitive(mpsa.toString()));
|
lines.add(new JsonPrimitive(mpsa.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
resp.add("openLines", lines);
|
resp.add("openLines", lines);
|
||||||
JsonArray extraRoutes = new JsonArray();
|
|
||||||
if (info.getExtraRoutes().getStatus().filter(NodeInfoQueryStatus.OK::equals).isPresent()
|
|
||||||
&& info.getExtraRoutes().getValue().isPresent()) {
|
|
||||||
for (String route : info.getExtraRoutes().getValue().get()) {
|
|
||||||
extraRoutes.add(new JsonPrimitive(route != null ? route : ""));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resp.add("extraRoutes", extraRoutes);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
resp.addProperty("deviceName", "");
|
resp.addProperty("deviceName", "");
|
||||||
resp.addProperty("deviceDescription", "");
|
resp.addProperty("deviceDescription", "");
|
||||||
resp.addProperty("reachable", false);
|
resp.addProperty("reachable", false);
|
||||||
resp.add("openLines", new JsonArray());
|
resp.add("openLines", new JsonArray());
|
||||||
resp.add("extraRoutes", new JsonArray());
|
|
||||||
}
|
}
|
||||||
sendJsonResponse(exchange, 200, resp);
|
sendJsonResponse(exchange, 200, resp);
|
||||||
}
|
}
|
||||||
@@ -784,17 +584,6 @@ public class KLALBWebServer {
|
|||||||
KLALBRoutingProtocol rproto = kc.getIpv6Router().getKlalbRouteProtol();
|
KLALBRoutingProtocol rproto = kc.getIpv6Router().getKlalbRouteProtol();
|
||||||
Map<IPv6Address, Long> addrs = rproto.getAddresses();
|
Map<IPv6Address, Long> addrs = rproto.getAddresses();
|
||||||
IPv6Address selfAddr = kc.getIpv6Router().getLocator().getAddress();
|
IPv6Address selfAddr = kc.getIpv6Router().getLocator().getAddress();
|
||||||
KLALBController.PublishedNodeInfo published = kc.getPublishedNodeInfo();
|
|
||||||
Set<IPv6Address> activeAddresses = addrs == null
|
|
||||||
? Collections.<IPv6Address>emptySet() : new HashSet<IPv6Address>(addrs.keySet());
|
|
||||||
synchronized (tinyNameStateLock) {
|
|
||||||
tinyDeviceNameCache.keySet().removeIf(address -> !activeAddresses.contains(address));
|
|
||||||
tinyDeviceNameCacheTimes.keySet().removeIf(address -> !activeAddresses.contains(address));
|
|
||||||
tinyNameRequestsInFlight.removeIf(address -> !activeAddresses.contains(address));
|
|
||||||
tinyNameRequestTimes.keySet().removeIf(address -> !activeAddresses.contains(address));
|
|
||||||
tinyNameRequestGenerations.keySet().removeIf(address -> !activeAddresses.contains(address));
|
|
||||||
}
|
|
||||||
nodeInfoRevisions.keySet().removeIf(address -> !activeAddresses.contains(address));
|
|
||||||
|
|
||||||
if (addrs != null) {
|
if (addrs != null) {
|
||||||
for (IPv6Address addr : addrs.keySet()) {
|
for (IPv6Address addr : addrs.keySet()) {
|
||||||
@@ -803,12 +592,8 @@ public class KLALBWebServer {
|
|||||||
nodeObj.addProperty("address", addr.toString());
|
nodeObj.addProperty("address", addr.toString());
|
||||||
nodeObj.addProperty("compressedAddress", addr.toCompressedString());
|
nodeObj.addProperty("compressedAddress", addr.toCompressedString());
|
||||||
nodeObj.addProperty("isSelf", addr.equals(selfAddr));
|
nodeObj.addProperty("isSelf", addr.equals(selfAddr));
|
||||||
String dname = addr.equals(selfAddr) ? kc.getIpv6Router().getDeviceName()
|
String dname = rproto.getDeviceName(addr);
|
||||||
: getTinyDeviceName(kc, addr);
|
|
||||||
nodeObj.addProperty("deviceName", dname != null ? dname : "");
|
nodeObj.addProperty("deviceName", dname != null ? dname : "");
|
||||||
long nodeInfoRevision = addr.equals(selfAddr) ? published.getFullRevision()
|
|
||||||
: nodeInfoRevisions.getOrDefault(addr, 0L);
|
|
||||||
nodeObj.addProperty("nodeInfoRevision", nodeInfoRevision);
|
|
||||||
nodesArray.add(nodeObj);
|
nodesArray.add(nodeObj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -859,33 +644,21 @@ public class KLALBWebServer {
|
|||||||
sendError(exchange, 404, "Configuration not found");
|
sendError(exchange, 404, "Configuration not found");
|
||||||
}
|
}
|
||||||
} else if ("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) {
|
} else if ("POST".equalsIgnoreCase(method) || "PUT".equalsIgnoreCase(method)) {
|
||||||
synchronized (configUpdateLock) {
|
|
||||||
String body = readRequestBody(exchange);
|
String body = readRequestBody(exchange);
|
||||||
try {
|
try {
|
||||||
JsonObject json = new JsonParser().parse(body).getAsJsonObject();
|
JsonObject json = new JsonParser().parse(body).getAsJsonObject();
|
||||||
KLALBControllerConfigItem current = proxySystem.getControllerConfig();
|
KLALBControllerConfigItem current = proxySystem.getControllerConfig();
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
String oldDeviceName = current.getDeviceName();
|
|
||||||
String oldDeviceDescription = current.getDeviceDescription();
|
|
||||||
List<MultiProtocolSocketAddress> oldExternalEndpoints = current.getExternalEndpoints() == null
|
|
||||||
? null
|
|
||||||
: new ArrayList<MultiProtocolSocketAddress>(current.getExternalEndpoints());
|
|
||||||
List<String> oldExtraRoutes = current.getExtraRoutes() == null
|
|
||||||
? null : new ArrayList<String>(current.getExtraRoutes());
|
|
||||||
String newDeviceName = oldDeviceName;
|
|
||||||
String newDeviceDescription = oldDeviceDescription;
|
|
||||||
List<MultiProtocolSocketAddress> newExternalEndpoints = current.getExternalEndpoints();
|
|
||||||
List<String> newExtraRoutes = current.getExtraRoutes();
|
|
||||||
if (json.has("deviceName") && !json.get("deviceName").isJsonNull()) {
|
if (json.has("deviceName") && !json.get("deviceName").isJsonNull()) {
|
||||||
newDeviceName = json.get("deviceName").getAsString();
|
current.setDeviceName(json.get("deviceName").getAsString());
|
||||||
} else if (json.has("DeviceName") && !json.get("DeviceName").isJsonNull()) {
|
} else if (json.has("DeviceName") && !json.get("DeviceName").isJsonNull()) {
|
||||||
newDeviceName = json.get("DeviceName").getAsString();
|
current.setDeviceName(json.get("DeviceName").getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.has("deviceDescription") && !json.get("deviceDescription").isJsonNull()) {
|
if (json.has("deviceDescription") && !json.get("deviceDescription").isJsonNull()) {
|
||||||
newDeviceDescription = json.get("deviceDescription").getAsString();
|
current.setDeviceDescription(json.get("deviceDescription").getAsString());
|
||||||
} else if (json.has("DeviceDescription") && !json.get("DeviceDescription").isJsonNull()) {
|
} else if (json.has("DeviceDescription") && !json.get("DeviceDescription").isJsonNull()) {
|
||||||
newDeviceDescription = json.get("DeviceDescription").getAsString();
|
current.setDeviceDescription(json.get("DeviceDescription").getAsString());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.has("language") && !json.get("language").isJsonNull()) {
|
if (json.has("language") && !json.get("language").isJsonNull()) {
|
||||||
@@ -960,7 +733,7 @@ public class KLALBWebServer {
|
|||||||
list.add(new MultiProtocolSocketAddress(el.getAsString()));
|
list.add(new MultiProtocolSocketAddress(el.getAsString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newExternalEndpoints = list;
|
current.setExternalEndpoints(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.has("autoConnections") || json.has("AutoConnections") || json.has("connectLineTable") || json.has("ConnectLineTable")) {
|
if (json.has("autoConnections") || json.has("AutoConnections") || json.has("connectLineTable") || json.has("ConnectLineTable")) {
|
||||||
@@ -1010,7 +783,7 @@ public class KLALBWebServer {
|
|||||||
list.add(el.getAsString());
|
list.add(el.getAsString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
newExtraRoutes = list;
|
current.setExtraRoutes(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (json.has("networkInterfaceExcepts") || json.has("NetworkInterfaceExcepts")) {
|
if (json.has("networkInterfaceExcepts") || json.has("NetworkInterfaceExcepts")) {
|
||||||
@@ -1072,23 +845,6 @@ public class KLALBWebServer {
|
|||||||
current.setDenyExternalEndpointBroadcast(json.get("denyLineTableBroadcast").getAsBoolean());
|
current.setDenyExternalEndpointBroadcast(json.get("denyLineTableBroadcast").getAsBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean deviceNameChanged = !Objects.equals(oldDeviceName, newDeviceName);
|
|
||||||
boolean deviceDescriptionChanged = !Objects.equals(oldDeviceDescription, newDeviceDescription);
|
|
||||||
boolean externalEndpointsChanged = !Objects.equals(oldExternalEndpoints, newExternalEndpoints);
|
|
||||||
boolean extraRoutesChanged = !Objects.equals(oldExtraRoutes, newExtraRoutes);
|
|
||||||
if (deviceNameChanged || deviceDescriptionChanged || externalEndpointsChanged || extraRoutesChanged) {
|
|
||||||
KLALBController kc = proxySystem.getKlalbController();
|
|
||||||
if (kc != null) {
|
|
||||||
kc.publishNodeInfo(newDeviceName, newDeviceDescription, newExternalEndpoints,
|
|
||||||
newExtraRoutes);
|
|
||||||
} else {
|
|
||||||
current.setDeviceName(newDeviceName);
|
|
||||||
current.setDeviceDescription(newDeviceDescription);
|
|
||||||
current.setExternalEndpoints(newExternalEndpoints);
|
|
||||||
current.setExtraRoutes(newExtraRoutes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger GUI save consumer or save directly
|
// Trigger GUI save consumer or save directly
|
||||||
if (proxySystem.getKLALBGUI() != null && proxySystem.getKLALBGUI().getSaveComsumer() != null) {
|
if (proxySystem.getKLALBGUI() != null && proxySystem.getKLALBGUI().getSaveComsumer() != null) {
|
||||||
proxySystem.getKLALBGUI().getSaveComsumer().accept(proxySystem.getConfig());
|
proxySystem.getKLALBGUI().getSaveComsumer().accept(proxySystem.getConfig());
|
||||||
@@ -1106,7 +862,6 @@ public class KLALBWebServer {
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sendError(exchange, 400, "Failed to update configuration: " + e.getMessage());
|
sendError(exchange, 400, "Failed to update configuration: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
sendError(exchange, 405, "Method not allowed");
|
sendError(exchange, 405, "Method not allowed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.kne.math.Long128;
|
|||||||
public class NTPContext implements Closeable, AutoCloseable {
|
public class NTPContext implements Closeable, AutoCloseable {
|
||||||
private HighAccuracyClock clock;
|
private HighAccuracyClock clock;
|
||||||
private static final boolean debug = false;
|
private static final boolean debug = false;
|
||||||
private static final int REQUEST_COUNT = 5;
|
private static final int REQUEST_COUNT = 10;
|
||||||
|
|
||||||
private Long128 systemFrequencyOffset = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(5000));
|
private Long128 systemFrequencyOffset = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(5000));
|
||||||
private Long128 localPrecision = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(1000));
|
private Long128 localPrecision = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(1000));
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
package org.kne.cloud.network.srv6;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
|
||||||
|
|
||||||
public final class ExternalEndpointsResult {
|
|
||||||
private final List<MultiProtocolSocketAddress> externalEndpoints;
|
|
||||||
private final NodeInfoQueryStatus status;
|
|
||||||
|
|
||||||
public ExternalEndpointsResult(List<MultiProtocolSocketAddress> externalEndpoints, NodeInfoQueryStatus status) {
|
|
||||||
this.externalEndpoints = Collections.unmodifiableList(new ArrayList<MultiProtocolSocketAddress>(
|
|
||||||
externalEndpoints == null ? Collections.<MultiProtocolSocketAddress>emptyList() : externalEndpoints));
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<MultiProtocolSocketAddress> getExternalEndpoints() {
|
|
||||||
return externalEndpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeInfoQueryStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(externalEndpoints, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof ExternalEndpointsResult)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ExternalEndpointsResult other = (ExternalEndpointsResult) obj;
|
|
||||||
return Objects.equals(externalEndpoints, other.externalEndpoints) && status == other.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ExternalEndpointsResult [externalEndpoints=" + externalEndpoints + ", status=" + status + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package org.kne.cloud.network.srv6;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public final class ExtraRoutesResult {
|
|
||||||
private final List<String> extraRoutes;
|
|
||||||
private final NodeInfoQueryStatus status;
|
|
||||||
|
|
||||||
public ExtraRoutesResult(List<String> extraRoutes, NodeInfoQueryStatus status) {
|
|
||||||
this.extraRoutes = Collections.unmodifiableList(new ArrayList<String>(
|
|
||||||
extraRoutes == null ? Collections.<String>emptyList() : extraRoutes));
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getExtraRoutes() {
|
|
||||||
return extraRoutes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeInfoQueryStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(extraRoutes, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof ExtraRoutesResult)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
ExtraRoutesResult other = (ExtraRoutesResult) obj;
|
|
||||||
return Objects.equals(extraRoutes, other.extraRoutes) && status == other.status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "ExtraRoutesResult [extraRoutes=" + extraRoutes + ", status=" + status + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -34,7 +34,6 @@ public class JsonDataPacket extends KLALBRoutingProtocolPacket implements Serial
|
|||||||
private String data;
|
private String data;
|
||||||
|
|
||||||
private static final int HEADER_LENGTH=3;
|
private static final int HEADER_LENGTH=3;
|
||||||
private static final int MAX_JSON_PAYLOAD_LENGTH=65535-HEADER_LENGTH;
|
|
||||||
|
|
||||||
private static Gson gson;
|
private static Gson gson;
|
||||||
static{
|
static{
|
||||||
@@ -76,9 +75,6 @@ public class JsonDataPacket extends KLALBRoutingProtocolPacket implements Serial
|
|||||||
@Override
|
@Override
|
||||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||||
byte[]bta=data.getBytes(Charset.forName("UTF-8"));
|
byte[]bta=data.getBytes(Charset.forName("UTF-8"));
|
||||||
if(bta.length>MAX_JSON_PAYLOAD_LENGTH) {
|
|
||||||
throw new IOException("JSON payload exceeds " + MAX_JSON_PAYLOAD_LENGTH + " bytes");
|
|
||||||
}
|
|
||||||
getHeader().putChar(1,(char) bta.length);
|
getHeader().putChar(1,(char) bta.length);
|
||||||
super.writeToChannel(dto);
|
super.writeToChannel(dto);
|
||||||
dto.write(ByteBuffer.wrap(bta));
|
dto.write(ByteBuffer.wrap(bta));
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package org.kne.cloud.network.srv6;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 节点信息(开放线路 + 设备名称 + 设备描述),由路由协议 JSON API 查询获得。
|
||||||
|
*/
|
||||||
|
public class KLALBNodeInformation {
|
||||||
|
private List<MultiProtocolSocketAddress> openLines;
|
||||||
|
private String deviceName;
|
||||||
|
private String deviceDescription;
|
||||||
|
|
||||||
|
public KLALBNodeInformation(List<MultiProtocolSocketAddress> openLines, String deviceName,
|
||||||
|
String deviceDescription) {
|
||||||
|
super();
|
||||||
|
this.openLines = openLines;
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
this.deviceDescription = deviceDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<MultiProtocolSocketAddress> getOpenLines() {
|
||||||
|
return openLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenLines(List<MultiProtocolSocketAddress> openLines) {
|
||||||
|
this.openLines = openLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceName() {
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceName(String deviceName) {
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeviceDescription() {
|
||||||
|
return deviceDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceDescription(String deviceDescription) {
|
||||||
|
this.deviceDescription = deviceDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "KLALBNodeInformation [openLines=" + openLines + ", deviceName=" + deviceName
|
||||||
|
+ ", deviceDescription=" + deviceDescription + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
@@ -22,8 +21,6 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
import java.util.concurrent.CopyOnWriteArraySet;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
@@ -46,10 +43,6 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
|
|
||||||
private RouterInfo selfRouterInfo;
|
private RouterInfo selfRouterInfo;
|
||||||
private Map<IPv6Address, RouterInfo> netmap=new ConcurrentHashMap<>();
|
private Map<IPv6Address, RouterInfo> netmap=new ConcurrentHashMap<>();
|
||||||
private final AtomicLong selfCreateTime = new AtomicLong();
|
|
||||||
private final AtomicInteger pendingNodeInfoUpdateFlags = new AtomicInteger();
|
|
||||||
private static final int NODE_INFO_UPDATE_REPLAY_WINDOW_SIZE = 64;
|
|
||||||
private final Map<IPv6Address, LinkedHashSet<Long>> seenNodeInfoUpdates = new HashMap<>();
|
|
||||||
|
|
||||||
public Map<IPv6Address, RouterInfo> getNetmap() {
|
public Map<IPv6Address, RouterInfo> getNetmap() {
|
||||||
return netmap;
|
return netmap;
|
||||||
@@ -92,7 +85,6 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
private ReentrantLock sendLock=new ReentrantLock();
|
private ReentrantLock sendLock=new ReentrantLock();
|
||||||
|
|
||||||
private Set<BiConsumer<SocketAddress,JsonDataPacket>>receivers=new CopyOnWriteArraySet<BiConsumer<SocketAddress,JsonDataPacket>>();
|
private Set<BiConsumer<SocketAddress,JsonDataPacket>>receivers=new CopyOnWriteArraySet<BiConsumer<SocketAddress,JsonDataPacket>>();
|
||||||
private Set<BiConsumer<IPv6Address,Integer>> nodeInfoUpdateListeners = new CopyOnWriteArraySet<BiConsumer<IPv6Address,Integer>>();
|
|
||||||
|
|
||||||
public void addReceiver(BiConsumer<SocketAddress,JsonDataPacket> rec) {
|
public void addReceiver(BiConsumer<SocketAddress,JsonDataPacket> rec) {
|
||||||
receivers.add(rec);
|
receivers.add(rec);
|
||||||
@@ -102,57 +94,6 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
receivers.remove(rec);
|
receivers.remove(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addNodeInfoUpdateListener(BiConsumer<IPv6Address,Integer> listener) {
|
|
||||||
nodeInfoUpdateListeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeNodeInfoUpdateListener(BiConsumer<IPv6Address,Integer> listener) {
|
|
||||||
nodeInfoUpdateListeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void announceNodeInfoUpdate(int flags) {
|
|
||||||
int validFlags = flags & (RouterInfoPacket.NODE_INFO_TINY_UPDATE_REQUIRED
|
|
||||||
| RouterInfoPacket.NODE_INFO_FULL_UPDATE_REQUIRED);
|
|
||||||
if(validFlags != 0) {
|
|
||||||
pendingNodeInfoUpdateFlags.getAndUpdate(old -> old | validFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean markNodeInfoUpdateSeen(IPv6Address origin, long createTime) {
|
|
||||||
synchronized(seenNodeInfoUpdates) {
|
|
||||||
LinkedHashSet<Long> createTimes = seenNodeInfoUpdates.get(origin);
|
|
||||||
if(createTimes == null) {
|
|
||||||
createTimes = new LinkedHashSet<>();
|
|
||||||
seenNodeInfoUpdates.put(origin, createTimes);
|
|
||||||
}
|
|
||||||
if(!createTimes.add(createTime)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
while(createTimes.size() > NODE_INFO_UPDATE_REPLAY_WINDOW_SIZE) {
|
|
||||||
createTimes.remove(createTimes.iterator().next());
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void removeNodeInfoUpdateWindow(IPv6Address origin) {
|
|
||||||
synchronized(seenNodeInfoUpdates) {
|
|
||||||
seenNodeInfoUpdates.remove(origin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void notifyNodeInfoUpdate(IPv6Address origin, int flags) {
|
|
||||||
for(BiConsumer<IPv6Address,Integer> listener : nodeInfoUpdateListeners) {
|
|
||||||
try {
|
|
||||||
listener.accept(origin, flags);
|
|
||||||
} catch(Throwable e) {
|
|
||||||
if(debug) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Thread.currentThread().setName("KLALB路由协议接收线程");
|
Thread.currentThread().setName("KLALB路由协议接收线程");
|
||||||
@@ -167,17 +108,6 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
selfRouterInfo = getSelfRouterInfo();
|
selfRouterInfo = getSelfRouterInfo();
|
||||||
RouterInfo oslf=netmap.put(selfRouterInfo.getLocator().getAddress(), selfRouterInfo);
|
RouterInfo oslf=netmap.put(selfRouterInfo.getLocator().getAddress(), selfRouterInfo);
|
||||||
noticeUpdate();
|
noticeUpdate();
|
||||||
int nodeInfoUpdateFlags = pendingNodeInfoUpdateFlags.getAndSet(0);
|
|
||||||
if(nodeInfoUpdateFlags != 0) {
|
|
||||||
RouterInfoPacket updatePacket = new RouterInfoPacket(getSelfRouterInfo(), true, -1);
|
|
||||||
updatePacket.setNodeInfoUpdateFlags(nodeInfoUpdateFlags);
|
|
||||||
try {
|
|
||||||
floodPacket(null, updatePacket);
|
|
||||||
} catch(IOException e) {
|
|
||||||
pendingNodeInfoUpdateFlags.getAndUpdate(old -> old | nodeInfoUpdateFlags);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*if(oslf==null||(!selfRouterInfo.equals(oslf))) {
|
/*if(oslf==null||(!selfRouterInfo.equals(oslf))) {
|
||||||
long cur=System.nanoTime();
|
long cur=System.nanoTime();
|
||||||
if(cur-floodTimer2>5000000000L) {
|
if(cur-floodTimer2>5000000000L) {
|
||||||
@@ -218,10 +148,8 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
timeout=2000000000L;
|
timeout=2000000000L;
|
||||||
}
|
}
|
||||||
if(val.checkTimeOut(timeout)) {
|
if(val.checkTimeOut(timeout)) {
|
||||||
if(netmap.remove(type.getKey(), val)) {
|
iterator.remove();
|
||||||
removeNodeInfoUpdateWindow(type.getKey());
|
noticeUpdate();
|
||||||
noticeUpdate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/*List<NeighborInfo> ads=val.getNeighborAddresses();
|
/*List<NeighborInfo> ads=val.getNeighborAddresses();
|
||||||
for (Iterator<NeighborInfo> iterator2 = ads.iterator(); iterator2.hasNext();) {
|
for (Iterator<NeighborInfo> iterator2 = ads.iterator(); iterator2.hasNext();) {
|
||||||
@@ -283,12 +211,12 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
while(true) {
|
while(true) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[]ca=MembandBoost.allocateUninitializedArray(65535);
|
byte[]ca=MembandBoost.allocateUninitializedByteArray(65535);
|
||||||
DatagramPacket dgp=new DatagramPacket(ca, ca.length);
|
DatagramPacket dgp=new DatagramPacket(ca, ca.length);
|
||||||
ds.receive(dgp);
|
ds.receive(dgp);
|
||||||
//System.out.println(Arrays.toString( Arrays.copyOf( dgp.getData(),dgp.getLength())));
|
//System.out.println(Arrays.toString( Arrays.copyOf( dgp.getData(),dgp.getLength())));
|
||||||
ByteArrayInputStream bi=new ByteArrayInputStream(dgp.getData(),0,dgp.getLength());
|
ByteArrayInputStream bi=new ByteArrayInputStream(dgp.getData(),0,dgp.getLength());
|
||||||
KLALBRoutingProtocolPacket kp=KLALBRoutingProtocolPacket.readKLALBPacketFromChannel(Channels.newChannel(bi), dgp.getLength());
|
KLALBRoutingProtocolPacket kp=KLALBRoutingProtocolPacket.readKLALBPacketFromChannel(Channels.newChannel(bi));
|
||||||
|
|
||||||
switch(kp.getType()) {
|
switch(kp.getType()) {
|
||||||
case KLALBRoutingProtocolPacket.RINFO_REQ:
|
case KLALBRoutingProtocolPacket.RINFO_REQ:
|
||||||
@@ -309,30 +237,24 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
RouterInfoPacket rifp=(RouterInfoPacket) kp;
|
RouterInfoPacket rifp=(RouterInfoPacket) kp;
|
||||||
RouterInfo rif=rifp.getRinfo();
|
RouterInfo rif=rifp.getRinfo();
|
||||||
RouterInfo oldrif=netmap.get(rif.getLocator().getAddress());
|
RouterInfo oldrif=netmap.get(rif.getLocator().getAddress());
|
||||||
IPv6Address origin = rif.getLocator().getAddress();
|
|
||||||
int nodeInfoUpdateFlags = rifp.getNodeInfoUpdateFlags();
|
|
||||||
boolean newNodeInfoUpdate = nodeInfoUpdateFlags != 0
|
|
||||||
&& markNodeInfoUpdateSeen(origin, rif.getCreateTime());
|
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
System.out.println(rif);
|
System.out.println(rif);
|
||||||
boolean topologyUpdated = oldrif==null||oldrif.getCreateTime()<rif.getCreateTime();
|
if(oldrif==null||oldrif.getCreateTime()<rif.getCreateTime()) {
|
||||||
if(topologyUpdated) {
|
|
||||||
if(debug)
|
if(debug)
|
||||||
System.out.println("update RouterInfo");
|
System.out.println("update RouterInfo");
|
||||||
netmap.put(rif.getLocator().getAddress(), rif);
|
netmap.put(rif.getLocator().getAddress(), rif);
|
||||||
noticeUpdate();
|
noticeUpdate();
|
||||||
|
if(rifp.isFlood()) {
|
||||||
|
floodPacket( dgp.getSocketAddress(), rifp);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}else {
|
}else {
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
System.out.println("dispose RouterInfo");
|
System.out.println("dispose RouterInfo");
|
||||||
}
|
}
|
||||||
if(newNodeInfoUpdate) {
|
|
||||||
notifyNodeInfoUpdate(origin, nodeInfoUpdateFlags);
|
|
||||||
}
|
|
||||||
if(rifp.isFlood() && (topologyUpdated || newNodeInfoUpdate)) {
|
|
||||||
floodPacket(dgp.getSocketAddress(), rifp);
|
|
||||||
}
|
|
||||||
computeShortestPathIfUpdated();
|
computeShortestPathIfUpdated();
|
||||||
break;
|
break;
|
||||||
case KLALBRoutingProtocolPacket.JSON_DATA:
|
case KLALBRoutingProtocolPacket.JSON_DATA:
|
||||||
@@ -395,7 +317,6 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
}catch(BindException e) {
|
}catch(BindException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
System.err.println("Cannot assign:"+dest);
|
System.err.println("Cannot assign:"+dest);
|
||||||
throw e;
|
|
||||||
}finally {
|
}finally {
|
||||||
sendLock.unlock();
|
sendLock.unlock();
|
||||||
}
|
}
|
||||||
@@ -627,9 +548,8 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
private RouterInfo getSelfRouterInfo() {
|
private RouterInfo getSelfRouterInfo() {
|
||||||
List<IPv6NetworkLink>links=router.getLinkTabel();
|
List<IPv6NetworkLink>links=router.getLinkTabel();
|
||||||
Object[] nls=links.toArray();
|
Object[] nls=links.toArray();
|
||||||
long currentTime = System.currentTimeMillis();
|
RouterInfo ri=new RouterInfo(System.currentTimeMillis(),router.getLocator(),router.getASN());
|
||||||
long createTime = selfCreateTime.updateAndGet(previous -> Math.max(currentTime, previous + 1));
|
ri.setDeviceName(router.getDeviceName());
|
||||||
RouterInfo ri=new RouterInfo(createTime,router.getLocator(),router.getASN());
|
|
||||||
for(int i=0;i<nls.length;i++) {
|
for(int i=0;i<nls.length;i++) {
|
||||||
IPv6NetworkLink nl=(IPv6NetworkLink) nls[i];
|
IPv6NetworkLink nl=(IPv6NetworkLink) nls[i];
|
||||||
if((!nl.isLoopBack())&&nl.isUp()) {
|
if((!nl.isLoopBack())&&nl.isUp()) {
|
||||||
@@ -685,6 +605,12 @@ public class KLALBRoutingProtocol extends Thread{
|
|||||||
* 查询某地址广播的设备名称(未知返回null)
|
* 查询某地址广播的设备名称(未知返回null)
|
||||||
*/
|
*/
|
||||||
public String getDeviceName(IPv6Address address) {
|
public String getDeviceName(IPv6Address address) {
|
||||||
|
RouterInfo ri=netmap.get(address);
|
||||||
|
if(ri!=null) {
|
||||||
|
String dn=ri.getDeviceName();
|
||||||
|
if(dn!=null&&!dn.isEmpty())
|
||||||
|
return dn;
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
public Map<IPv6Address, List<LinkDirection>> getPaths() {
|
public Map<IPv6Address, List<LinkDirection>> getPaths() {
|
||||||
|
|||||||
@@ -3,19 +3,16 @@ package org.kne.cloud.network.srv6;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.Cleaner;
|
import java.lang.ref.Cleaner;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
import org.kne.cloud.network.MultiProtocolSocketAddress;
|
||||||
import org.kne.cloud.network.congestion.NOCongestionAlgorithm;
|
import org.kne.cloud.network.congestion.NOCongestionAlgorithm;
|
||||||
import org.kne.cloud.network.congestion.SendPacketSlidingWindow;
|
import org.kne.cloud.network.congestion.SendPacketSlidingWindow;
|
||||||
import org.kne.cloud.network.klalb.SendItem;
|
|
||||||
import org.kne.opencl64.Releaser;
|
import org.kne.opencl64.Releaser;
|
||||||
|
|
||||||
public class KLALBRoutingProtocolAPIClient {
|
public class KLALBRoutingProtocolAPIClient {
|
||||||
@@ -27,105 +24,37 @@ public class KLALBRoutingProtocolAPIClient {
|
|||||||
|
|
||||||
private BiConsumer<SocketAddress, JsonDataPacket> rec = (addr, data) -> {
|
private BiConsumer<SocketAddress, JsonDataPacket> rec = (addr, data) -> {
|
||||||
KLALBRoutingProtocolJsonData dataobj = data.getDecodedData();
|
KLALBRoutingProtocolJsonData dataobj = data.getDecodedData();
|
||||||
|
InetSocketAddress addrs = (InetSocketAddress) addr;
|
||||||
UUID ruid = dataobj.getUuid();
|
UUID ruid = dataobj.getUuid();
|
||||||
|
JsonDataPacket relate = null;
|
||||||
|
//System.out.println(ruid + " " + window.getSendmap());
|
||||||
switch (dataobj.getType()) {
|
switch (dataobj.getType()) {
|
||||||
case KLALBRoutingProtocolJsonData.NODE_PROFILE_RESP:
|
case KLALBRoutingProtocolJsonData.NODE_INFO_FULL_RESP:
|
||||||
PendingRequest profileRequest = acknowledgeResponse(ruid,
|
case KLALBRoutingProtocolJsonData.NODE_INFO_TINY_RESP:
|
||||||
KLALBRoutingProtocolJsonData.NODE_PROFILE_REQ, addr);
|
|
||||||
if (profileRequest != null) {
|
|
||||||
((Consumer<NodeProfile>) profileRequest.callback)
|
|
||||||
.accept(new NodeProfile(dataobj.getDeviceName(), dataobj.getDeviceDescription()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KLALBRoutingProtocolJsonData.NODE_EXTERNAL_ENDPOINTS_RESP:
|
|
||||||
PendingRequest endpointsRequest = acknowledgeResponse(ruid,
|
|
||||||
KLALBRoutingProtocolJsonData.NODE_EXTERNAL_ENDPOINTS_REQ, addr);
|
|
||||||
if (endpointsRequest != null) {
|
|
||||||
((Consumer<ExternalEndpointsResult>) endpointsRequest.callback).accept(
|
|
||||||
new ExternalEndpointsResult(decodeExternalEndpoints(dataobj.getData()), dataobj.getStatus()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KLALBRoutingProtocolJsonData.NODE_EXTRA_ROUTES_RESP:
|
|
||||||
PendingRequest routesRequest = acknowledgeResponse(ruid,
|
|
||||||
KLALBRoutingProtocolJsonData.NODE_EXTRA_ROUTES_REQ, addr);
|
|
||||||
if (routesRequest != null) {
|
|
||||||
((Consumer<ExtraRoutesResult>) routesRequest.callback).accept(
|
|
||||||
new ExtraRoutesResult(decodeExtraRoutes(dataobj.getData()), dataobj.getStatus()));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private PendingRequest acknowledgeResponse(UUID uuid, String expectedRequestType, SocketAddress sourceAddress) {
|
if ((relate = window.ack(ruid)) != null) {
|
||||||
SendItem<JsonDataPacket> pending = window.getSendmap().get(uuid);
|
List<?> connects = (List<?>) dataobj.getData();
|
||||||
if (pending == null) {
|
List<MultiProtocolSocketAddress> connectsm = new ArrayList<MultiProtocolSocketAddress>(
|
||||||
return null;
|
connects == null ? 0 : connects.size());
|
||||||
}
|
if (connects != null) {
|
||||||
KLALBRoutingProtocolJsonData request = pending.getPacket().getDecodedData();
|
for (Object open : connects) {
|
||||||
if (request == null || !expectedRequestType.equals(request.getType())) {
|
if (open instanceof MultiProtocolSocketAddress) {
|
||||||
return null;
|
connectsm.add((MultiProtocolSocketAddress) open);
|
||||||
}
|
} else {
|
||||||
Object callback = pending.getPacket().getUserCallback();
|
connectsm.add(new MultiProtocolSocketAddress((String) open));
|
||||||
if (!(callback instanceof PendingRequest)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
PendingRequest pendingRequest = (PendingRequest) callback;
|
|
||||||
if (!expectedRequestType.equals(pendingRequest.expectedRequestType)
|
|
||||||
|| !sameDestination(pendingRequest.expectedDestination, sourceAddress)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return window.ack(uuid) == null ? null : pendingRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean sameDestination(SocketAddress expected, SocketAddress actual) {
|
}
|
||||||
if (expected instanceof InetSocketAddress && actual instanceof InetSocketAddress) {
|
}
|
||||||
InetSocketAddress expectedInet = (InetSocketAddress) expected;
|
|
||||||
InetSocketAddress actualInet = (InetSocketAddress) actual;
|
|
||||||
if (expectedInet.getPort() != actualInet.getPort()) return false;
|
|
||||||
InetAddress expectedAddress = expectedInet.getAddress();
|
|
||||||
InetAddress actualAddress = actualInet.getAddress();
|
|
||||||
if (expectedAddress != null && actualAddress != null) return expectedAddress.equals(actualAddress);
|
|
||||||
if (expectedAddress == null && actualAddress == null) {
|
|
||||||
return expectedInet.getHostString().equalsIgnoreCase(actualInet.getHostString());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return expected != null && expected.equals(actual);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<MultiProtocolSocketAddress> decodeExternalEndpoints(Object data) {
|
|
||||||
if (!(data instanceof List<?>)) {
|
|
||||||
return new ArrayList<MultiProtocolSocketAddress>();
|
|
||||||
}
|
|
||||||
List<?> encoded = (List<?>) data;
|
|
||||||
List<MultiProtocolSocketAddress> endpoints = new ArrayList<MultiProtocolSocketAddress>(encoded.size());
|
|
||||||
for (Object value : encoded) {
|
|
||||||
if (value instanceof MultiProtocolSocketAddress) {
|
|
||||||
endpoints.add((MultiProtocolSocketAddress) value);
|
|
||||||
} else if (value instanceof String) {
|
|
||||||
try {
|
|
||||||
endpoints.add(new MultiProtocolSocketAddress((String) value));
|
|
||||||
} catch (RuntimeException ignored) {
|
|
||||||
// Ignore malformed entries while preserving the rest of the response.
|
|
||||||
}
|
}
|
||||||
|
// 组装节点信息(线路 + 设备名称 + 设备描述,精简模式下线路与描述为 null)
|
||||||
|
KLALBNodeInformation info = new KLALBNodeInformation(connectsm, dataobj.getDeviceName(),
|
||||||
|
dataobj.getDeviceDescription());
|
||||||
|
((Consumer<KLALBNodeInformation>) relate.getUserCallback()).accept(info);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return endpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> decodeExtraRoutes(Object data) {
|
};
|
||||||
if (!(data instanceof List<?>)) {
|
|
||||||
return new ArrayList<String>();
|
|
||||||
}
|
|
||||||
List<?> encoded = (List<?>) data;
|
|
||||||
List<String> routes = new ArrayList<String>(encoded.size());
|
|
||||||
for (Object value : encoded) {
|
|
||||||
if (value instanceof String) {
|
|
||||||
routes.add((String) value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return routes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public KLALBRoutingProtocolAPIClient(KLALBRoutingProtocol routingProtocol) {
|
public KLALBRoutingProtocolAPIClient(KLALBRoutingProtocol routingProtocol) {
|
||||||
this.routingProtocol = routingProtocol;
|
this.routingProtocol = routingProtocol;
|
||||||
@@ -134,29 +63,31 @@ public class KLALBRoutingProtocolAPIClient {
|
|||||||
clr.register(this, releaser);
|
clr.register(this, releaser);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestNodeProfile(SocketAddress addr, Consumer<NodeProfile> callback) throws IOException {
|
/**
|
||||||
sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_PROFILE_REQ, addr, callback);
|
* 精简查询:仅获取对端设备名称(开销最小,适用于未查看节点详情的场景)。
|
||||||
}
|
*/
|
||||||
|
public void requestNodeInfoTiny(SocketAddress addr, Consumer<KLALBNodeInformation> callback)
|
||||||
public void requestExternalEndpoints(SocketAddress addr, Consumer<ExternalEndpointsResult> callback)
|
|
||||||
throws IOException {
|
throws IOException {
|
||||||
sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_EXTERNAL_ENDPOINTS_REQ, addr, callback);
|
sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_INFO_TINY_REQ, addr, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestExtraRoutes(SocketAddress addr, Consumer<ExtraRoutesResult> callback) throws IOException {
|
/**
|
||||||
sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_EXTRA_ROUTES_REQ, addr, callback);
|
* 完整查询:获取对端开放线路 + 设备名称 + 设备描述(查看节点信息时使用)。
|
||||||
|
*/
|
||||||
|
public void requestNodeInfoFull(SocketAddress addr, Consumer<KLALBNodeInformation> callback)
|
||||||
|
throws IOException {
|
||||||
|
sendNodeInfoRequest(KLALBRoutingProtocolJsonData.NODE_INFO_FULL_REQ, addr, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendNodeInfoRequest(String type, SocketAddress addr, Object callback) throws IOException {
|
private void sendNodeInfoRequest(String type, SocketAddress addr, Consumer<KLALBNodeInformation> callback)
|
||||||
|
throws IOException {
|
||||||
UUID suid = UUID.randomUUID();
|
UUID suid = UUID.randomUUID();
|
||||||
KLALBRoutingProtocolJsonData json = new KLALBRoutingProtocolJsonData(type, suid, null);
|
KLALBRoutingProtocolJsonData json = new KLALBRoutingProtocolJsonData(type, suid, null);
|
||||||
JsonDataPacket packet = new JsonDataPacket(json);
|
JsonDataPacket packet = new JsonDataPacket(json);
|
||||||
packet.setUserCallback(new PendingRequest(addr, type, callback));
|
packet.setUserCallback(callback);
|
||||||
synchronized (this) {
|
window.put(suid, packet);
|
||||||
if (closed.get() || releaser.isReleased()) throw new IOException("Node info client is closed");
|
routingProtocol.sendJsonPacketToAddress(packet, addr);
|
||||||
window.put(suid, packet);
|
|
||||||
routingProtocol.sendJsonPacketToAddress(packet, addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public KLALBRoutingProtocol getRoutingProtocol() {
|
public KLALBRoutingProtocol getRoutingProtocol() {
|
||||||
@@ -165,27 +96,13 @@ public class KLALBRoutingProtocolAPIClient {
|
|||||||
|
|
||||||
private KLALBRoutingProtocolAPIClientReleaser releaser;
|
private KLALBRoutingProtocolAPIClientReleaser releaser;
|
||||||
|
|
||||||
public synchronized void close() {
|
public void close() {
|
||||||
if (closed.compareAndSet(false, true)) releaser.run();
|
releaser.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return closed.get() || releaser.isReleased();
|
return releaser.isReleased();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PendingRequest {
|
|
||||||
private final SocketAddress expectedDestination;
|
|
||||||
private final String expectedRequestType;
|
|
||||||
private final Object callback;
|
|
||||||
|
|
||||||
private PendingRequest(SocketAddress expectedDestination, String expectedRequestType, Object callback) {
|
|
||||||
this.expectedDestination = expectedDestination;
|
|
||||||
this.expectedRequestType = expectedRequestType;
|
|
||||||
this.callback = callback;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicBoolean closed = new AtomicBoolean();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class KLALBRoutingProtocolAPIClientReleaser extends Releaser<BiConsumer<SocketAddress, JsonDataPacket>> {
|
class KLALBRoutingProtocolAPIClientReleaser extends Releaser<BiConsumer<SocketAddress, JsonDataPacket>> {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package org.kne.cloud.network.srv6;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.ref.Cleaner;
|
import java.lang.ref.Cleaner;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
import org.kne.cloud.network.klalb.KLALBController;
|
import org.kne.cloud.network.klalb.KLALBController;
|
||||||
@@ -13,52 +13,41 @@ public class KLALBRoutingProtocolAPIServer {
|
|||||||
private KLALBController controller;
|
private KLALBController controller;
|
||||||
private KLALBRoutingProtocol routingProtocol;
|
private KLALBRoutingProtocol routingProtocol;
|
||||||
|
|
||||||
private static final Cleaner clr = Cleaner.create();
|
|
||||||
|
|
||||||
private BiConsumer<SocketAddress, JsonDataPacket> rec = (addr, data) -> {
|
private static final Cleaner clr=Cleaner.create();
|
||||||
|
|
||||||
|
private BiConsumer<SocketAddress, JsonDataPacket> rec=(addr,data)->{
|
||||||
try {
|
try {
|
||||||
KLALBRoutingProtocolJsonData dataobj = data.getDecodedData();
|
KLALBRoutingProtocolJsonData dataobj= data.getDecodedData();
|
||||||
switch (dataobj.getType()) {
|
InetSocketAddress addrs=(InetSocketAddress) addr;
|
||||||
case KLALBRoutingProtocolJsonData.NODE_PROFILE_REQ:
|
switch(dataobj.getType()){
|
||||||
KLALBController.PublishedNodeInfo profilePublished = controller.getPublishedNodeInfo();
|
case KLALBRoutingProtocolJsonData.NODE_INFO_TINY_REQ:
|
||||||
KLALBRoutingProtocolJsonData profile = new KLALBRoutingProtocolJsonData(
|
// 精简查询:仅返回设备名称(设备名称随路由信息广播公开,不受 denyExternalEndpointQuery 限制)
|
||||||
KLALBRoutingProtocolJsonData.NODE_PROFILE_RESP, dataobj.getUuid(), null);
|
KLALBRoutingProtocolJsonData tinyjson=new KLALBRoutingProtocolJsonData(KLALBRoutingProtocolJsonData.NODE_INFO_TINY_RESP,dataobj.getUuid(),null);
|
||||||
profile.setDeviceName(profilePublished.getDeviceName());
|
tinyjson.setDeviceName(controller.getIpv6Router().getDeviceName());
|
||||||
profile.setDeviceDescription(profilePublished.getDeviceDescription());
|
routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(tinyjson),addr);
|
||||||
profile.setStatus(NodeInfoQueryStatus.OK);
|
break;
|
||||||
routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(profile), addr);
|
case KLALBRoutingProtocolJsonData.NODE_INFO_FULL_REQ:
|
||||||
break;
|
// 完整查询:设备名称与描述总是正常响应;denyExternalEndpointQuery 仅隐藏外部端点列表
|
||||||
case KLALBRoutingProtocolJsonData.NODE_EXTERNAL_ENDPOINTS_REQ:
|
boolean denyEndpoints=controller.getConfigItem()!=null&&controller.getConfigItem().isDenyExternalEndpointQuery();
|
||||||
boolean denyEndpoints = controller.getConfigItem() != null
|
KLALBRoutingProtocolJsonData json=new KLALBRoutingProtocolJsonData(KLALBRoutingProtocolJsonData.NODE_INFO_FULL_RESP,dataobj.getUuid(),denyEndpoints?null:controller.getExternalEndpoints());
|
||||||
&& controller.getConfigItem().isDenyExternalEndpointQuery();
|
json.setDeviceName(controller.getIpv6Router().getDeviceName());// 附带本机设备名称
|
||||||
KLALBController.PublishedNodeInfo endpointsPublished = controller.getPublishedNodeInfo();
|
if(controller.getConfigItem()!=null) {
|
||||||
KLALBRoutingProtocolJsonData endpoints = new KLALBRoutingProtocolJsonData(
|
json.setDeviceDescription(controller.getConfigItem().getDeviceDescription());// 附带本机设备描述
|
||||||
KLALBRoutingProtocolJsonData.NODE_EXTERNAL_ENDPOINTS_RESP, dataobj.getUuid(),
|
|
||||||
denyEndpoints ? new ArrayList<org.kne.cloud.network.MultiProtocolSocketAddress>()
|
|
||||||
: new ArrayList<org.kne.cloud.network.MultiProtocolSocketAddress>(
|
|
||||||
endpointsPublished.getExternalEndpoints()));
|
|
||||||
endpoints.setStatus(denyEndpoints ? NodeInfoQueryStatus.DENIED : NodeInfoQueryStatus.OK);
|
|
||||||
routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(endpoints), addr);
|
|
||||||
break;
|
|
||||||
case KLALBRoutingProtocolJsonData.NODE_EXTRA_ROUTES_REQ:
|
|
||||||
KLALBController.PublishedNodeInfo routesPublished = controller.getPublishedNodeInfo();
|
|
||||||
KLALBRoutingProtocolJsonData routes = new KLALBRoutingProtocolJsonData(
|
|
||||||
KLALBRoutingProtocolJsonData.NODE_EXTRA_ROUTES_RESP, dataobj.getUuid(),
|
|
||||||
new ArrayList<String>(routesPublished.getExtraRoutes()));
|
|
||||||
routes.setStatus(NodeInfoQueryStatus.OK);
|
|
||||||
routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(routes), addr);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
routingProtocol.sendJsonPacketToAddress(new JsonDataPacket(json),addr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public KLALBRoutingProtocolAPIServer(KLALBRoutingProtocol routingProtocol, KLALBController controller) {
|
public KLALBRoutingProtocolAPIServer(KLALBRoutingProtocol routingProtocol,KLALBController controller) {
|
||||||
this.controller = controller;
|
this.controller=controller;
|
||||||
this.routingProtocol = routingProtocol;
|
this.routingProtocol=routingProtocol;
|
||||||
routingProtocol.addReceiver(rec);
|
routingProtocol.addReceiver(rec);
|
||||||
this.releaser = new KLALBRoutingProtocolAPIServerReleaser(this.routingProtocol, rec);
|
this.releaser=new KLALBRoutingProtocolAPIServerReleaser(this.routingProtocol,rec);
|
||||||
clr.register(this, releaser);
|
clr.register(this, releaser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,25 +59,26 @@ public class KLALBRoutingProtocolAPIServer {
|
|||||||
return routingProtocol;
|
return routingProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
private KLALBRoutingProtocolAPIServerReleaser releaser;
|
|
||||||
|
private KLALBRoutingProtocolAPIServerReleaser releaser;
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
releaser.run();
|
releaser.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return releaser.isReleased();
|
return releaser.isReleased();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class KLALBRoutingProtocolAPIServerReleaser extends Releaser<BiConsumer<SocketAddress, JsonDataPacket>> {
|
}
|
||||||
|
class KLALBRoutingProtocolAPIServerReleaser extends Releaser<BiConsumer<SocketAddress, JsonDataPacket>>{
|
||||||
|
|
||||||
private KLALBRoutingProtocol routingProtocol;
|
private KLALBRoutingProtocol routingProtocol;
|
||||||
|
|
||||||
public KLALBRoutingProtocolAPIServerReleaser(KLALBRoutingProtocol routingProtocol,
|
public KLALBRoutingProtocolAPIServerReleaser(KLALBRoutingProtocol routingProtocol,BiConsumer<SocketAddress, JsonDataPacket> resource) {
|
||||||
BiConsumer<SocketAddress, JsonDataPacket> resource) {
|
|
||||||
super(resource);
|
super(resource);
|
||||||
this.routingProtocol = routingProtocol;
|
this.routingProtocol=routingProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,89 +1,95 @@
|
|||||||
package org.kne.cloud.network.srv6;
|
package org.kne.cloud.network.srv6;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class KLALBRoutingProtocolJsonData {
|
public class KLALBRoutingProtocolJsonData {
|
||||||
public static final String NODE_PROFILE_REQ = "nodeprofilereq";
|
public static final String NODE_INFO_TINY_REQ="nodeinfotinyreq";// 精简查询:仅设备名称
|
||||||
public static final String NODE_PROFILE_RESP = "nodeprofileresp";
|
public static final String NODE_INFO_TINY_RESP="nodeinfotinyresp";
|
||||||
public static final String NODE_EXTERNAL_ENDPOINTS_REQ = "nodeexternalendpointsreq";
|
public static final String NODE_INFO_FULL_REQ="nodeinfofullreq";// 完整查询:开放线路+设备名称+设备描述
|
||||||
public static final String NODE_EXTERNAL_ENDPOINTS_RESP = "nodeexternalendpointsresp";
|
public static final String NODE_INFO_FULL_RESP="nodeinfofullresp";
|
||||||
public static final String NODE_EXTRA_ROUTES_REQ = "nodeextraroutesreq";
|
|
||||||
public static final String NODE_EXTRA_ROUTES_RESP = "nodeextraroutesresp";
|
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
private UUID uuid;
|
private UUID uuid;
|
||||||
private Object data;
|
private Object data;
|
||||||
private String deviceName;
|
private String deviceName;// 对端设备名称
|
||||||
private String deviceDescription;
|
private String deviceDescription;// 对端设备描述
|
||||||
private NodeInfoQueryStatus status;
|
public String getDeviceName() {
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
public void setDeviceName(String deviceName) {
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
}
|
||||||
|
public String getDeviceDescription() {
|
||||||
|
return deviceDescription;
|
||||||
|
}
|
||||||
|
public void setDeviceDescription(String deviceDescription) {
|
||||||
|
this.deviceDescription = deviceDescription;
|
||||||
|
}
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
public Object getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
public UUID getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((data == null) ? 0 : data.hashCode());
|
||||||
|
result = prime * result + ((type == null) ? 0 : type.hashCode());
|
||||||
|
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
|
||||||
|
result = prime * result + ((deviceName == null) ? 0 : deviceName.hashCode());
|
||||||
|
result = prime * result + ((deviceDescription == null) ? 0 : deviceDescription.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;
|
||||||
|
KLALBRoutingProtocolJsonData other = (KLALBRoutingProtocolJsonData) obj;
|
||||||
|
if (data == null) {
|
||||||
|
if (other.data != null)
|
||||||
|
return false;
|
||||||
|
} else if (!data.equals(other.data))
|
||||||
|
return false;
|
||||||
|
if (type == null) {
|
||||||
|
if (other.type != null)
|
||||||
|
return false;
|
||||||
|
} else if (!type.equals(other.type))
|
||||||
|
return false;
|
||||||
|
if (uuid == null) {
|
||||||
|
if (other.uuid != null)
|
||||||
|
return false;
|
||||||
|
} else if (!uuid.equals(other.uuid))
|
||||||
|
return false;
|
||||||
|
if (deviceName == null) {
|
||||||
|
if (other.deviceName != null)
|
||||||
|
return false;
|
||||||
|
} else if (!deviceName.equals(other.deviceName))
|
||||||
|
return false;
|
||||||
|
if (deviceDescription == null) {
|
||||||
|
if (other.deviceDescription != null)
|
||||||
|
return false;
|
||||||
|
} else if (!deviceDescription.equals(other.deviceDescription))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
public KLALBRoutingProtocolJsonData(String type, UUID uuid, Object data) {
|
public KLALBRoutingProtocolJsonData(String type, UUID uuid, Object data) {
|
||||||
|
super();
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UUID getUuid() {
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object getData() {
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceName() {
|
|
||||||
return deviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceName(String deviceName) {
|
|
||||||
this.deviceName = deviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceDescription() {
|
|
||||||
return deviceDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDeviceDescription(String deviceDescription) {
|
|
||||||
this.deviceDescription = deviceDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
public NodeInfoQueryStatus getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStatus(NodeInfoQueryStatus status) {
|
|
||||||
this.status = status;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(type, uuid, data, deviceName, deviceDescription, status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof KLALBRoutingProtocolJsonData)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
KLALBRoutingProtocolJsonData other = (KLALBRoutingProtocolJsonData) obj;
|
|
||||||
return Objects.equals(type, other.type) && Objects.equals(uuid, other.uuid)
|
|
||||||
&& Objects.equals(data, other.data) && Objects.equals(deviceName, other.deviceName)
|
|
||||||
&& Objects.equals(deviceDescription, other.deviceDescription)
|
|
||||||
&& Objects.equals(status, other.status);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "KLALBRoutingProtocolJsonData [type=" + type + ", uuid=" + uuid + ", data=" + data
|
return "KLALBRoutingProtocolJsonData [type=" + type + ", uuid=" + uuid + ", data=" + data + ", deviceName="
|
||||||
+ ", deviceName=" + deviceName + ", deviceDescription=" + deviceDescription + ", status=" + status
|
+ deviceName + ", deviceDescription=" + deviceDescription + "]";
|
||||||
+ "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,10 +96,6 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static KLALBRoutingProtocolPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException {
|
public static KLALBRoutingProtocolPacket readKLALBPacketFromChannel(ReadableByteChannel in) throws IOException {
|
||||||
return readKLALBPacketFromChannel(in, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KLALBRoutingProtocolPacket readKLALBPacketFromChannel(ReadableByteChannel in, long packetLength) throws IOException {
|
|
||||||
while(true) {
|
while(true) {
|
||||||
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40);
|
ByteBuffer bb=NetworkPacket.bufferAllocator.allocate(40);
|
||||||
bb.limit(1);
|
bb.limit(1);
|
||||||
@@ -115,13 +111,11 @@ public abstract class KLALBRoutingProtocolPacket extends NetworkPacket {
|
|||||||
switch(type) {
|
switch(type) {
|
||||||
case RINFO_REQ:
|
case RINFO_REQ:
|
||||||
klp=new RouterInfoRequestPacket(bb);
|
klp=new RouterInfoRequestPacket(bb);
|
||||||
if(packetLength < 0) klp.readFromChannel(in);
|
klp.readFromChannel(in);
|
||||||
else klp.readFromChannel(in, packetLength);
|
|
||||||
return klp;
|
return klp;
|
||||||
case RINFO:
|
case RINFO:
|
||||||
klp=new RouterInfoPacket(bb);
|
klp=new RouterInfoPacket(bb);
|
||||||
if(packetLength < 0) klp.readFromChannel(in);
|
klp.readFromChannel(in);
|
||||||
else klp.readFromChannel(in, packetLength);
|
|
||||||
return klp;
|
return klp;
|
||||||
case JSON_DATA:
|
case JSON_DATA:
|
||||||
klp=new JsonDataPacket(bb);
|
klp=new JsonDataPacket(bb);
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
package org.kne.cloud.network.srv6;
|
|
||||||
|
|
||||||
public enum NodeInfoQueryStatus {
|
|
||||||
OK,
|
|
||||||
DENIED
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package org.kne.cloud.network.srv6;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public final class NodeProfile {
|
|
||||||
private final String deviceName;
|
|
||||||
private final String deviceDescription;
|
|
||||||
|
|
||||||
public NodeProfile(String deviceName, String deviceDescription) {
|
|
||||||
this.deviceName = deviceName;
|
|
||||||
this.deviceDescription = deviceDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceName() {
|
|
||||||
return deviceName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDeviceDescription() {
|
|
||||||
return deviceDescription;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash(deviceName, deviceDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!(obj instanceof NodeProfile)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
NodeProfile other = (NodeProfile) obj;
|
|
||||||
return Objects.equals(deviceName, other.deviceName)
|
|
||||||
&& Objects.equals(deviceDescription, other.deviceDescription);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "NodeProfile [deviceName=" + deviceName + ", deviceDescription=" + deviceDescription + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -60,6 +60,7 @@ public class RouterInfo implements Serializable{
|
|||||||
return Objects.equals(locator, other.locator) && Objects.equals(neighborAddresses, other.neighborAddresses);
|
return Objects.equals(locator, other.locator) && Objects.equals(neighborAddresses, other.neighborAddresses);
|
||||||
}
|
}
|
||||||
private List<NeighborInfo> neighborAddresses=new ArrayList<>();
|
private List<NeighborInfo> neighborAddresses=new ArrayList<>();
|
||||||
|
private String deviceName=""; // 设备名称(广播时携带,描述不广播)
|
||||||
private long createTime;
|
private long createTime;
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +69,6 @@ public class RouterInfo implements Serializable{
|
|||||||
}
|
}
|
||||||
private static final long INFO_UPDATETIME=10000000000L;
|
private static final long INFO_UPDATETIME=10000000000L;
|
||||||
private static final long INFO_TIMEOUT=60000000000L;
|
private static final long INFO_TIMEOUT=60000000000L;
|
||||||
private static final int MAX_NEIGHBOR_COUNT = 512;
|
|
||||||
private long putTime=System.nanoTime();
|
private long putTime=System.nanoTime();
|
||||||
public boolean checkUpdateTime() {
|
public boolean checkUpdateTime() {
|
||||||
return System.nanoTime()-putTime>INFO_UPDATETIME;
|
return System.nanoTime()-putTime>INFO_UPDATETIME;
|
||||||
@@ -91,6 +91,14 @@ public class RouterInfo implements Serializable{
|
|||||||
return neighborAddresses;
|
return neighborAddresses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getDeviceName() {
|
||||||
|
return deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceName(String deviceName) {
|
||||||
|
this.deviceName = deviceName;
|
||||||
|
}
|
||||||
|
|
||||||
public RouterInfo( long createTime,IPv6AddressGroup locator,long asn) {
|
public RouterInfo( long createTime,IPv6AddressGroup locator,long asn) {
|
||||||
this.createTime = createTime;
|
this.createTime = createTime;
|
||||||
this.locator=locator;
|
this.locator=locator;
|
||||||
@@ -100,19 +108,14 @@ public class RouterInfo implements Serializable{
|
|||||||
public RouterInfo() {
|
public RouterInfo() {
|
||||||
}
|
}
|
||||||
public void writeToStream(DataOutputStream out) throws IOException {
|
public void writeToStream(DataOutputStream out) throws IOException {
|
||||||
int neighborCount = neighborAddresses == null ? -1 : neighborAddresses.size();
|
|
||||||
if(neighborCount<0 || neighborCount>MAX_NEIGHBOR_COUNT) {
|
|
||||||
throw new IOException("Invalid neighbor count: " + neighborCount);
|
|
||||||
}
|
|
||||||
locator.writeToStream(out);
|
locator.writeToStream(out);
|
||||||
out.writeLong(asn);
|
out.writeLong(asn);
|
||||||
out.writeLong(createTime);
|
out.writeLong(createTime);
|
||||||
out.writeInt(neighborCount);
|
out.writeInt(neighborAddresses.size());
|
||||||
for( NeighborInfo neighborInfo :neighborAddresses) {
|
for( NeighborInfo neighborInfo :neighborAddresses) {
|
||||||
neighborInfo.writeToStream(out);
|
neighborInfo.writeToStream(out);
|
||||||
}
|
}
|
||||||
// Keep the legacy UTF slot so older RINFO decoders stay aligned.
|
out.writeUTF(deviceName==null?"":deviceName);
|
||||||
out.writeUTF("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
protected void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||||
@@ -126,9 +129,6 @@ public class RouterInfo implements Serializable{
|
|||||||
asn=in.readLong();
|
asn=in.readLong();
|
||||||
createTime=in.readLong();
|
createTime=in.readLong();
|
||||||
int size=in.readInt();
|
int size=in.readInt();
|
||||||
if(size<0 || size>MAX_NEIGHBOR_COUNT) {
|
|
||||||
throw new IOException("Invalid neighbor count: " + size);
|
|
||||||
}
|
|
||||||
neighborAddresses=new ArrayList<>(size);
|
neighborAddresses=new ArrayList<>(size);
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
NeighborInfo nif=new NeighborInfo();
|
NeighborInfo nif=new NeighborInfo();
|
||||||
@@ -136,8 +136,7 @@ public class RouterInfo implements Serializable{
|
|||||||
neighborAddresses.add(nif);
|
neighborAddresses.add(nif);
|
||||||
|
|
||||||
}
|
}
|
||||||
// Consume the legacy device-name slot; names are no longer broadcast here.
|
deviceName=in.readUTF();
|
||||||
in.readUTF();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.kne.cloud.network.srv6;
|
|||||||
|
|
||||||
import java.io.DataInputStream;
|
import java.io.DataInputStream;
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.Externalizable;
|
import java.io.Externalizable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.ObjectInput;
|
import java.io.ObjectInput;
|
||||||
@@ -24,11 +23,6 @@ import org.kne.cloud.network.NetworkPacket;
|
|||||||
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
import org.kne.cloud.network.ipv6.IPv6AddressGroup;
|
||||||
|
|
||||||
public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Serializable{
|
public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Serializable{
|
||||||
public static final int NODE_INFO_TINY_UPDATE_REQUIRED = 1;
|
|
||||||
public static final int NODE_INFO_FULL_UPDATE_REQUIRED = 2;
|
|
||||||
private static final int NODE_INFO_UPDATE_FLAGS_MASK = NODE_INFO_TINY_UPDATE_REQUIRED
|
|
||||||
| NODE_INFO_FULL_UPDATE_REQUIRED;
|
|
||||||
private static final int NODE_INFO_UPDATE_MAGIC = 0xA5;
|
|
||||||
|
|
||||||
public RouterInfoPacket(RouterInfo routerInfo, boolean flood,long asn) {
|
public RouterInfoPacket(RouterInfo routerInfo, boolean flood,long asn) {
|
||||||
super(RINFO);
|
super(RINFO);
|
||||||
@@ -41,7 +35,6 @@ public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Seri
|
|||||||
}
|
}
|
||||||
|
|
||||||
private RouterInfo rinfo;
|
private RouterInfo rinfo;
|
||||||
private transient int nodeInfoUpdateFlags;
|
|
||||||
|
|
||||||
public boolean isFlood() {
|
public boolean isFlood() {
|
||||||
return (getHeader().get(1)&1)==1;
|
return (getHeader().get(1)&1)==1;
|
||||||
@@ -54,14 +47,6 @@ public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Seri
|
|||||||
public RouterInfo getRinfo() {
|
public RouterInfo getRinfo() {
|
||||||
return rinfo;
|
return rinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNodeInfoUpdateFlags() {
|
|
||||||
return nodeInfoUpdateFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNodeInfoUpdateFlags(int flags) {
|
|
||||||
nodeInfoUpdateFlags = flags & NODE_INFO_UPDATE_FLAGS_MASK;
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
protected long getHeaderSize() {
|
protected long getHeaderSize() {
|
||||||
return super.getHeaderSize()+9;
|
return super.getHeaderSize()+9;
|
||||||
@@ -83,43 +68,12 @@ public class RouterInfoPacket extends KLALBRoutingProtocolPacket implements Seri
|
|||||||
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
public void writeToChannel(WritableByteChannel dto) throws IOException {
|
||||||
super.writeToChannel(dto);
|
super.writeToChannel(dto);
|
||||||
rinfo.writeToChannel(dto);
|
rinfo.writeToChannel(dto);
|
||||||
int flags = nodeInfoUpdateFlags & NODE_INFO_UPDATE_FLAGS_MASK;
|
|
||||||
if(flags != 0) {
|
|
||||||
ByteBuffer extension = ByteBuffer.wrap(new byte[] {(byte) NODE_INFO_UPDATE_MAGIC, (byte) flags});
|
|
||||||
while(extension.hasRemaining()) {
|
|
||||||
dto.write(extension);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
public void readFromChannel(ReadableByteChannel din, long length) throws IOException {
|
||||||
super.readFromChannel(din, length);
|
super.readFromChannel(din, length);
|
||||||
rinfo=new RouterInfo();
|
rinfo=new RouterInfo();
|
||||||
if(length < 0) {
|
rinfo.readFromChannel(din, length);
|
||||||
rinfo.readFromChannel(din, length);
|
|
||||||
nodeInfoUpdateFlags = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long payloadLength = length - getHeaderSize();
|
|
||||||
if(payloadLength < 0 || payloadLength > Integer.MAX_VALUE) {
|
|
||||||
throw new IOException("Invalid RINFO packet length: " + length);
|
|
||||||
}
|
|
||||||
byte[] payload = new byte[(int) payloadLength];
|
|
||||||
ByteBuffer payloadBuffer = ByteBuffer.wrap(payload);
|
|
||||||
while(payloadBuffer.hasRemaining()) {
|
|
||||||
if(din.read(payloadBuffer) == -1) {
|
|
||||||
throw new java.io.EOFException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ByteArrayInputStream payloadInput = new ByteArrayInputStream(payload);
|
|
||||||
rinfo.readFromStream(new DataInputStream(payloadInput));
|
|
||||||
nodeInfoUpdateFlags = 0;
|
|
||||||
int marker = payloadInput.read();
|
|
||||||
int flags = payloadInput.read();
|
|
||||||
int trailing = payloadInput.read();
|
|
||||||
if(marker == NODE_INFO_UPDATE_MAGIC && flags >= 0 && trailing == -1) {
|
|
||||||
nodeInfoUpdateFlags = flags & NODE_INFO_UPDATE_FLAGS_MASK;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package org.kne.cloud.network.srv6;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.kne.cloud.network.ipv6.*;
|
||||||
|
|
||||||
|
public class SRHInsertNetworkLink extends AbstractIPv6NetworkLink {
|
||||||
|
|
||||||
|
private IPv6AddressGroup ipgroup;
|
||||||
|
|
||||||
|
public SRHInsertNetworkLink(SRv6Router sRv6Router,IPv6AddressGroup ipgroup) {
|
||||||
|
super(false);
|
||||||
|
setSRv6Router(sRv6Router);
|
||||||
|
this.ipgroup=ipgroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IPv6AddressGroup> getAddressGroups() {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Neighbor> getNeighborsInfo() {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendPacket(IPv6Packet pack, IPv6Address inet6Address) throws IOException {
|
||||||
|
getSrv6Router().insertSRHeader( pack);
|
||||||
|
getSrv6Router().insertHeaderAndRoutePacket(null, pack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RouteItem> getRouteItems() {
|
||||||
|
return List.of(new RouteItem(ipgroup, null, this, RouteItem.KLALB_SRv6, 30, 0,"G"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "SRHInsertNetworkLink";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUp() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -60,7 +60,7 @@ public class SRv6Router {
|
|||||||
|
|
||||||
// public static final int MTU = 16384;
|
// public static final int MTU = 16384;
|
||||||
public static final int MTU = 16384; // 最大传输单元
|
public static final int MTU = 16384; // 最大传输单元
|
||||||
public static final int MAX_REROUTE_COUNT = 2;// 1 // 最大重路由次数
|
public static final int MAX_REROUTE_COUNT = 2;// 最大重路由次数
|
||||||
|
|
||||||
private static final int IPv6_BITS = 128; // IPv6地址位数
|
private static final int IPv6_BITS = 128; // IPv6地址位数
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ public class SRv6Router {
|
|||||||
|
|
||||||
// 环回网络链路
|
// 环回网络链路
|
||||||
private final LoopbackIPv6NetworkLink inLoopBack;
|
private final LoopbackIPv6NetworkLink inLoopBack;
|
||||||
|
private final SRHInsertNetworkLink srhInserter;
|
||||||
// 获取路由表
|
// 获取路由表
|
||||||
public List<RouteItem> getRouteTabel() {
|
public List<RouteItem> getRouteTabel() {
|
||||||
return routeTabel;
|
return routeTabel;
|
||||||
@@ -121,7 +121,7 @@ public class SRv6Router {
|
|||||||
@Override
|
@Override
|
||||||
public void accept(IPv6Packet t) {
|
public void accept(IPv6Packet t) {
|
||||||
// HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
// HighPerformanceExecutor.defaultExecutor.execute(() -> {
|
||||||
routePacket(null, t, true); // 执行重路由
|
routePacket(null, t); // 执行重路由
|
||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -142,21 +142,11 @@ public class SRv6Router {
|
|||||||
if (oamtlv == null)
|
if (oamtlv == null)
|
||||||
return true;
|
return true;
|
||||||
boolean bool = unduplicateSet.add(oamtlv.getUUID());
|
boolean bool = unduplicateSet.add(oamtlv.getUUID());
|
||||||
// System.out.println(bool);
|
|
||||||
return 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>>() {
|
private BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>> receiveConsumer = new BiConsumer<IPv6NetworkLink, Supplier<IPv6Packet>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(IPv6NetworkLink link, Supplier<IPv6Packet> pack) {
|
public void accept(IPv6NetworkLink link, Supplier<IPv6Packet> pack) {
|
||||||
@@ -255,7 +245,7 @@ public class SRv6Router {
|
|||||||
|
|
||||||
nlink.setSRv6Router(this);
|
nlink.setSRv6Router(this);
|
||||||
nlink.addIPv6LinkStateListener(listener); // 添加链路状态监听器
|
nlink.addIPv6LinkStateListener(listener); // 添加链路状态监听器
|
||||||
nlink.setReceiveConsumer(srhReceive); // 设置接收处理器
|
nlink.setReceiveConsumer(receiveConsumer); // 设置接收处理器
|
||||||
if (nlink instanceof ControlledIPv6NetworkLink) {
|
if (nlink instanceof ControlledIPv6NetworkLink) {
|
||||||
((ControlledIPv6NetworkLink) nlink).setRerouteConsumer(defaultReroute); // 设置重路由处理器
|
((ControlledIPv6NetworkLink) nlink).setRerouteConsumer(defaultReroute); // 设置重路由处理器
|
||||||
((ControlledIPv6NetworkLink) nlink).setCongressCondition(congressLock, congressCondition); // 设置拥塞条件
|
((ControlledIPv6NetworkLink) nlink).setCongressCondition(congressLock, congressCondition); // 设置拥塞条件
|
||||||
@@ -323,9 +313,9 @@ public class SRv6Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 插入SRH并路由数据包
|
// 插入SRH并路由数据包
|
||||||
public void insertSRHandRoutePacket(IPv6NetworkLink link, IPv6Packet ipp) {
|
public void insertHeaderAndRoutePacket(IPv6NetworkLink link, IPv6Packet ipp) {
|
||||||
insertHopByHopHeader(ipp);
|
insertHopByHopHeader(ipp);//插入逐跳头
|
||||||
insertSRHeader(ipp); // 插入段路由头
|
//insertSRHeader(ipp); // 插入段路由头
|
||||||
routePacket(link, ipp); // 路由数据包
|
routePacket(link, ipp); // 路由数据包
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,16 +374,13 @@ public class SRv6Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void routePacket(IPv6Packet iPv6Packet) {
|
private void routePacket(IPv6Packet iPv6Packet) {
|
||||||
routePacket(null, iPv6Packet, false);
|
routePacket(null, iPv6Packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 路由数据包(默认非重路由)
|
|
||||||
private void routePacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet) {
|
|
||||||
routePacket(linkfrom, iPv6Packet, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 路由数据包主方法
|
// 路由数据包主方法
|
||||||
private void routePacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, boolean reroute) {
|
private void routePacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet) {
|
||||||
StringBuilder dbg = null;
|
StringBuilder dbg = null;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
dbg = new StringBuilder(); // 调试信息
|
dbg = new StringBuilder(); // 调试信息
|
||||||
@@ -406,7 +393,7 @@ public class SRv6Router {
|
|||||||
List<RouteItem> searchResult = getTabelByAddress(dest);
|
List<RouteItem> searchResult = getTabelByAddress(dest);
|
||||||
if (searchResult!=null&&(!searchResult.isEmpty())) {
|
if (searchResult!=null&&(!searchResult.isEmpty())) {
|
||||||
// 匹配到路由表,执行负载均衡路由
|
// 匹配到路由表,执行负载均衡路由
|
||||||
routingLoadBalance(linkfrom, iPv6Packet, reroute, dbg, searchResult);
|
routingLoadBalance(linkfrom, iPv6Packet, dbg, searchResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,7 +428,7 @@ public class SRv6Router {
|
|||||||
// 重新搜索路由表
|
// 重新搜索路由表
|
||||||
List<RouteItem> searchResult2 = getTabelByAddress(dest);
|
List<RouteItem> searchResult2 = getTabelByAddress(dest);
|
||||||
if (searchResult2!=null&&(!searchResult2.isEmpty())) {
|
if (searchResult2!=null&&(!searchResult2.isEmpty())) {
|
||||||
routingLoadBalance(linkfrom, iPv6Packet, reroute, dbg, searchResult2);
|
routingLoadBalance(linkfrom, iPv6Packet, dbg, searchResult2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +495,7 @@ public class SRv6Router {
|
|||||||
private Condition congressCondition = congressLock.newCondition(); // 拥塞条件
|
private Condition congressCondition = congressLock.newCondition(); // 拥塞条件
|
||||||
|
|
||||||
// 负载均衡路由
|
// 负载均衡路由
|
||||||
private boolean routingLoadBalance(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, boolean reroute,
|
private boolean routingLoadBalance(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet,
|
||||||
StringBuilder dbg, List<RouteItem> routes) throws IllegalRawDataException, IOException {
|
StringBuilder dbg, List<RouteItem> routes) throws IllegalRawDataException, IOException {
|
||||||
|
|
||||||
if(routes==null||routes.isEmpty()) {
|
if(routes==null||routes.isEmpty()) {
|
||||||
@@ -517,7 +504,7 @@ public class SRv6Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (double i = 1; i < 100; i += 0.1) {
|
for (double i = 1; i < 100; i += 0.1) {
|
||||||
if (loadBalance(linkfrom, iPv6Packet, reroute, dbg, routes, i)) {
|
if (loadBalance(linkfrom, iPv6Packet, dbg, routes, i)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -536,7 +523,7 @@ public class SRv6Router {
|
|||||||
return false; // 路由失败
|
return false; // 路由失败
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean loadBalance(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, boolean reroute, StringBuilder dbg,
|
private boolean loadBalance(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, StringBuilder dbg,
|
||||||
List<RouteItem> routes, double cscale)
|
List<RouteItem> routes, double cscale)
|
||||||
throws IllegalRawDataException, IOException {
|
throws IllegalRawDataException, IOException {
|
||||||
// 遍历可用路由进行负载均衡
|
// 遍历可用路由进行负载均衡
|
||||||
@@ -564,31 +551,39 @@ public class SRv6Router {
|
|||||||
dbg.append("matched.\n");
|
dbg.append("matched.\n");
|
||||||
}
|
}
|
||||||
// 找到可用链路,处理数据包
|
// 找到可用链路,处理数据包
|
||||||
processPacket(linkfrom, iPv6Packet, tri, reroute);
|
processPacket(linkfrom, iPv6Packet, tri);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理数据包转发
|
// 处理数据包转发
|
||||||
private void processPacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, RouteItem ri, boolean reroute)
|
private void processPacket(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, RouteItem ri)
|
||||||
throws IllegalRawDataException, IOException {
|
throws IllegalRawDataException, IOException {
|
||||||
int hop = iPv6Packet.getHopLimit();
|
int hop = iPv6Packet.getHopLimit();
|
||||||
|
|
||||||
if (ri.getDestlink().isLoopBack()) { // 环回链路处理
|
if (ri.getDestlink().isLoopBack()) { // 环回链路处理
|
||||||
|
IPv6HopByHopHeader iPv6HopByHopHeader=iPv6Packet.getHopByHopHeader();
|
||||||
|
if(iPv6Packet.getRouteCounter().get()<=0) {
|
||||||
|
if (iPv6HopByHopHeader != null&&linkfrom instanceof KLALBRemoteLink) {
|
||||||
|
processKLALBOAM(iPv6Packet, linkfrom.getAddressGroups().get(0).getAddress(),
|
||||||
|
((KLALBRemoteLink) linkfrom).getRemoteVaddr().getAddress(), iPv6HopByHopHeader);
|
||||||
|
}
|
||||||
|
}
|
||||||
IPv6SegmentRoutingHeader srhh = iPv6Packet.getSegmentRoutingHeader();
|
IPv6SegmentRoutingHeader srhh = iPv6Packet.getSegmentRoutingHeader();
|
||||||
if (srhh != null) {
|
if (srhh != null) {
|
||||||
processSRv6Packet(linkfrom, iPv6Packet, ri, srhh, iPv6Packet.getHopByHopHeader(), reroute); // SRv6特殊处理
|
processSRv6Packet(linkfrom, iPv6Packet, ri, srhh); // SRv6特殊处理
|
||||||
} else {
|
} else {
|
||||||
sendPacketToRouteItem(iPv6Packet, ri);
|
sendPacketToRouteItem(iPv6Packet, ri);
|
||||||
}
|
}
|
||||||
} else { // 普通链路处理
|
} else { // 普通链路处理
|
||||||
// 检查重路由计数
|
// 检查重路由计数
|
||||||
if (iPv6Packet.getRerouteCounter().getAndIncrement() >= MAX_REROUTE_COUNT) {
|
int count=iPv6Packet.getRouteCounter().getAndIncrement();
|
||||||
|
if (count >= MAX_REROUTE_COUNT) {
|
||||||
return; // 超过最大重路由次数,丢弃
|
return; // 超过最大重路由次数,丢弃
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reroute) {
|
if (count<=0) {
|
||||||
hop--; // 减少TTL(非重路由时)
|
hop--; // 减少TTL(非重路由时)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,34 +646,16 @@ public class SRv6Router {
|
|||||||
|
|
||||||
// 处理SRv6数据包
|
// 处理SRv6数据包
|
||||||
private void processSRv6Packet(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, RouteItem ri,
|
private void processSRv6Packet(IPv6NetworkLink linkfrom, IPv6Packet iPv6Packet, RouteItem ri,
|
||||||
IPv6SegmentRoutingHeader srhh, IPv6HopByHopHeader iPv6HopByHopHeader, boolean reroute)
|
IPv6SegmentRoutingHeader srhh)
|
||||||
throws IllegalRawDataException, IOException {
|
throws IllegalRawDataException, IOException {
|
||||||
|
|
||||||
|
|
||||||
if (srhh.getSegmentsLeft() <= 0) { // 所有段已处理完毕
|
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);
|
sendPacketToRouteItem(iPv6Packet, ri);
|
||||||
} else {
|
} else {
|
||||||
if (reroute) {
|
if (iPv6Packet.getRouteCounter().get()<=0) {
|
||||||
// 重路由处理
|
// 重路由不处理
|
||||||
} else {
|
|
||||||
int oldSL = srhh.getSegmentsLeft();
|
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处理:移动到下一个段
|
// 正常SRv6处理:移动到下一个段
|
||||||
int newSL = oldSL - 1;
|
int newSL = oldSL - 1;
|
||||||
srhh.setSegmentsLeft(newSL); // 更新剩余段数
|
srhh.setSegmentsLeft(newSL); // 更新剩余段数
|
||||||
@@ -687,7 +664,7 @@ public class SRv6Router {
|
|||||||
// 记录热点地址(用于流量工程)
|
// 记录热点地址(用于流量工程)
|
||||||
if (iPv6Packet.getPayload().getProtocolNumber() != KLALBRoutingProtocol.DEFAULT_PROTOCOL_NUMBER)
|
if (iPv6Packet.getPayload().getProtocolNumber() != KLALBRoutingProtocol.DEFAULT_PROTOCOL_NUMBER)
|
||||||
klalbRouteProtol.putHotspotAddress(iPv6Packet.getSourceAddress());
|
klalbRouteProtol.putHotspotAddress(iPv6Packet.getSourceAddress());
|
||||||
routePacket(linkfrom, iPv6Packet, reroute); // 继续路由
|
routePacket(linkfrom, iPv6Packet); // 继续路由
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -814,7 +791,7 @@ public class SRv6Router {
|
|||||||
if(ecn) {
|
if(ecn) {
|
||||||
packet.markCE();
|
packet.markCE();
|
||||||
}
|
}
|
||||||
insertSRHandRoutePacket(null, packet); // 插入SRH并路由
|
insertHeaderAndRoutePacket(null, packet); // 插入SRH并路由
|
||||||
long time=System.nanoTime()-start;
|
long time=System.nanoTime()-start;
|
||||||
backplaneCount(time,ecn);
|
backplaneCount(time,ecn);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -827,7 +804,7 @@ public class SRv6Router {
|
|||||||
|
|
||||||
public void onReceive(IPv6NetworkLink link,IPv6Packet t){
|
public void onReceive(IPv6NetworkLink link,IPv6Packet t){
|
||||||
if (unduplicate(t)) {
|
if (unduplicate(t)) {
|
||||||
insertSRHandRoutePacket(link, t); // 插入SRH并路由数据包
|
insertHeaderAndRoutePacket(link, t); // 插入SRH并路由数据包
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -916,15 +893,17 @@ public class SRv6Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 构造函数
|
// 构造函数
|
||||||
public SRv6Router(IPv6AddressGroup hostAddress, HighAccuracyClock clock) {
|
public SRv6Router(IPv6AddressGroup endSID,IPv6AddressGroup networkGroup, HighAccuracyClock clock) {
|
||||||
super();
|
super();
|
||||||
this.locator = hostAddress;
|
this.locator = endSID;
|
||||||
this.clock = clock;
|
this.clock = clock;
|
||||||
// initWorkerThreads();
|
// initWorkerThreads();
|
||||||
// 创建环回链路
|
// 创建环回链路
|
||||||
this.inLoopBack = new LoopbackIPv6NetworkLink(
|
this.inLoopBack = new LoopbackIPv6NetworkLink(
|
||||||
List.of(new IPv6AddressGroup(IPv6Address.LOOPBACK, 128), hostAddress), this);
|
List.of(new IPv6AddressGroup(IPv6Address.LOOPBACK, 128), endSID), this);
|
||||||
linkTabel.add(inLoopBack); // 添加到链路表
|
linkTabel.add(inLoopBack); // 添加到链路表
|
||||||
|
this.srhInserter=new SRHInsertNetworkLink(this,networkGroup);
|
||||||
|
linkTabel.add(srhInserter);
|
||||||
backplaneTimer.scheduleAtFixedRate(new TimerTask() {
|
backplaneTimer.scheduleAtFixedRate(new TimerTask() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user