mirror of https://github.com/jetkvm/kvm.git
feat(lldp): implement rx
This commit is contained in:
parent
1674a6666c
commit
748bfe5477
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "JetKVM",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1-1.23-bookworm",
|
||||
"image": "mcr.microsoft.com/devcontainers/go:1-1.24-bookworm",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
// Should match what is defined in ui/package.json
|
||||
|
|
26
Makefile
26
Makefile
|
@ -8,6 +8,9 @@ VERSION := 0.4.4
|
|||
PROMETHEUS_TAG := github.com/prometheus/common/version
|
||||
KVM_PKG_NAME := github.com/jetkvm/kvm
|
||||
|
||||
BUILDKIT_FLAVOR := arm-rockchip830-linux-uclibcgnueabihf
|
||||
BUILDKIT_PATH ?= /opt/jetkvm-native-buildkit
|
||||
|
||||
GO_BUILD_ARGS := -tags netgo
|
||||
GO_RELEASE_BUILD_ARGS := -trimpath $(GO_BUILD_ARGS)
|
||||
GO_LDFLAGS := \
|
||||
|
@ -17,7 +20,19 @@ GO_LDFLAGS := \
|
|||
-X $(PROMETHEUS_TAG).Revision=$(REVISION) \
|
||||
-X $(KVM_PKG_NAME).builtTimestamp=$(BUILDTS)
|
||||
|
||||
GO_CMD := GOOS=linux GOARCH=arm GOARM=7 go
|
||||
GO_ARGS := GOOS=linux GOARCH=arm GOARM=7
|
||||
# if BUILDKIT_PATH exists, use buildkit to build
|
||||
ifneq ($(wildcard $(BUILDKIT_PATH)),)
|
||||
GO_ARGS := $(GO_ARGS) \
|
||||
CGO_CFLAGS="-I$(BUILDKIT_PATH)/$(BUILDKIT_FLAVOR)/include -I$(BUILDKIT_PATH)/$(BUILDKIT_FLAVOR)/sysroot/usr/include" \
|
||||
CGO_LDFLAGS="-L$(BUILDKIT_PATH)/$(BUILDKIT_FLAVOR)/lib -L$(BUILDKIT_PATH)/$(BUILDKIT_FLAVOR)/sysroot/usr/lib" \
|
||||
CC="$(BUILDKIT_PATH)/bin/$(BUILDKIT_FLAVOR)-gcc" \
|
||||
LD="$(BUILDKIT_PATH)/bin/$(BUILDKIT_FLAVOR)-ld" \
|
||||
CGO_ENABLED=1
|
||||
endif
|
||||
|
||||
GO_CMD := $(GO_ARGS) go
|
||||
|
||||
BIN_DIR := $(shell pwd)/bin
|
||||
|
||||
TEST_DIRS := $(shell find . -name "*_test.go" -type f -exec dirname {} \; | sort -u)
|
||||
|
@ -32,6 +47,13 @@ build_dev: hash_resource
|
|||
$(GO_RELEASE_BUILD_ARGS) \
|
||||
-o $(BIN_DIR)/jetkvm_app cmd/main.go
|
||||
|
||||
build_afpacket:
|
||||
@echo "Building..."
|
||||
$(GO_CMD) build \
|
||||
-ldflags="$(GO_LDFLAGS) -X $(KVM_PKG_NAME).builtAppVersion=$(VERSION_DEV)" \
|
||||
$(GO_RELEASE_BUILD_ARGS) \
|
||||
-o $(BIN_DIR)/afpacket internal/lldp/cmd/afp.go
|
||||
|
||||
build_test2json:
|
||||
$(GO_CMD) build -o $(BIN_DIR)/test2json cmd/test2json
|
||||
|
||||
|
@ -86,4 +108,4 @@ release:
|
|||
@echo "Uploading release..."
|
||||
@shasum -a 256 bin/jetkvm_app | cut -d ' ' -f 1 > bin/jetkvm_app.sha256
|
||||
rclone copyto bin/jetkvm_app r2://jetkvm-update/app/$(VERSION)/jetkvm_app
|
||||
rclone copyto bin/jetkvm_app.sha256 r2://jetkvm-update/app/$(VERSION)/jetkvm_app.sha256
|
||||
rclone copyto bin/jetkvm_app.sha256 r2://jetkvm-update/app/$(VERSION)/jetkvm_app.sha256
|
28
go.mod
28
go.mod
|
@ -11,12 +11,15 @@ require (
|
|||
github.com/coreos/go-oidc/v3 v3.11.0
|
||||
github.com/creack/pty v1.1.23
|
||||
github.com/fsnotify/fsnotify v1.9.0
|
||||
github.com/gin-contrib/logger v1.2.6
|
||||
github.com/gin-gonic/gin v1.10.1
|
||||
github.com/gin-contrib/logger v1.2.5
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/guregu/null/v6 v6.0.0
|
||||
github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf
|
||||
github.com/hanwen/go-fuse/v2 v2.8.0
|
||||
github.com/hanwen/go-fuse/v2 v2.5.1
|
||||
github.com/hashicorp/go-getter/v2 v2.2.3
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0
|
||||
github.com/pion/logging v0.2.3
|
||||
github.com/pion/mdns/v2 v2.0.7
|
||||
github.com/pion/webrtc/v4 v4.0.16
|
||||
|
@ -30,15 +33,16 @@ require (
|
|||
github.com/stretchr/testify v1.10.0
|
||||
github.com/vishvananda/netlink v1.3.0
|
||||
go.bug.st/serial v1.6.2
|
||||
golang.org/x/crypto v0.39.0
|
||||
golang.org/x/net v0.41.0
|
||||
golang.org/x/sys v0.33.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/sys v0.32.0
|
||||
)
|
||||
|
||||
replace github.com/pojntfx/go-nbd v0.3.2 => github.com/chemhack/go-nbd v0.0.0-20241006125820-59e45f5b1e7b
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/bytedance/sonic v1.13.2 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.4 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
|
@ -52,11 +56,19 @@ require (
|
|||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.0 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/go-homedir v1.0.0 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
|
@ -80,11 +92,13 @@ require (
|
|||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/ulikunitz/xz v0.5.8 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
golang.org/x/arch v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.24.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
75
go.sum
75
go.sum
|
@ -4,6 +4,8 @@ github.com/beevik/ntp v1.4.3 h1:PlbTvE5NNy4QHmA4Mg57n7mcFTmr1W1j3gcK7L1lqho=
|
|||
github.com/beevik/ntp v1.4.3/go.mod h1:Unr8Zg+2dRn7d8bHFuehIMSvvUYssHMxW3Q5Nx4RW5Q=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
|
||||
github.com/bytedance/sonic v1.13.2 h1:8/H1FempDZqC4VqjptGo14QQlJx8VdZJegxs6wwfqpQ=
|
||||
github.com/bytedance/sonic v1.13.2/go.mod h1:o68xyaF9u2gvVBuGHPlUVCy+ZfmNNO5ETf1+KgkJhz4=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
|
@ -32,12 +34,12 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
|
|||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
|
||||
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
|
||||
github.com/gin-contrib/logger v1.2.6 h1:EPolruKUTzNXMVBD9LuAFQmRjTs7AH7yKGuXgYqrKWc=
|
||||
github.com/gin-contrib/logger v1.2.6/go.mod h1:7niPrd7F0Nscw/zvgz8RiGJxSdbKM2yfQNy8xCHcm64=
|
||||
github.com/gin-contrib/logger v1.2.5 h1:qVQI4omayQecuN4zX9ZZnsOq7w9J/ZLds3J/FMn8ypM=
|
||||
github.com/gin-contrib/logger v1.2.5/go.mod h1:/bj+vNMuA2xOEQ1aRHoJ1m9+uyaaXIAxQTvM2llsc6I=
|
||||
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
|
||||
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
|
||||
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
|
||||
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
|
@ -54,14 +56,30 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
|
|||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/guregu/null/v6 v6.0.0 h1:N14VRS+4di81i1PXRiprbQJ9EM9gqBa0+KVMeS/QSjQ=
|
||||
github.com/guregu/null/v6 v6.0.0/go.mod h1:hrMIhIfrOZeLPZhROSn149tpw2gHkidAqxoXNyeX3iQ=
|
||||
github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf h1:JO6ISZIvEUitto5zjQ3/VEnDM5rPbqIFuOhS0U0ByeA=
|
||||
github.com/gwatts/rootcerts v0.0.0-20240401182218-3ab9db955caf/go.mod h1:5Kt9XkWvkGi2OHOq0QsGxebHmhCcqJ8KCbNg/a6+n+g=
|
||||
github.com/hanwen/go-fuse/v2 v2.8.0 h1:wV8rG7rmCz8XHSOwBZhG5YcVqcYjkzivjmbaMafPlAs=
|
||||
github.com/hanwen/go-fuse/v2 v2.8.0/go.mod h1:yE6D2PqWwm3CbYRxFXV9xUd8Md5d6NG0WBs5spCswmI=
|
||||
github.com/hanwen/go-fuse/v2 v2.5.1 h1:OQBE8zVemSocRxA4OaFJbjJ5hlpCmIWbGr7r0M4uoQQ=
|
||||
github.com/hanwen/go-fuse/v2 v2.5.1/go.mod h1:xKwi1cF7nXAOBCXujD5ie0ZKsxc8GGSA1rlMJc+8IJs=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-getter/v2 v2.2.3 h1:6CVzhT0KJQHqd9b0pK3xSP0CM/Cv+bVhk+jcaRJ2pGk=
|
||||
github.com/hashicorp/go-getter/v2 v2.2.3/go.mod h1:hp5Yy0GMQvwWVUmwLs3ygivz1JSLI323hdIE9J9m7TY=
|
||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
|
||||
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
|
||||
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
|
||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0 h1:BdoC9cE81qXfrxeb9eoJi9dWrdhSuwXMAnHTbnBm4Wc=
|
||||
github.com/jellydator/ttlcache/v3 v3.3.0/go.mod h1:bj2/e0l4jRnQdrnSTaGTsh4GSXvMjQcy41i7th0GVGw=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
|
@ -77,6 +95,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
|
@ -88,8 +107,12 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/
|
|||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -167,6 +190,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
|||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
|
@ -175,23 +200,41 @@ github.com/wlynxg/anet v0.0.5 h1:J3VJGi1gvo0JwZ/P1/Yc/8p63SoW98B5dHkYDmpgvvU=
|
|||
github.com/wlynxg/anet v0.0.5/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA=
|
||||
go.bug.st/serial v1.6.2 h1:kn9LRX3sdm+WxWKufMlIRndwGfPWsH1/9lCWXQCasq8=
|
||||
go.bug.st/serial v1.6.2/go.mod h1:UABfsluHAiaNI+La2iESysd9Vetq7VRdpxvjx7CmmOE=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
|
||||
golang.org/x/arch v0.17.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
|
||||
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
|
||||
golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
|
||||
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
|
||||
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
|
||||
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package lldp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/google/gopacket/afpacket"
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
const (
|
||||
afPacketBufferSize = 2 // in MiB
|
||||
afPacketSnaplen = 9216
|
||||
)
|
||||
|
||||
func afPacketComputeSize(targetSizeMb int, snaplen int, pageSize int) (
|
||||
frameSize int, blockSize int, numBlocks int, err error) {
|
||||
|
||||
if snaplen < pageSize {
|
||||
frameSize = pageSize / (pageSize / snaplen)
|
||||
} else {
|
||||
frameSize = (snaplen/pageSize + 1) * pageSize
|
||||
}
|
||||
|
||||
// 128 is the default from the gopacket library so just use that
|
||||
blockSize = frameSize * 128
|
||||
numBlocks = (targetSizeMb * 1024 * 1024) / blockSize
|
||||
|
||||
if numBlocks == 0 {
|
||||
return 0, 0, 0, fmt.Errorf("interface buffersize is too small")
|
||||
}
|
||||
|
||||
return frameSize, blockSize, numBlocks, nil
|
||||
}
|
||||
|
||||
func afPacketNewTPacket(ifName string) (*afpacket.TPacket, error) {
|
||||
szFrame, szBlock, numBlocks, err := afPacketComputeSize(
|
||||
afPacketBufferSize,
|
||||
afPacketSnaplen,
|
||||
os.Getpagesize())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return afpacket.NewTPacket(
|
||||
afpacket.OptInterface(ifName),
|
||||
afpacket.OptFrameSize(szFrame),
|
||||
afpacket.OptBlockSize(szBlock),
|
||||
afpacket.OptNumBlocks(numBlocks),
|
||||
afpacket.OptAddVLANHeader(false),
|
||||
afpacket.SocketRaw,
|
||||
afpacket.TPacketVersion3)
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
ifrName [IFNAMSIZ]byte
|
||||
ifrHwaddr syscall.RawSockaddr
|
||||
}
|
||||
|
||||
func addMulticastAddr(ifName string, addr net.HardwareAddr) error {
|
||||
fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_DGRAM, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer syscall.Close(fd)
|
||||
|
||||
var name [IFNAMSIZ]byte
|
||||
copy(name[:], []byte(ifName))
|
||||
|
||||
ifr := &ifreq{
|
||||
ifrName: name,
|
||||
ifrHwaddr: toRawSockaddr(addr),
|
||||
}
|
||||
|
||||
_, _, ep := unix.Syscall(unix.SYS_IOCTL, uintptr(fd),
|
||||
unix.SIOCADDMULTI, uintptr(unsafe.Pointer(ifr)))
|
||||
|
||||
if ep != 0 {
|
||||
return syscall.Errno(ep)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//go:build arm && linux
|
||||
|
||||
package lldp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func toRawSockaddr(mac net.HardwareAddr) (sockaddr syscall.RawSockaddr) {
|
||||
for i, n := range mac {
|
||||
sockaddr.Data[i] = uint8(n)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//go:build !arm && linux
|
||||
|
||||
package lldp
|
||||
|
||||
import (
|
||||
"net"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func toRawSockaddr(mac net.HardwareAddr) (sockaddr syscall.RawSockaddr) {
|
||||
for i, n := range mac {
|
||||
sockaddr.Data[i] = int8(n)
|
||||
}
|
||||
return
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package lldp
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/afpacket"
|
||||
"github.com/jellydator/ttlcache/v3"
|
||||
"github.com/jetkvm/kvm/internal/logging"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
var defaultLogger = logging.GetSubsystemLogger("lldp")
|
||||
|
||||
type LLDP struct {
|
||||
l *zerolog.Logger
|
||||
tPacket *afpacket.TPacket
|
||||
pktSource *gopacket.PacketSource
|
||||
|
||||
enableRx bool
|
||||
enableTx bool
|
||||
|
||||
packets chan gopacket.Packet
|
||||
interfaceName string
|
||||
stop chan struct{}
|
||||
|
||||
neighbors *ttlcache.Cache[string, Neighbor]
|
||||
}
|
||||
|
||||
type LLDPOptions struct {
|
||||
InterfaceName string
|
||||
EnableRx bool
|
||||
EnableTx bool
|
||||
Logger *zerolog.Logger
|
||||
}
|
||||
|
||||
func NewLLDP(opts *LLDPOptions) *LLDP {
|
||||
if opts.Logger == nil {
|
||||
opts.Logger = defaultLogger
|
||||
}
|
||||
|
||||
if opts.InterfaceName == "" {
|
||||
opts.Logger.Fatal().Msg("InterfaceName is required")
|
||||
}
|
||||
|
||||
return &LLDP{
|
||||
interfaceName: opts.InterfaceName,
|
||||
enableRx: opts.EnableRx,
|
||||
enableTx: opts.EnableTx,
|
||||
l: opts.Logger,
|
||||
neighbors: ttlcache.New(ttlcache.WithTTL[string, Neighbor](1 * time.Hour)),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *LLDP) Start() error {
|
||||
if l.enableRx {
|
||||
l.l.Info().Msg("setting up AF_PACKET")
|
||||
if err := l.setUpCapture(); err != nil {
|
||||
l.l.Error().Err(err).Msg("unable to set up AF_PACKET")
|
||||
return err
|
||||
}
|
||||
l.startCapture()
|
||||
}
|
||||
|
||||
go l.neighbors.Start()
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package lldp
|
||||
|
||||
import "time"
|
||||
|
||||
type Neighbor struct {
|
||||
Mac string `json:"mac"`
|
||||
Source string `json:"source"`
|
||||
ChassisID string `json:"chassis_id"`
|
||||
PortID string `json:"port_id"`
|
||||
PortDescription string `json:"port_description"`
|
||||
SystemName string `json:"system_name"`
|
||||
SystemDescription string `json:"system_description"`
|
||||
TTL uint16 `json:"ttl"`
|
||||
ManagementAddress string `json:"management_address"`
|
||||
Values map[string]string `json:"values"`
|
||||
}
|
||||
|
||||
func (l *LLDP) addNeighbor(mac string, neighbor Neighbor, ttl time.Duration) {
|
||||
logger := l.l.With().
|
||||
Str("mac", mac).
|
||||
Interface("neighbor", neighbor).
|
||||
Logger()
|
||||
|
||||
current_neigh := l.neighbors.Get(mac)
|
||||
if current_neigh != nil {
|
||||
current_source := current_neigh.Value().Source
|
||||
if current_source == "lldp" && neighbor.Source != "lldp" {
|
||||
logger.Info().Msg("skip updating neighbor, as LLDP has higher priority")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info().Msg("adding neighbor")
|
||||
l.neighbors.Set(mac, neighbor, ttl)
|
||||
}
|
||||
|
||||
func (l *LLDP) deleteNeighbor(mac string) {
|
||||
logger := l.l.With().
|
||||
Str("mac", mac).
|
||||
Logger()
|
||||
|
||||
logger.Info().Msg("deleting neighbor")
|
||||
l.neighbors.Delete(mac)
|
||||
}
|
||||
|
||||
func (l *LLDP) GetNeighbors() []Neighbor {
|
||||
items := l.neighbors.Items()
|
||||
neighbors := make([]Neighbor, 0, len(items))
|
||||
|
||||
for _, item := range items {
|
||||
neighbors = append(neighbors, item.Value())
|
||||
}
|
||||
|
||||
return neighbors
|
||||
}
|
|
@ -0,0 +1,254 @@
|
|||
package lldp
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/google/gopacket"
|
||||
"github.com/google/gopacket/layers"
|
||||
"github.com/rs/zerolog"
|
||||
"golang.org/x/net/bpf"
|
||||
)
|
||||
|
||||
const IFNAMSIZ = 16
|
||||
|
||||
var (
|
||||
lldpDefaultTTL = 120 * time.Second
|
||||
cdpDefaultTTL = 180 * time.Second
|
||||
)
|
||||
|
||||
// from lldpd
|
||||
// https://github.com/lldpd/lldpd/blob/9034c9332cca0c8b1a20e1287f0e5fed81f7eb2a/src/daemon/lldpd.h#L246
|
||||
var bpfFilter = []bpf.RawInstruction{
|
||||
{0x30, 0, 0, 0x00000000}, {0x54, 0, 0, 0x00000001}, {0x15, 0, 16, 0x00000001},
|
||||
{0x28, 0, 0, 0x0000000c}, {0x15, 0, 6, 0x000088cc},
|
||||
{0x20, 0, 0, 0x00000002}, {0x15, 2, 0, 0xc200000e},
|
||||
{0x15, 1, 0, 0xc2000003}, {0x15, 0, 2, 0xc2000000},
|
||||
{0x28, 0, 0, 0x00000000}, {0x15, 12, 13, 0x00000180},
|
||||
{0x20, 0, 0, 0x00000002}, {0x15, 0, 2, 0x52cccccc},
|
||||
{0x28, 0, 0, 0x00000000}, {0x15, 8, 9, 0x000001e0},
|
||||
{0x15, 1, 0, 0x0ccccccc}, {0x15, 0, 2, 0x81000100},
|
||||
{0x28, 0, 0, 0x00000000}, {0x15, 4, 5, 0x00000100},
|
||||
{0x20, 0, 0, 0x00000002}, {0x15, 0, 3, 0x2b000000},
|
||||
{0x28, 0, 0, 0x00000000}, {0x15, 0, 1, 0x000000e0},
|
||||
{0x6, 0, 0, 0x00040000},
|
||||
{0x6, 0, 0, 0x00000000},
|
||||
}
|
||||
|
||||
var multicastAddrs = []string{
|
||||
// LLDP
|
||||
"01:80:C2:00:00:00",
|
||||
"01:80:C2:00:00:03",
|
||||
"01:80:C2:00:00:0E",
|
||||
// CDP
|
||||
"01:00:0C:CC:CC:CC",
|
||||
}
|
||||
|
||||
func (l *LLDP) setUpCapture() error {
|
||||
logger := l.l.With().Str("interface", l.interfaceName).Logger()
|
||||
tPacket, err := afPacketNewTPacket(l.interfaceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Info().Msg("created TPacket")
|
||||
|
||||
// set up multicast addresses
|
||||
// otherwise the kernel might discard the packets
|
||||
// another workaround would be to enable promiscuous mode but that's too tricky
|
||||
for _, mac := range multicastAddrs {
|
||||
hwAddr, err := net.ParseMAC(mac)
|
||||
if err != nil {
|
||||
logger.Error().Msgf("unable to parse MAC address %s: %s", mac, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err := addMulticastAddr(l.interfaceName, hwAddr); err != nil {
|
||||
logger.Error().Msgf("unable to add multicast address %s: %s", mac, err)
|
||||
continue
|
||||
}
|
||||
|
||||
logger.Info().
|
||||
Interface("hwaddr", hwAddr).
|
||||
Msgf("added multicast address")
|
||||
}
|
||||
|
||||
if err = tPacket.SetBPF(bpfFilter); err != nil {
|
||||
logger.Error().Msgf("unable to set BPF filter: %s", err)
|
||||
tPacket.Close()
|
||||
return err
|
||||
}
|
||||
logger.Info().Msg("BPF filter set")
|
||||
|
||||
l.pktSource = gopacket.NewPacketSource(tPacket, layers.LayerTypeEthernet)
|
||||
l.tPacket = tPacket
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LLDP) startCapture() error {
|
||||
logger := l.l.With().Str("interface", l.interfaceName).Logger()
|
||||
if l.tPacket == nil {
|
||||
return fmt.Errorf("AFPacket not initialized")
|
||||
}
|
||||
|
||||
if l.pktSource == nil {
|
||||
return fmt.Errorf("packet source not initialized")
|
||||
}
|
||||
|
||||
go func() {
|
||||
logger.Info().Msg("starting capture LLDP ethernet frames")
|
||||
|
||||
for packet := range l.pktSource.Packets() {
|
||||
if err := l.handlePacket(packet, &logger); err != nil {
|
||||
logger.Error().Msgf("error handling packet: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LLDP) handlePacket(packet gopacket.Packet, logger *zerolog.Logger) error {
|
||||
linkLayer := packet.LinkLayer()
|
||||
if linkLayer == nil {
|
||||
return fmt.Errorf("no link layer")
|
||||
}
|
||||
|
||||
srcMac := linkLayer.LinkFlow().Src().String()
|
||||
dstMac := linkLayer.LinkFlow().Dst().String()
|
||||
|
||||
logger.Trace().
|
||||
Str("src_mac", srcMac).
|
||||
Str("dst_mac", dstMac).
|
||||
Int("length", len(packet.Data())).
|
||||
Hex("data", packet.Data()).
|
||||
Msg("received packet")
|
||||
|
||||
lldpRaw := packet.Layer(layers.LayerTypeLinkLayerDiscovery)
|
||||
if lldpRaw != nil {
|
||||
logger.Trace().Msgf("Found LLDP Frame")
|
||||
|
||||
lldpInfo := packet.Layer(layers.LayerTypeLinkLayerDiscoveryInfo)
|
||||
if lldpInfo == nil {
|
||||
return fmt.Errorf("no LLDP info layer")
|
||||
}
|
||||
|
||||
return l.handlePacketLLDP(
|
||||
srcMac,
|
||||
lldpRaw.(*layers.LinkLayerDiscovery),
|
||||
lldpInfo.(*layers.LinkLayerDiscoveryInfo),
|
||||
)
|
||||
}
|
||||
|
||||
cdpRaw := packet.Layer(layers.LayerTypeCiscoDiscovery)
|
||||
if cdpRaw != nil {
|
||||
logger.Trace().Msgf("Found CDP Frame")
|
||||
|
||||
cdpInfo := packet.Layer(layers.LayerTypeCiscoDiscoveryInfo)
|
||||
if cdpInfo == nil {
|
||||
return fmt.Errorf("no CDP info layer")
|
||||
}
|
||||
|
||||
return l.handlePacketCDP(
|
||||
srcMac,
|
||||
cdpRaw.(*layers.CiscoDiscovery),
|
||||
cdpInfo.(*layers.CiscoDiscoveryInfo),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LLDP) handlePacketLLDP(mac string, raw *layers.LinkLayerDiscovery, info *layers.LinkLayerDiscoveryInfo) error {
|
||||
n := &Neighbor{
|
||||
Values: make(map[string]string),
|
||||
Source: "lldp",
|
||||
Mac: mac,
|
||||
}
|
||||
gotEnd := false
|
||||
|
||||
ttl := lldpDefaultTTL
|
||||
|
||||
for _, v := range raw.Values {
|
||||
switch v.Type {
|
||||
case layers.LLDPTLVEnd:
|
||||
gotEnd = true
|
||||
case layers.LLDPTLVChassisID:
|
||||
n.ChassisID = string(raw.ChassisID.ID)
|
||||
n.Values["chassis_id"] = n.ChassisID
|
||||
case layers.LLDPTLVPortID:
|
||||
n.PortID = string(raw.PortID.ID)
|
||||
n.Values["port_id"] = n.PortID
|
||||
case layers.LLDPTLVPortDescription:
|
||||
n.PortDescription = info.PortDescription
|
||||
n.Values["port_description"] = n.PortDescription
|
||||
case layers.LLDPTLVSysName:
|
||||
n.SystemName = info.SysName
|
||||
n.Values["system_name"] = n.SystemName
|
||||
case layers.LLDPTLVSysDescription:
|
||||
n.SystemDescription = info.SysDescription
|
||||
n.Values["system_description"] = n.SystemDescription
|
||||
case layers.LLDPTLVMgmtAddress:
|
||||
// n.ManagementAddress = info.MgmtAddress.Address
|
||||
case layers.LLDPTLVTTL:
|
||||
n.TTL = uint16(raw.TTL)
|
||||
ttl = time.Duration(n.TTL) * time.Second
|
||||
n.Values["ttl"] = fmt.Sprintf("%d", n.TTL)
|
||||
case layers.LLDPTLVOrgSpecific:
|
||||
for _, org := range info.OrgTLVs {
|
||||
n.Values[fmt.Sprintf("org_specific_%d", org.OUI)] = string(org.Info)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if gotEnd || ttl < 1*time.Second {
|
||||
l.deleteNeighbor(mac)
|
||||
} else {
|
||||
l.addNeighbor(mac, *n, ttl)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LLDP) handlePacketCDP(mac string, raw *layers.CiscoDiscovery, info *layers.CiscoDiscoveryInfo) error {
|
||||
// TODO: implement full CDP parsing
|
||||
n := &Neighbor{
|
||||
Values: make(map[string]string),
|
||||
Source: "cdp",
|
||||
Mac: mac,
|
||||
}
|
||||
|
||||
ttl := cdpDefaultTTL
|
||||
|
||||
n.ChassisID = info.DeviceID
|
||||
n.PortID = info.PortID
|
||||
n.SystemName = info.SysName
|
||||
n.SystemDescription = info.Platform
|
||||
n.TTL = uint16(raw.TTL)
|
||||
|
||||
if n.TTL > 1 {
|
||||
ttl = time.Duration(n.TTL) * time.Second
|
||||
}
|
||||
|
||||
if len(info.MgmtAddresses) > 0 {
|
||||
n.ManagementAddress = fmt.Sprintf("%s", info.MgmtAddresses[0])
|
||||
}
|
||||
|
||||
l.addNeighbor(mac, *n, ttl)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l *LLDP) shutdownCapture() error {
|
||||
if l.tPacket != nil {
|
||||
l.tPacket.Close()
|
||||
l.tPacket = nil
|
||||
}
|
||||
|
||||
if l.pktSource != nil {
|
||||
l.pktSource = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
11
network.go
11
network.go
|
@ -3,6 +3,7 @@ package kvm
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/lldp"
|
||||
"github.com/jetkvm/kvm/internal/network"
|
||||
"github.com/jetkvm/kvm/internal/udhcpc"
|
||||
)
|
||||
|
@ -31,6 +32,16 @@ func networkStateChanged() {
|
|||
func initNetwork() error {
|
||||
ensureConfigLoaded()
|
||||
|
||||
lldp := lldp.NewLLDP(&lldp.LLDPOptions{
|
||||
InterfaceName: NetIfName,
|
||||
EnableRx: true,
|
||||
EnableTx: true,
|
||||
Logger: networkLogger,
|
||||
})
|
||||
if err := lldp.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
state, err := network.NewNetworkInterfaceState(&network.NetworkInterfaceOptions{
|
||||
DefaultHostname: GetDefaultHostname(),
|
||||
InterfaceName: NetIfName,
|
||||
|
|
Loading…
Reference in New Issue