fix: SDWAN TUN device lifecycle + stability

Key fixes:
- SDWAN config: use absolute path /root/.openclaw/workspace/inp2p/sdwan.json
- Client: register handlers BEFORE ReadLoop (race condition fix)
- Client: make ensureTUNReader non-fatal on error
- Client: fix TUN device conflict between ip tuntap add and ioctl
- Client: fix panic on empty TUN read (n==0 check)
- Build: static binary with -extldflags=-static for glibc compatibility

Verified: hcss(10.10.0.3) <-> i-6986(10.10.0.2) ping 5/5, 0% loss, 44ms
This commit is contained in:
2026-03-02 22:16:45 +08:00
parent 676a6e659a
commit 752988a7f4
3 changed files with 39 additions and 32 deletions

View File

@@ -59,10 +59,8 @@ type Server struct {
// New creates a new server.
func New(cfg config.ServerConfig) *Server {
sdwanPath := "sdwan.json"
if cfg.DBPath != "" {
sdwanPath = cfg.DBPath + ".sdwan.json"
}
// Use absolute path for sdwan config to avoid working directory issues
sdwanPath := "/root/.openclaw/workspace/inp2p/sdwan.json"
return &Server{
cfg: cfg,
nodes: make(map[string]*NodeInfo),
@@ -166,6 +164,8 @@ func (s *Server) HandleWS(w http.ResponseWriter, r *http.Request) {
// Check duplicate node
s.mu.Lock()
sdwanCfg := s.sdwan.get()
log.Printf("[server] sdwan config: enabled=%v gateway=%s nodes=%d", sdwanCfg.Enabled, sdwanCfg.GatewayCIDR, len(sdwanCfg.Nodes))
if old, exists := s.nodes[loginReq.Node]; exists {
log.Printf("[server] replacing existing node %s", loginReq.Node)
old.Conn.Close()
@@ -212,7 +212,11 @@ func (s *Server) HandleWS(w http.ResponseWriter, r *http.Request) {
// Push current SDWAN config right after login (if exists and enabled)
if cfg := s.sdwan.get(); cfg.Enabled && cfg.GatewayCIDR != "" {
_ = conn.Write(protocol.MsgPush, protocol.SubPushSDWANConfig, cfg)
if err := conn.Write(protocol.MsgPush, protocol.SubPushSDWANConfig, cfg); err != nil {
log.Printf("[server] sdwan config push failed: %v", err)
} else {
log.Printf("[server] sdwan config pushed to %s", loginReq.Node)
}
}
// Event-driven SDWAN peer notification
s.announceSDWANNodeOnline(loginReq.Node)
@@ -321,6 +325,7 @@ func (s *Server) registerHandlers(conn *signal.Conn, node *NodeInfo) {
// SDWAN data plane packet relay (raw IP payload)
conn.OnMessage(protocol.MsgTunnel, protocol.SubTunnelSDWANRaw, func(data []byte) error {
log.Printf("[sdwan] raw packet from %s, len=%d", node.Name, len(data))
if len(data) <= protocol.HeaderSize {
return nil
}