feat: raw binary SDWAN data plane + EncodeRaw + TUN close-on-stop

- protocol: add SubTunnelSDWANRaw subtype + EncodeRaw() for zero-copy IP packets
- client: tunReadLoop sends raw frames (no JSON/base64 overhead)
- client: SubTunnelSDWANRaw handler strips header and writes directly to TUN
- client: Stop() closes TUN file FIRST to unblock tunReadLoop
- server: SubTunnelSDWANRaw handler parses IPv4 src/dst from raw packet
- server: RouteSDWANPacket forwards as raw frame to destination

Verified: hcss(10.10.0.3) ↔ i-6986(10.10.0.2) ping 3/3, 0% loss, 46ms RTT
This commit is contained in:
2026-03-02 18:22:41 +08:00
parent 5568ea67d9
commit 489c2d191c
4 changed files with 79 additions and 33 deletions

View File

@@ -143,5 +143,6 @@ func (s *Server) RouteSDWANPacket(from *NodeInfo, pkt protocol.SDWANPacket) {
pkt.FromNode = from.Name
pkt.ToNode = toNode
_ = to.Conn.Write(protocol.MsgTunnel, protocol.SubTunnelSDWANData, pkt)
frame := protocol.EncodeRaw(protocol.MsgTunnel, protocol.SubTunnelSDWANRaw, pkt.Payload)
_ = to.Conn.WriteRaw(frame)
}

View File

@@ -309,7 +309,7 @@ func (s *Server) registerHandlers(conn *signal.Conn, node *NodeInfo) {
return s.handleRelayNodeReq(conn, node, req)
})
// SDWAN data plane packet relay (server as control-plane router)
// SDWAN data plane packet relay (JSON control payload)
conn.OnMessage(protocol.MsgTunnel, protocol.SubTunnelSDWANData, func(data []byte) error {
var pkt protocol.SDWANPacket
if err := protocol.DecodePayload(data, &pkt); err != nil {
@@ -318,6 +318,26 @@ func (s *Server) registerHandlers(conn *signal.Conn, node *NodeInfo) {
s.RouteSDWANPacket(node, pkt)
return nil
})
// SDWAN data plane packet relay (raw IP payload)
conn.OnMessage(protocol.MsgTunnel, protocol.SubTunnelSDWANRaw, func(data []byte) error {
if len(data) <= protocol.HeaderSize {
return nil
}
payload := data[protocol.HeaderSize:]
if len(payload) < 20 {
return nil
}
version := payload[0] >> 4
if version != 4 {
return nil
}
srcIP := net.IP(payload[12:16]).String()
dstIP := net.IP(payload[16:20]).String()
pkt := protocol.SDWANPacket{SrcIP: srcIP, DstIP: dstIP, Payload: payload}
s.RouteSDWANPacket(node, pkt)
return nil
})
}
// handleRelayNodeReq finds and returns the best relay node.