diff --git a/.vscode/launch.json b/.vscode/launch.json index c3a3980..ae64ec4 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,8 @@ "request": "launch", "mode": "auto", "program": "${workspaceFolder}", - "args":["-config","example_config/p2p_mode/n1.yaml","-mode","edge"/*,"-example"*/], + "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, + "args":["-config","example_config/static_mode/n1.yaml","-mode","edge"/*,"-example"*/], } ] } \ No newline at end of file diff --git a/config/config.go b/config/config.go index e7e7fae..b7c2aa4 100644 --- a/config/config.go +++ b/config/config.go @@ -5,15 +5,16 @@ import ( ) type EdgeConfig struct { - Interface InterfaceConf - NodeID Vertex - NodeName string - PrivKey string - ListenPort int - LogLevel LoggerInfo - DynamicRoute DynamicRouteInfo - NextHopTable NextHopTable - Peers []PeerInfo + Interface InterfaceConf + NodeID Vertex + NodeName string + PrivKey string + ListenPort int + LogLevel LoggerInfo + DynamicRoute DynamicRouteInfo + NextHopTable NextHopTable + ResetConnInterval float64 + Peers []PeerInfo } type SuperConfig struct { @@ -28,15 +29,15 @@ type SuperConfig struct { } type InterfaceConf struct { - Itype string - Name string - VPPIfaceID uint32 - VPPBridgeID uint32 - MacAddr string - MTU int - RecvAddr string - SendAddr string - DevFriendly bool + Itype string + Name string + VPPIfaceID uint32 + VPPBridgeID uint32 + MacAddrPrefix string + MTU int + RecvAddr string + SendAddr string + L2HeaderMode string } type PeerInfo struct { diff --git a/device/device.go b/device/device.go index 015a51a..548d5a5 100644 --- a/device/device.go +++ b/device/device.go @@ -7,6 +7,7 @@ package device import ( "encoding/base64" + "errors" "runtime" "sync" "sync/atomic" @@ -69,9 +70,12 @@ type Device struct { Peer_state [32]byte } event_tryendpoint chan struct{} + ResetConnInterval float64 - EdgeConfigPath string - EdgeConfig *config.EdgeConfig + EdgeConfigPath string + EdgeConfig *config.EdgeConfig + SuperConfigPath string + SuperConfig *config.SuperConfig Event_server_register chan path.RegisterMsg Event_server_pong chan path.PongMsg @@ -304,7 +308,7 @@ func (device *Device) SetPrivateKey(sk NoisePrivateKey) error { return nil } -func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, theconfigpath string, econfig *config.EdgeConfig, sconfig *config.SuperConfig, superevents *path.SUPER_Events) *Device { +func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *Logger, graph *path.IG, IsSuperNode bool, configpath string, econfig *config.EdgeConfig, sconfig *config.SuperConfig, superevents *path.SUPER_Events) *Device { device := new(Device) device.state.state = uint32(deviceStateDown) device.closed = make(chan struct{}) @@ -333,9 +337,11 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L device.Event_server_NhTable_changed = superevents.Event_server_NhTable_changed device.LogTransit = sconfig.LogLevel.LogTransit device.LogControl = sconfig.LogLevel.LogControl + device.SuperConfig = sconfig + device.SuperConfigPath = configpath go device.RoutineRecalculateNhTable() } else { - device.EdgeConfigPath = theconfigpath + device.EdgeConfigPath = configpath device.EdgeConfig = econfig device.DRoute = econfig.DynamicRoute device.DupData = *fixed_time_cache.NewCache(path.S2TD(econfig.DynamicRoute.DupCheckTimeout), false, path.S2TD(60)) @@ -343,11 +349,13 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L device.Event_save_config = make(chan struct{}, 1<<5) device.LogTransit = econfig.LogLevel.LogTransit device.LogControl = econfig.LogLevel.LogControl + device.ResetConnInterval = device.EdgeConfig.ResetConnInterval go device.RoutineSetEndpoint() go device.RoutineRegister() go device.RoutineSendPing() go device.RoutineRecalculateNhTable() go device.RoutineSpreadAllMyNeighbor() + go device.RoutineResetConn() } // create queues @@ -374,6 +382,29 @@ func NewDevice(tapDevice tap.Device, id config.Vertex, bind conn.Bind, logger *L return device } +func (device *Device) LookupPeerIDAtConfig(pk NoisePublicKey) (ID config.Vertex, err error) { + var peerlist []config.PeerInfo + if device.IsSuperNode { + if device.SuperConfig == nil { + return 0, errors.New("Superconfig is nil") + } + peerlist = device.SuperConfig.Peers + } else { + if device.EdgeConfig == nil { + return 0, errors.New("EdgeConfig is nil") + } + peerlist = device.EdgeConfig.Peers + } + + pkstr := PubKey2Str(pk) + for _, peerinfo := range peerlist { + if peerinfo.PubKey == pkstr { + return peerinfo.NodeID, nil + } + } + return 0, errors.New("Peer not found in the config file.") +} + func (device *Device) LookupPeer(pk NoisePublicKey) *Peer { device.peers.RLock() defer device.peers.RUnlock() diff --git a/device/peer.go b/device/peer.go index 45db886..813ef6c 100644 --- a/device/peer.go +++ b/device/peer.go @@ -36,6 +36,8 @@ type Peer struct { ID config.Vertex AskedForNeighbor bool + StaticConn bool //if true, this peer will not write to config file when roaming, and the endpoint will be reset periodically + ConnURL string // These fields are accessed with atomic operations, which must be // 64-bit aligned even on 32-bit platforms. Go guarantees that an @@ -330,15 +332,16 @@ func (device *Device) SaveToConfig(peer *Peer, endpoint conn.Endpoint) { if device.IsSuperNode { //Can't in super mode return } + if peer.StaticConn == true { //static conn do not write new endpoint to config + return + } if !device.DRoute.P2P.UseP2P { //Must in p2p mode return } if peer.endpoint != nil && peer.endpoint.DstIP().Equal(endpoint.DstIP()) { //endpoint changed return } - if peer.LastPingReceived.Add(path.S2TD(device.DRoute.P2P.PeerAliveTimeout)).After(time.Now()) { //Peer alives - return - } + url := endpoint.DstToString() foundInFile := false pubkeystr := PubKey2Str(peer.handshake.remoteStatic) diff --git a/device/receive.go b/device/receive.go index ca4eaf0..30d0c7a 100644 --- a/device/receive.go +++ b/device/receive.go @@ -548,7 +548,7 @@ func (peer *Peer) RoutineSequentialReceiver() { goto skip } src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:]) - if !tap.IsBoardCast(src_macaddr) { + if !tap.IsNotUnicast(src_macaddr) { device.l2fib.Store(src_macaddr, src_nodeID) // Write to l2fib table } _, err = device.tap.device.Write(elem.buffer[:MessageTransportOffsetContent+len(elem.packet)], MessageTransportOffsetContent+path.EgHeaderLen) diff --git a/device/receivesendproc.go b/device/receivesendproc.go index 154b693..69403c6 100644 --- a/device/receivesendproc.go +++ b/device/receivesendproc.go @@ -142,7 +142,7 @@ func (device *Device) process_received(msg_type path.Usage, peer *Peer, body []b } case path.BoardcastPeer: if content, err := path.ParseBoardcastPeerMsg(body); err == nil { - return device.process_BoardcastPeerMsg(content) + return device.process_BoardcastPeerMsg(peer, content) } default: err = errors.New("Not a valid msg_type") @@ -245,7 +245,6 @@ func (device *Device) process_pong(peer *Peer, content path.PongMsg) error { header.SetPacketLength(uint16(len(body))) copy(buf[path.EgHeaderLen:], body) device.SendPacket(peer, buf, MessageTransportOffsetContent) - peer.AskedForNeighbor = true } } return nil @@ -434,12 +433,35 @@ func (device *Device) RoutineSpreadAllMyNeighbor() { } for { device.process_RequestPeerMsg(path.QueryPeerMsg{ - Request_ID: 0, + Request_ID: uint32(path.Boardcast), }) time.Sleep(path.S2TD(device.DRoute.P2P.SendPeerInterval)) } } +func (device *Device) RoutineResetConn() { + if device.ResetConnInterval <= 0.01 { + return + } + for { + for _, peer := range device.peers.keyMap { + if peer.StaticConn { + continue + } + if peer.ConnURL == "" { + continue + } + endpoint, err := device.Bind().ParseEndpoint(peer.ConnURL) + if err != nil { + device.log.Errorf("Failed to bind "+peer.ConnURL, err) + continue + } + peer.SetEndpointFromPacket(endpoint) + } + time.Sleep(time.Duration(device.ResetConnInterval)) + } +} + func (device *Device) GeneratePingPacket(src_nodeID config.Vertex) ([]byte, error) { body, err := path.GetByte(&path.PingMsg{ Src_nodeID: src_nodeID, @@ -531,9 +553,12 @@ func (device *Device) process_RequestPeerMsg(content path.QueryPeerMsg) error { return nil } -func (device *Device) process_BoardcastPeerMsg(content path.BoardcastPeerMsg) error { +func (device *Device) process_BoardcastPeerMsg(peer *Peer, content path.BoardcastPeerMsg) error { if device.DRoute.P2P.UseP2P { var sk NoisePublicKey + if content.Request_ID == uint32(device.ID) { + peer.AskedForNeighbor = true + } if bytes.Equal(content.PubKey[:], device.staticIdentity.publicKey[:]) { return nil } diff --git a/device/send.go b/device/send.go index 4eff00d..bb9c3fd 100644 --- a/device/send.go +++ b/device/send.go @@ -250,7 +250,7 @@ func (device *Device) RoutineReadFromTUN() { dst_nodeID := EgBody.GetDst() dstMacAddr := tap.GetDstMacAddr(elem.packet[path.EgHeaderLen:]) // lookup peer - if tap.IsBoardCast(dstMacAddr) { + if tap.IsNotUnicast(dstMacAddr) { dst_nodeID = path.Boardcast } else if val, ok := device.l2fib.Load(dstMacAddr); !ok { //Lookup failed dst_nodeID = path.Boardcast diff --git a/device/uapi.go b/device/uapi.go index 9dfbbaa..ee284f7 100644 --- a/device/uapi.go +++ b/device/uapi.go @@ -10,7 +10,6 @@ import ( "bytes" "errors" "fmt" - "hash/crc32" "io" "net" "strconv" @@ -19,7 +18,6 @@ import ( "sync/atomic" "time" - "github.com/KusakabeSi/EtherGuardVPN/config" "github.com/KusakabeSi/EtherGuardVPN/ipc" ) @@ -268,8 +266,6 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error if err != nil { return ipcErrorf(ipc.IpcErrorInvalid, "failed to get peer by public key: %w", err) } - h := crc32.NewIEEE() - h.Write(publicKey[:]) // Ignore peer with the same public key as this device. device.staticIdentity.RLock() @@ -284,7 +280,11 @@ func (device *Device) handlePublicKeyLine(peer *ipcSetPeer, value string) error peer.created = peer.Peer == nil if peer.created { - peer.Peer, err = device.NewPeer(publicKey, config.Vertex(h.Sum32())) + id, err := device.LookupPeerIDAtConfig(publicKey) + if err != nil { + return errors.New("Create new peer by UAPI is not implemented") + } + peer.Peer, err = device.NewPeer(publicKey, id) if err != nil { return ipcErrorf(ipc.IpcErrorInvalid, "failed to create new peer: %w", err) } diff --git a/example_config/p2p_mode/n1.yaml b/example_config/p2p_mode/n1.yaml index c7e5707..4de4376 100644 --- a/example_config/p2p_mode/n1.yaml +++ b/example_config/p2p_mode/n1.yaml @@ -1,18 +1,19 @@ interface: itype: stdio - ifaceid: 1 name: tap1 - macaddr: AA:BB:CC:DD:EE:01 + vppifaceid: 1 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4001 sendaddr: 127.0.0.1:5001 - devfriendly: true + l2headermode: kbdbg nodeid: 1 nodename: Node01 privkey: aABzjKhWdkFfQ29ZuijtMp1h1TNJe66SDCwvfmvQznw= listenport: 3001 loglevel: - loglevel: normal` + loglevel: normal logtransit: true logcontrol: true dynamicroute: @@ -23,9 +24,9 @@ dynamicroute: supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,9 +94,10 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 2 pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= pskey: "" endpoint: 127.0.0.1:3002 - static: true + static: true \ No newline at end of file diff --git a/example_config/p2p_mode/n2.yaml b/example_config/p2p_mode/n2.yaml index d017b4e..9082cb7 100644 --- a/example_config/p2p_mode/n2.yaml +++ b/example_config/p2p_mode/n2.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 2 name: tap2 - macaddr: AA:BB:CC:DD:EE:02 + vppifaceid: 2 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4002 sendaddr: 127.0.0.1:5002 - devfriendly: true + l2headermode: kbdbg nodeid: 2 nodename: Node02 privkey: UNZMzPX5fG/8yGC8edVj/ksF9N6ARRqdq7fqE/PD7ls= @@ -23,9 +24,9 @@ dynamicroute: supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 1 pubkey: CooSkIP7/wiC7Rh83UYnB2yPkJijkNFmhtorHtyYlzY= diff --git a/example_config/p2p_mode/n3.yaml b/example_config/p2p_mode/n3.yaml index 646d308..e490675 100644 --- a/example_config/p2p_mode/n3.yaml +++ b/example_config/p2p_mode/n3.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 3 name: tap3 - macaddr: AA:BB:CC:DD:EE:03 + vppifaceid: 3 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4003 sendaddr: 127.0.0.1:5003 - devfriendly: true + l2headermode: kbdbg nodeid: 3 nodename: Node03 privkey: gJy35nbsd8FuuxyWHjsefN+U+oM7RkuIB1EanNLSVHg= @@ -23,9 +24,9 @@ dynamicroute: supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 2 pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= diff --git a/example_config/p2p_mode/n4.yaml b/example_config/p2p_mode/n4.yaml index 1290614..ca5ba5b 100644 --- a/example_config/p2p_mode/n4.yaml +++ b/example_config/p2p_mode/n4.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 4 name: tap4 - macaddr: AA:BB:CC:DD:EE:04 + vppifaceid: 4 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4004 sendaddr: 127.0.0.1:5004 - devfriendly: true + l2headermode: kbdbg nodeid: 4 nodename: Node04 privkey: wAdLgCk0SHiO11/aUf9944focD1BUCH5b6Pe+cRHHXQ= @@ -23,9 +24,9 @@ dynamicroute: supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 2 pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= diff --git a/example_config/p2p_mode/n5.yaml b/example_config/p2p_mode/n5.yaml index cbb2fa8..24d0deb 100644 --- a/example_config/p2p_mode/n5.yaml +++ b/example_config/p2p_mode/n5.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 5 name: tap5 - macaddr: AA:BB:CC:DD:EE:05 + vppifaceid: 5 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4005 sendaddr: 127.0.0.1:5005 - devfriendly: true + l2headermode: kbdbg nodeid: 5 nodename: Node05 privkey: gLmzeCbmN/hjiE+ehNXL9IxuG9hhWIYv2s16/DOW6FE= @@ -23,9 +24,9 @@ dynamicroute: supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 3 pubkey: 0meQ0pQCAkLZdpfyMqggpnk0k3UKG2M8jfIMlQjTRWs= diff --git a/example_config/p2p_mode/n6.yaml b/example_config/p2p_mode/n6.yaml index fb36bbe..0188680 100644 --- a/example_config/p2p_mode/n6.yaml +++ b/example_config/p2p_mode/n6.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 6 name: tap6 - macaddr: AA:BB:CC:DD:EE:03 + vppifaceid: 6 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4006 sendaddr: 127.0.0.1:5006 - devfriendly: true + l2headermode: kbdbg nodeid: 6 nodename: Node06 privkey: IIX5F6oWZUS2dlhxWFJ7TxdJtDCr5jzeuhxUB6YM7Us= @@ -23,9 +24,9 @@ dynamicroute: supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 4 pubkey: 2EfY85KF1S+3dZ3A55eZcyi0QU+sOzOyuADtJs2U2Ww= diff --git a/example_config/static_mode/n1.yaml b/example_config/static_mode/n1.yaml index 5efe3a4..d5e74a6 100644 --- a/example_config/static_mode/n1.yaml +++ b/example_config/static_mode/n1.yaml @@ -1,31 +1,32 @@ interface: itype: stdio - ifaceid: 1 name: tap1 - macaddr: AA:BB:CC:DD:EE:01 + vppifaceid: 1 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4001 sendaddr: 127.0.0.1:5001 - devfriendly: true + l2headermode: kbdbg nodeid: 1 nodename: Node01 privkey: aABzjKhWdkFfQ29ZuijtMp1h1TNJe66SDCwvfmvQznw= listenport: 3001 loglevel: - loglevel: normal` + loglevel: normal logtransit: true logcontrol: true dynamicroute: sendpinginterval: 20 dupchecktimeout: 40 conntimeout: 30 - savenewpeers: true + savenewpeers: false supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 2 pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= diff --git a/example_config/static_mode/n2.yaml b/example_config/static_mode/n2.yaml index c88b4b8..91f4971 100644 --- a/example_config/static_mode/n2.yaml +++ b/example_config/static_mode/n2.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 2 name: tap2 - macaddr: AA:BB:CC:DD:EE:02 + vppifaceid: 2 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4002 sendaddr: 127.0.0.1:5002 - devfriendly: true + l2headermode: kbdbg nodeid: 2 nodename: Node02 privkey: UNZMzPX5fG/8yGC8edVj/ksF9N6ARRqdq7fqE/PD7ls= @@ -19,13 +20,13 @@ dynamicroute: sendpinginterval: 20 dupchecktimeout: 40 conntimeout: 30 - savenewpeers: true + savenewpeers: false supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 1 pubkey: CooSkIP7/wiC7Rh83UYnB2yPkJijkNFmhtorHtyYlzY= diff --git a/example_config/static_mode/n3.yaml b/example_config/static_mode/n3.yaml index 1563c37..fe7e330 100644 --- a/example_config/static_mode/n3.yaml +++ b/example_config/static_mode/n3.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 3 name: tap3 - macaddr: AA:BB:CC:DD:EE:03 + vppifaceid: 3 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4003 sendaddr: 127.0.0.1:5003 - devfriendly: true + l2headermode: kbdbg nodeid: 3 nodename: Node03 privkey: gJy35nbsd8FuuxyWHjsefN+U+oM7RkuIB1EanNLSVHg= @@ -19,13 +20,13 @@ dynamicroute: sendpinginterval: 20 dupchecktimeout: 40 conntimeout: 30 - savenewpeers: true + savenewpeers: false supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 2 pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= diff --git a/example_config/static_mode/n4.yaml b/example_config/static_mode/n4.yaml index 1f458ff..923984a 100644 --- a/example_config/static_mode/n4.yaml +++ b/example_config/static_mode/n4.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 4 name: tap4 - macaddr: AA:BB:CC:DD:EE:04 + vppifaceid: 4 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4004 sendaddr: 127.0.0.1:5004 - devfriendly: true + l2headermode: kbdbg nodeid: 4 nodename: Node04 privkey: wAdLgCk0SHiO11/aUf9944focD1BUCH5b6Pe+cRHHXQ= @@ -19,13 +20,13 @@ dynamicroute: sendpinginterval: 20 dupchecktimeout: 40 conntimeout: 30 - savenewpeers: true + savenewpeers: false supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 2 pubkey: csT+hco4Jpa7btMeC9subHk2ZqzxcljcBk/57V0cSEk= diff --git a/example_config/static_mode/n5.yaml b/example_config/static_mode/n5.yaml index 7dff132..1fb5087 100644 --- a/example_config/static_mode/n5.yaml +++ b/example_config/static_mode/n5.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 5 name: tap5 - macaddr: AA:BB:CC:DD:EE:05 + vppifaceid: 5 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4005 sendaddr: 127.0.0.1:5005 - devfriendly: true + l2headermode: kbdbg nodeid: 5 nodename: Node05 privkey: gLmzeCbmN/hjiE+ehNXL9IxuG9hhWIYv2s16/DOW6FE= @@ -19,13 +20,13 @@ dynamicroute: sendpinginterval: 20 dupchecktimeout: 40 conntimeout: 30 - savenewpeers: true + savenewpeers: false supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 3 pubkey: 0meQ0pQCAkLZdpfyMqggpnk0k3UKG2M8jfIMlQjTRWs= diff --git a/example_config/static_mode/n6.yaml b/example_config/static_mode/n6.yaml index aa3b3bf..d633a5f 100644 --- a/example_config/static_mode/n6.yaml +++ b/example_config/static_mode/n6.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 6 name: tap6 - macaddr: AA:BB:CC:DD:EE:03 + vppifaceid: 6 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4006 sendaddr: 127.0.0.1:5006 - devfriendly: true + l2headermode: kbdbg nodeid: 6 nodename: Node06 privkey: IIX5F6oWZUS2dlhxWFJ7TxdJtDCr5jzeuhxUB6YM7Us= @@ -19,13 +20,13 @@ dynamicroute: sendpinginterval: 20 dupchecktimeout: 40 conntimeout: 30 - savenewpeers: true + savenewpeers: false supernode: usesupernode: false connurlv4: 127.0.0.1:3000 - pubkeyv4: j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y= + pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= connurlv6: '[::1]:3000' - pubkeyv6: cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw= + pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 p2p: @@ -93,6 +94,7 @@ nexthoptable: 3: 4 4: 4 5: 4 +resetconninterval: 86400 peers: - nodeid: 4 pubkey: 2EfY85KF1S+3dZ3A55eZcyi0QU+sOzOyuADtJs2U2Ww= diff --git a/example_config/super_mode/n1.yaml b/example_config/super_mode/n1.yaml index 940c940..0dd339d 100644 --- a/example_config/super_mode/n1.yaml +++ b/example_config/super_mode/n1.yaml @@ -1,12 +1,13 @@ interface: itype: stdio - ifaceid: 1 name: tap1 - macaddr: AA:BB:CC:DD:EE:FF + vppifaceid: 1 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4001 sendaddr: 127.0.0.1:5001 - devfriendly: true + l2headermode: kbdbg nodeid: 1 nodename: Node01 privkey: 6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M= @@ -24,7 +25,7 @@ dynamicroute: usesupernode: true connurlv4: 127.0.0.1:3000 pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= - connurlv6: '[::1]:2999' + connurlv6: '[::1]:3000' pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 @@ -57,4 +58,5 @@ dynamicroute: - time.euro.apple.com - time.windows.com nexthoptable: {} +resetconninterval: 86400 peers: [] \ No newline at end of file diff --git a/example_config/super_mode/n2.yaml b/example_config/super_mode/n2.yaml index e810a26..0cd8d65 100644 --- a/example_config/super_mode/n2.yaml +++ b/example_config/super_mode/n2.yaml @@ -1,14 +1,15 @@ interface: itype: stdio - ifaceid: 2 name: tap2 - macaddr: AA:BB:CC:DD:EE:FF + vppifaceid: 2 + vppbridgeid: 0 + macaddrprefix: AA:BB:CC:DD:EE mtu: 1400 recvaddr: 127.0.0.1:4002 sendaddr: 127.0.0.1:5002 - devfriendly: true -nodeid: 2 -nodename: Node02 + l2headermode: kbdbg +nodeid: 1 +nodename: Node01 privkey: OH8BsVUU2Rqzeu9B2J5GPG8PUmxWfX8uVvNFZKhVF3o= listenport: 3002 loglevel: @@ -24,7 +25,7 @@ dynamicroute: usesupernode: true connurlv4: 127.0.0.1:3000 pubkeyv4: LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic= - connurlv6: '[::1]:2999' + connurlv6: '[::1]:3000' pubkeyv6: HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI= apiurl: http://127.0.0.1:3000/api supernodeinfotimeout: 40 @@ -57,4 +58,5 @@ dynamicroute: - time.euro.apple.com - time.windows.com nexthoptable: {} +resetconninterval: 86400 peers: [] \ No newline at end of file diff --git a/example_config/super_mode/s1.yaml b/example_config/super_mode/s1.yaml index 8da8b1b..11e660b 100644 --- a/example_config/super_mode/s1.yaml +++ b/example_config/super_mode/s1.yaml @@ -2,14 +2,14 @@ nodename: NodeSuper privkeyv4: mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk= privkeyv6: +EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I= listenport: 3000 -repushconfiginterval: 10 loglevel: loglevel: normal logtransit: true logcontrol: true +repushconfiginterval: 30 graphrecalculatesetting: - jittertolerance: 20 - jittertolerancemultiplier: 1.1 + jittertolerance: 5 + jittertolerancemultiplier: 1.01 nodereporttimeout: 40 recalculatecooldown: 5 peers: diff --git a/main.go b/main.go index 7ab0593..28f3402 100644 --- a/main.go +++ b/main.go @@ -25,8 +25,8 @@ const ( ) const ( - ENV_WP_UAPI_FD = "WP_UAPI_FD" - ENV_WP_UAPI_DIR = "WP_UAPI_DIR" + ENV_EG_UAPI_FD = "EG_UAPI_FD" + ENV_EG_UAPI_DIR = "EG_UAPI_DIR" ) func printUsage() { @@ -62,20 +62,25 @@ func main() { return } - uapiDir := os.Getenv(ENV_WP_UAPI_DIR) + uapiDir := os.Getenv(ENV_EG_UAPI_DIR) if uapiDir != "" { ipc.SetsocketDirectory(uapiDir) } + var err error switch *mode { case "edge": - Edge(*tconfig, !*nouapi, *printExample) + err = Edge(*tconfig, !*nouapi, *printExample) case "super": - Super(*tconfig, !*nouapi, *printExample) + err = Super(*tconfig, !*nouapi, *printExample) case "path": path.Solve() default: flag.Usage() } + if err != nil { + fmt.Fprintf(os.Stderr, "Error :%v\n", err) + os.Exit(1) + } return } diff --git a/main_edge.go b/main_edge.go index e1e65e4..382d3ee 100644 --- a/main_edge.go +++ b/main_edge.go @@ -29,13 +29,13 @@ func printExampleEdgeConf() { tconfig := config.EdgeConfig{ Interface: config.InterfaceConf{ Itype: "stdio", - VPPIfaceID: 5, + VPPIfaceID: 5, Name: "tap1", - MacAddr: "AA:BB:CC:DD:EE:FF", + MacAddrPrefix: "AA:BB:CC:DD:EE:FF", MTU: 1400, RecvAddr: "127.0.0.1:4001", SendAddr: "127.0.0.1:5001", - DevFriendly: true, + L2HeaderMode: "nochg", }, NodeID: 1, NodeName: "Node01", @@ -44,6 +44,7 @@ func printExampleEdgeConf() { LogLevel: config.LoggerInfo{ LogLevel: "normal", LogTransit: true, + LogControl: true, }, DynamicRoute: config.DynamicRouteInfo{ SendPingInterval: 20, @@ -53,9 +54,9 @@ func printExampleEdgeConf() { SuperNode: config.SuperInfo{ UseSuperNode: true, ConnURLV4: "127.0.0.1:3000", - PubKeyV4: "j8i4dY1i7CUqd/ftaCSfCWosnURiztM+ExI7QRezU2Y=", + PubKeyV4: "LJ8KKacUcIoACTGB/9Ed9w0osrJ3WWeelzpL2u4oUic=", ConnURLV6: "[::1]:3000", - PubKeyV6: "cCcPlZw0hVkPSi15G+jpJpKE3TdCVEtO1nSiaedukGw=", + PubKeyV6: "HCfL6YJtpJEGHTlJ2LgVXIWKB/K95P57LHTJ42ZG8VI=", APIUrl: "http://127.0.0.1:3000/api", SuperNodeInfoTimeout: 40, }, @@ -90,7 +91,8 @@ func printExampleEdgeConf() { "time.windows.com"}, }, }, - NextHopTable: config.NextHopTable{}, + NextHopTable: config.NextHopTable{}, + ResetConnInterval: 86400, Peers: []config.PeerInfo{ { NodeID: 2, @@ -165,13 +167,17 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) { case "dummy": thetap, err = tap.CreateDummyTAP() case "stdio": - thetap, err = tap.CreateStdIOTAP(tconfig.Interface.Name, tconfig.Interface.DevFriendly) + tconfig.Interface.VPPIfaceID = uint32(tconfig.NodeID) + thetap, err = tap.CreateStdIOTAP(tconfig.Interface) case "udpsock": - { - lis, _ := net.ResolveUDPAddr("udp", tconfig.Interface.RecvAddr) - sen, _ := net.ResolveUDPAddr("udp", tconfig.Interface.SendAddr) - thetap, err = tap.CreateUDPSockTAP(tconfig.Interface.Name, lis, sen, tconfig.Interface.DevFriendly) - } + tconfig.Interface.VPPIfaceID = uint32(tconfig.NodeID) + lis, _ := net.ResolveUDPAddr("udp", tconfig.Interface.RecvAddr) + sen, _ := net.ResolveUDPAddr("udp", tconfig.Interface.SendAddr) + thetap, err = tap.CreateUDPSockTAP(tconfig.Interface, lis, sen) + case "vpp": + thetap, err = tap.CreateVppTAP(tconfig.Interface, tconfig.LogLevel.LogLevel) + default: + return errors.New("Unknow interface type:" + tconfig.Interface.Itype) } if err != nil { logger.Errorf("Failed to create TAP device: %v", err) @@ -206,6 +212,8 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) { logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err) return err } + peer.StaticConn = peerconf.Static + peer.ConnURL = peerconf.EndPoint peer.SetEndpointFromPacket(endpoint) } } @@ -222,6 +230,8 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) { if err != nil { return err } + peer.StaticConn = false + peer.ConnURL = tconfig.DynamicRoute.SuperNode.ConnURLV4 peer.SetEndpointFromPacket(endpoint) } if tconfig.DynamicRoute.SuperNode.ConnURLV6 != "" { @@ -235,6 +245,8 @@ func Edge(configPath string, useUAPI bool, printExample bool) (err error) { if err != nil { return err } + peer.StaticConn = false + peer.ConnURL = tconfig.DynamicRoute.SuperNode.ConnURLV6 peer.SetEndpointFromPacket(endpoint) } } diff --git a/main_super.go b/main_super.go index c1af782..28e76a4 100644 --- a/main_super.go +++ b/main_super.go @@ -34,13 +34,15 @@ import ( func printExampleSuperConf() { sconfig := config.SuperConfig{ NodeName: "NodeSuper", - PrivKeyV4: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=", - PrivKeyV6: "SM8pGjT0r8njy1/7ffN4wMwF7nnJ8UYSjGRWpCqo3ng=", + PrivKeyV4: "mL5IW0GuqbjgDeOJuPHBU2iJzBPNKhaNEXbIGwwYWWk=", + PrivKeyV6: "+EdOKIoBp/EvIusHDsvXhV1RJYbyN3Qr8nxlz35wl3I=", ListenPort: 3000, LogLevel: config.LoggerInfo{ LogLevel: "normal", LogTransit: true, + LogControl: true, }, + RePushConfigInterval: 30, Peers: []config.PeerInfo{ { NodeID: 2, @@ -50,8 +52,8 @@ func printExampleSuperConf() { }, }, GraphRecalculateSetting: config.GraphRecalculateSetting{ - JitterTolerance: 20, - JitterToleranceMultiplier: 1.1, + JitterTolerance: 5, + JitterToleranceMultiplier: 1.01, NodeReportTimeout: 40, RecalculateCoolDown: 5, }, @@ -70,8 +72,7 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) { var sconfig config.SuperConfig err = readYaml(configPath, &sconfig) if err != nil { - fmt.Printf("Error read config: %s :", configPath) - fmt.Print(err) + fmt.Printf("Error read config: %v\n", configPath) return err } interfaceName := sconfig.NodeName @@ -107,21 +108,29 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) { thetap, _ := tap.CreateDummyTAP() http_graph = path.NewGraph(3, true, sconfig.GraphRecalculateSetting) - http_device4 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(true, false), logger4, http_graph, true, "", nil, &sconfig, &super_chains) - http_device6 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(false, true), logger6, http_graph, true, "", nil, &sconfig, &super_chains) + http_device4 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(true, false), logger4, http_graph, true, configPath, nil, &sconfig, &super_chains) + http_device6 = device.NewDevice(thetap, path.SuperNodeMessage, conn.NewCustomBind(false, true), logger6, http_graph, true, configPath, nil, &sconfig, &super_chains) defer http_device4.Close() defer http_device6.Close() var sk [32]byte - sk_slice, _ := base64.StdEncoding.DecodeString(sconfig.PrivKeyV4) + sk_slice, err := base64.StdEncoding.DecodeString(sconfig.PrivKeyV4) + if err != nil { + fmt.Printf("Can't decode base64:%v\n", sconfig.PrivKeyV4) + return err + } copy(sk[:], sk_slice) http_device4.SetPrivateKey(sk) - sk_slice, _ = base64.StdEncoding.DecodeString(sconfig.PrivKeyV6) + sk_slice, err = base64.StdEncoding.DecodeString(sconfig.PrivKeyV6) + if err != nil { + fmt.Printf("Can't decode base64:%v\n", sconfig.PrivKeyV6) + return err + } copy(sk[:], sk_slice) http_device6.SetPrivateKey(sk) http_device4.IpcSet("fwmark=0\n") http_device6.IpcSet("fwmark=0\n") http_device4.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") - http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort-1) + "\n") + http_device6.IpcSet("listen_port=" + strconv.Itoa(sconfig.ListenPort) + "\n") http_device4.IpcSet("replace_peers=true\n") http_device6.IpcSet("replace_peers=true\n") @@ -143,8 +152,20 @@ func Super(configPath string, useUAPI bool, printExample bool) (err error) { PSKey: peerconf.PSKey, Connurl: make(map[string]bool), } - peer4, _ := http_device4.NewPeer(pk, peerconf.NodeID) - peer6, _ := http_device6.NewPeer(pk, peerconf.NodeID) + peer4, err := http_device4.NewPeer(pk, peerconf.NodeID) + if err != nil { + fmt.Printf("Error create peer id %v\n", peerconf.NodeID) + return err + } + peer4.StaticConn = true + peer4.ConnURL = peerconf.EndPoint + peer6, err := http_device6.NewPeer(pk, peerconf.NodeID) + if err != nil { + fmt.Printf("Error create peer id %v\n", peerconf.NodeID) + return err + } + peer6.StaticConn = true + peer6.ConnURL = peerconf.EndPoint if peerconf.PSKey != "" { var psk device.NoisePresharedKey psk_slice, err := base64.StdEncoding.DecodeString(peerconf.PSKey) @@ -306,7 +327,7 @@ func PushUpdate() { func startUAPI(interfaceName string, logger *device.Logger, the_device *device.Device, errs chan error) (net.Listener, error) { fileUAPI, err := func() (*os.File, error) { - uapiFdStr := os.Getenv(ENV_WP_UAPI_FD) + uapiFdStr := os.Getenv(ENV_EG_UAPI_FD) if uapiFdStr == "" { return ipc.UAPIOpen(interfaceName) } @@ -317,10 +338,14 @@ func startUAPI(interfaceName string, logger *device.Logger, the_device *device.D } return os.NewFile(uintptr(fd), ""), nil }() + if err != nil { + fmt.Printf("Error create UAPI socket \n") + return nil, err + } uapi, err := ipc.UAPIListen(interfaceName, fileUAPI) if err != nil { logger.Errorf("Failed to listen on uapi socket: %v", err) - os.Exit(ExitSetupFailed) + return nil, err } go func() { diff --git a/path/path.go b/path/path.go index 2ec711d..6c81b18 100644 --- a/path/path.go +++ b/path/path.go @@ -79,22 +79,29 @@ func NewGraph(num_node int, IsSuperMode bool, theconfig config.GraphRecalculateS return &g } -func (g *IG) GetWeightType(x float64) float64 { +func (g *IG) GetWeightType(x float64) (y float64) { x = math.Abs(x) - y := x - if g.JitterTolerance > 1 && g.JitterToleranceMultiplier > 0.001 { - r := g.JitterTolerance - m := g.JitterToleranceMultiplier - y = math.Pow(math.Ceil(math.Pow(x/m, 1/r)), r) * m + y = x + if g.JitterTolerance > 0.001 && g.JitterToleranceMultiplier > 1 { + t := g.JitterTolerance + r := g.JitterToleranceMultiplier + y = math.Pow(math.Ceil(math.Pow(x/t, 1/r)), r) * t } return y } func (g *IG) ShouldUpdate(u config.Vertex, v config.Vertex, newval float64) bool { - oldval := g.Weight(u, v) * 1000 - newval *= 1000 + oldval := math.Abs(g.Weight(u, v) * 1000) + newval = math.Abs(newval * 1000) if g.IsSuperMode { - return (oldval-newval)*(oldval*g.JitterToleranceMultiplier) >= g.JitterTolerance + if g.JitterTolerance > 0.001 && g.JitterToleranceMultiplier >= 1 { + diff := math.Abs(newval - oldval) + x := math.Max(oldval, newval) + t := g.JitterTolerance + r := g.JitterToleranceMultiplier + return diff > t+x*(r-1) // https://www.desmos.com/calculator/raoti16r5n + } + return oldval == newval } else { return g.GetWeightType(oldval) == g.GetWeightType(newval) } diff --git a/tap/tap.go b/tap/tap.go index 288cafe..2d103cd 100644 --- a/tap/tap.go +++ b/tap/tap.go @@ -6,7 +6,10 @@ package tap import ( - "bytes" + "encoding/binary" + "errors" + "strconv" + "strings" ) type Event int @@ -22,13 +25,44 @@ func GetSrcMacAddr(packet []byte) (srcMacAddr MacAddress) { return } -func IsBoardCast(mac_in MacAddress) bool { - if bytes.Equal(mac_in[:], []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}) { - return true - } else if bytes.Equal(mac_in[0:2], []byte{0x33, 0x33}) { - return true +func GetMacAddr(prefix string, uid uint32) (mac MacAddress, err error) { + macprefix, _, err := prefixStr2prefix(prefix) + if err != nil { + return } - return false + idbuf := make([]byte, 4) + binary.BigEndian.PutUint32(idbuf, uid) + copy(mac[2:], idbuf) + copy(mac[:], macprefix) + if IsNotUnicast(mac) { + err = errors.New("ERROR: MAC address can only set to unicast address") + return + } + return +} + +func prefixStr2prefix(prefix string) ([]uint8, uint32, error) { + hexStrs := strings.Split(strings.ToLower(prefix), ":") + retprefix := make([]uint8, len(hexStrs)) + maxID := uint32(1)<<((6-len(hexStrs))*8) - 1 + if len(hexStrs) < 2 || len(hexStrs) > 6 { + return []uint8{}, 0, errors.New("Macaddr prefix length must between 2 and 6, " + prefix + " is " + strconv.Itoa(len(hexStrs))) + } + for index, hexstr := range hexStrs { + value, err := strconv.ParseInt(hexstr, 16, 16) + if err != nil { + return []uint8{}, 0, err + } + retprefix[index] = uint8(value) + } + return retprefix, maxID, nil +} + +func IsNotUnicast(mac_in MacAddress) bool { + if mac_in[0]&1 == 0 { // Is unicast + return false + } + return true } const ( diff --git a/tap/tap_linux.go b/tap/tap_linux.go new file mode 100644 index 0000000..6937800 --- /dev/null +++ b/tap/tap_linux.go @@ -0,0 +1,529 @@ +/* SPDX-License-Identifier: MIT + * + * Copyright (C) 2017-2021 WireGuard LLC. All Rights Reserved. + */ + +package tap + +/* Implementation of the TUN device interface for linux + */ + +import ( + "bytes" + "encoding/binary" + "errors" + "fmt" + "os" + "sync" + "syscall" + "time" + "unsafe" + + "golang.org/x/sys/unix" + + "github.com/KusakabeSi/EtherGuardVPN/config" + "github.com/KusakabeSi/EtherGuardVPN/rwcancel" +) + +const ( + cloneDevicePath = "/dev/net/tun" + ifReqSize = unix.IFNAMSIZ + 64 +) + +type NativeTap struct { + tapFile *os.File + index int32 // if index + errors chan error // async error handling + events chan Event // device related events + nopi bool // the device was passed IFF_NO_PI + netlinkSock int + netlinkCancel *rwcancel.RWCancel + hackListenerClosed sync.Mutex + statusListenersShutdown chan struct{} + + closeOnce sync.Once + + nameOnce sync.Once // guards calling initNameCache, which sets following fields + nameCache string // name of interface + nameErr error +} + +func (tap *NativeTap) File() *os.File { + return tap.tapFile +} + +func (tap *NativeTap) routineHackListener() { + defer tap.hackListenerClosed.Unlock() + /* This is needed for the detection to work across network namespaces + * If you are reading this and know a better method, please get in touch. + */ + last := 0 + const ( + up = 1 + down = 2 + ) + for { + sysconn, err := tap.tapFile.SyscallConn() + if err != nil { + return + } + err2 := sysconn.Control(func(fd uintptr) { + _, err = unix.Write(int(fd), nil) + }) + if err2 != nil { + return + } + switch err { + case unix.EINVAL: + if last != up { + // If the tunnel is up, it reports that write() is + // allowed but we provided invalid data. + tap.events <- EventUp + last = up + } + case unix.EIO: + if last != down { + // If the tunnel is down, it reports that no I/O + // is possible, without checking our provided data. + tap.events <- EventDown + last = down + } + default: + return + } + select { + case <-time.After(time.Second): + // nothing + case <-tap.statusListenersShutdown: + return + } + } +} + +func createNetlinkSocket() (int, error) { + sock, err := unix.Socket(unix.AF_NETLINK, unix.SOCK_RAW, unix.NETLINK_ROUTE) + if err != nil { + return -1, err + } + saddr := &unix.SockaddrNetlink{ + Family: unix.AF_NETLINK, + Groups: unix.RTMGRP_LINK | unix.RTMGRP_IPV4_IFADDR | unix.RTMGRP_IPV6_IFADDR, + } + err = unix.Bind(sock, saddr) + if err != nil { + return -1, err + } + return sock, nil +} + +func (tap *NativeTap) routineNetlinkListener() { + defer func() { + unix.Close(tap.netlinkSock) + tap.hackListenerClosed.Lock() + close(tap.events) + tap.netlinkCancel.Close() + }() + + for msg := make([]byte, 1<<16); ; { + var err error + var msgn int + for { + msgn, _, _, _, err = unix.Recvmsg(tap.netlinkSock, msg[:], nil, 0) + if err == nil || !rwcancel.RetryAfterError(err) { + break + } + if !tap.netlinkCancel.ReadyRead() { + tap.errors <- fmt.Errorf("netlink socket closed: %w", err) + return + } + } + if err != nil { + tap.errors <- fmt.Errorf("failed to receive netlink message: %w", err) + return + } + + select { + case <-tap.statusListenersShutdown: + return + default: + } + + wasEverUp := false + for remain := msg[:msgn]; len(remain) >= unix.SizeofNlMsghdr; { + + hdr := *(*unix.NlMsghdr)(unsafe.Pointer(&remain[0])) + + if int(hdr.Len) > len(remain) { + break + } + + switch hdr.Type { + case unix.NLMSG_DONE: + remain = []byte{} + + case unix.RTM_NEWLINK: + info := *(*unix.IfInfomsg)(unsafe.Pointer(&remain[unix.SizeofNlMsghdr])) + remain = remain[hdr.Len:] + + if info.Index != tap.index { + // not our interface + continue + } + + if info.Flags&unix.IFF_RUNNING != 0 { + tap.events <- EventUp + wasEverUp = true + } + + if info.Flags&unix.IFF_RUNNING == 0 { + // Don't emit EventDown before we've ever emitted EventUp. + // This avoids a startup race with HackListener, which + // might detect Up before we have finished reporting Down. + if wasEverUp { + tap.events <- EventDown + } + } + + tap.events <- EventMTUUpdate + + default: + remain = remain[hdr.Len:] + } + } + } +} + +func (tap *NativeTap) setMacAddr(mac MacAddress) (err error) { + fd, err := unix.Socket( + unix.AF_INET, + unix.SOCK_DGRAM, + 0, + ) + if err != nil { + return err + } + defer unix.Close(fd) + var ifr [ifReqSize]byte + name, err := tap.Name() + if err != nil { + return err + } + /* + ifreq = struct.pack('16sH6B8x', self.name, AF_UNIX, *macbytes) + fcntl.ioctl(sockfd, SIOCSIFHWADDR, ifreq) + */ + copy(ifr[:16], name) + binary.BigEndian.PutUint16(ifr[16:18], unix.AF_UNIX) + copy(ifr[18:24], mac[:]) + copy(ifr[24:32], make([]byte, 8)) + _, _, err = unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(unix.SIOCSIFHWADDR), + uintptr(unsafe.Pointer(&ifr[0])), + ) + return +} + +func getIFIndex(name string) (int32, error) { + fd, err := unix.Socket( + unix.AF_INET, + unix.SOCK_DGRAM, + 0, + ) + if err != nil { + return 0, err + } + + defer unix.Close(fd) + + var ifr [ifReqSize]byte + copy(ifr[:], name) + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(unix.SIOCGIFINDEX), + uintptr(unsafe.Pointer(&ifr[0])), + ) + + if errno != 0 { + return 0, errno + } + + return *(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])), nil +} + +func (tap *NativeTap) setMTU(n int) error { + name, err := tap.Name() + if err != nil { + return err + } + + // open datagram socket + fd, err := unix.Socket( + unix.AF_INET, + unix.SOCK_DGRAM, + 0, + ) + + if err != nil { + return err + } + + defer unix.Close(fd) + + // do ioctl call + var ifr [ifReqSize]byte + copy(ifr[:], name) + *(*uint32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = uint32(n) + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(unix.SIOCSIFMTU), + uintptr(unsafe.Pointer(&ifr[0])), + ) + + if errno != 0 { + return fmt.Errorf("failed to set MTU of TUN device: %w", errno) + } + + return nil +} + +func (tap *NativeTap) MTU() (int, error) { + name, err := tap.Name() + if err != nil { + return 0, err + } + + // open datagram socket + fd, err := unix.Socket( + unix.AF_INET, + unix.SOCK_DGRAM, + 0, + ) + + if err != nil { + return 0, err + } + + defer unix.Close(fd) + + // do ioctl call + + var ifr [ifReqSize]byte + copy(ifr[:], name) + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(fd), + uintptr(unix.SIOCGIFMTU), + uintptr(unsafe.Pointer(&ifr[0])), + ) + if errno != 0 { + return 0, fmt.Errorf("failed to get MTU of TUN device: %w", errno) + } + + return int(*(*int32)(unsafe.Pointer(&ifr[unix.IFNAMSIZ]))), nil +} + +func (tap *NativeTap) Name() (string, error) { + tap.nameOnce.Do(tap.initNameCache) + return tap.nameCache, tap.nameErr +} + +func (tap *NativeTap) initNameCache() { + tap.nameCache, tap.nameErr = tap.nameSlow() +} + +func (tap *NativeTap) nameSlow() (string, error) { + sysconn, err := tap.tapFile.SyscallConn() + if err != nil { + return "", err + } + var ifr [ifReqSize]byte + var errno syscall.Errno + err = sysconn.Control(func(fd uintptr) { + _, _, errno = unix.Syscall( + unix.SYS_IOCTL, + fd, + uintptr(unix.TUNGETIFF), + uintptr(unsafe.Pointer(&ifr[0])), + ) + }) + if err != nil { + return "", fmt.Errorf("failed to get name of TUN device: %w", err) + } + if errno != 0 { + return "", fmt.Errorf("failed to get name of TUN device: %w", errno) + } + name := ifr[:] + if i := bytes.IndexByte(name, 0); i != -1 { + name = name[:i] + } + return string(name), nil +} + +func (tap *NativeTap) Write(buf []byte, offset int) (int, error) { + buf = buf[offset:] + n, err := tap.tapFile.Write(buf) + if errors.Is(err, syscall.EBADFD) { + err = os.ErrClosed + } + return n, err +} + +func (tap *NativeTap) Flush() error { + // TODO: can flushing be implemented by buffering and using sendmmsg? + return nil +} + +func (tap *NativeTap) Read(buf []byte, offset int) (n int, err error) { + select { + case err = <-tap.errors: + default: + n, err = tap.tapFile.Read(buf[offset:]) + if errors.Is(err, syscall.EBADFD) { + err = os.ErrClosed + } + + } + return +} + +func (tap *NativeTap) Events() chan Event { + return tap.events +} + +func (tap *NativeTap) Close() error { + var err1, err2 error + tap.closeOnce.Do(func() { + if tap.statusListenersShutdown != nil { + close(tap.statusListenersShutdown) + if tap.netlinkCancel != nil { + err1 = tap.netlinkCancel.Cancel() + } + } else if tap.events != nil { + close(tap.events) + } + err2 = tap.tapFile.Close() + }) + if err1 != nil { + return err1 + } + return err2 +} + +func CreateTAP(iconfig config.InterfaceConf) (Device, error) { + nfd, err := unix.Open(cloneDevicePath, os.O_RDWR, 0) + if err != nil { + if os.IsNotExist(err) { + return nil, fmt.Errorf("CreateTAP(%q) failed; %s does not exist", iconfig.Name, cloneDevicePath) + } + return nil, err + } + + var ifr [ifReqSize]byte + var flags uint16 = unix.IFF_TAP | unix.IFF_NO_PI // (disabled for TUN status hack) + if err != nil { + fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix) + return nil, err + } + nameBytes := []byte(iconfig.Name) + if len(nameBytes) >= unix.IFNAMSIZ { + return nil, fmt.Errorf("interface name too long: %w", unix.ENAMETOOLONG) + } + copy(ifr[:], nameBytes) + *(*uint16)(unsafe.Pointer(&ifr[unix.IFNAMSIZ])) = flags + + _, _, errno := unix.Syscall( + unix.SYS_IOCTL, + uintptr(nfd), + uintptr(unix.TUNSETIFF), + uintptr(unsafe.Pointer(&ifr[0])), + ) + if errno != 0 { + return nil, errno + } + err = unix.SetNonblock(nfd, true) + + // Note that the above -- open,ioctl,nonblock -- must happen prior to handing it to netpoll as below this line. + + fd := os.NewFile(uintptr(nfd), cloneDevicePath) + if err != nil { + return nil, err + } + + return CreateTAPFromFile(fd, iconfig) +} + +func CreateTAPFromFile(file *os.File, iconfig config.InterfaceConf) (Device, error) { + tap := &NativeTap{ + tapFile: file, + events: make(chan Event, 5), + errors: make(chan error, 5), + statusListenersShutdown: make(chan struct{}), + nopi: false, + } + + name, err := tap.Name() + if err != nil { + return nil, err + } + + // start event listener + + tap.index, err = getIFIndex(name) + if err != nil { + return nil, err + } + + tap.netlinkSock, err = createNetlinkSocket() + if err != nil { + return nil, err + } + tap.netlinkCancel, err = rwcancel.NewRWCancel(tap.netlinkSock) + if err != nil { + unix.Close(tap.netlinkSock) + return nil, err + } + + tap.hackListenerClosed.Lock() + go tap.routineNetlinkListener() + go tap.routineHackListener() // cross namespace + + err = tap.setMTU(iconfig.MTU) + if err != nil { + unix.Close(tap.netlinkSock) + return nil, err + } + IfMacAddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID) + if err != nil { + fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix) + return nil, err + } + err = tap.setMacAddr(IfMacAddr) + if err != nil { + unix.Close(tap.netlinkSock) + return nil, err + } + return tap, nil +} + +func CreateUnmonitoredTUNFromFD(fd int) (Device, string, error) { + err := unix.SetNonblock(fd, true) + if err != nil { + return nil, "", err + } + file := os.NewFile(uintptr(fd), "/dev/tap") + tap := &NativeTap{ + tapFile: file, + events: make(chan Event, 5), + errors: make(chan error, 5), + nopi: true, + } + name, err := tap.Name() + if err != nil { + return nil, "", err + } + return tap, name, nil +} diff --git a/tap/tap_stdio.go b/tap/tap_stdio.go index 81caeb8..7920bcc 100644 --- a/tap/tap_stdio.go +++ b/tap/tap_stdio.go @@ -3,42 +3,71 @@ package tap import ( "fmt" "os" + + "github.com/KusakabeSi/EtherGuardVPN/config" ) +type L2MODE uint8 + +const ( + NoChange L2MODE = iota + KeyboardDebug //Register to server + BoardcastAndNodeID +) + +func GetL2Mode(mode string) L2MODE { + switch mode { + case "nochg": + return NoChange + case "kbdbg": + return KeyboardDebug + case "noL2": + return BoardcastAndNodeID + } + return NoChange +} + type StdIOTap struct { - name string - mtu int - HumanFriendly bool - events chan Event + name string + mtu int + macaddr MacAddress + L2mode L2MODE + events chan Event } func Charform2mac(b byte) MacAddress { if b == 'b' { return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, 0xff} } - return MacAddress{0xff, 0xff, 0xff, 0xff, 0xff, b - 48} + return MacAddress{0x00, 0x11, 0xff, 0xff, 0xff, b - 48} } func Mac2charForm(m []byte) byte { var M MacAddress copy(M[:], m) - if IsBoardCast(M) { + if IsNotUnicast(M) { return 'b' } return m[5] + 48 } // New creates and returns a new TUN interface for the application. -func CreateStdIOTAP(interfaceName string, HumanFriendly bool) (tapdev Device, err error) { +func CreateStdIOTAP(iconfig config.InterfaceConf) (tapdev Device, err error) { // Setup TUN Config if err != nil { fmt.Println(err.Error()) } + macaddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID) + if err != nil { + fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix) + return nil, err + } tapdev = &StdIOTap{ - name: interfaceName, - mtu: 1500, - HumanFriendly: HumanFriendly, - events: make(chan Event, 1<<5), + name: iconfig.Name, + mtu: 1500, + macaddr: macaddr, + L2mode: GetL2Mode(iconfig.L2HeaderMode), + events: make(chan Event, 1<<5), } tapdev.Events() <- EventUp return @@ -48,7 +77,8 @@ func CreateStdIOTAP(interfaceName string, HumanFriendly bool) (tapdev Device, er // Packet on the interface. func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) { - if tap.HumanFriendly { + switch tap.L2mode { + case KeyboardDebug: size, err := os.Stdin.Read(buf[offset+10:]) packet := buf[offset:] src := Charform2mac(packet[11]) @@ -56,22 +86,36 @@ func (tap *StdIOTap) Read(buf []byte, offset int) (int, error) { copy(packet[0:6], dst[:]) copy(packet[6:12], src[:]) return size - 2 + 12, err - } else { + case BoardcastAndNodeID: + size, err := os.Stdin.Read(buf[offset+12:]) + packet := buf[offset:] + src := tap.macaddr + dst := Charform2mac('b') + copy(packet[0:6], dst[:]) + copy(packet[6:12], src[:]) + return size + 12, err + default: size, err := os.Stdin.Read(buf[offset:]) return size, err } } // read a packet from the device (without any additional headers) func (tap *StdIOTap) Write(buf []byte, offset int) (size int, err error) { packet := buf[offset:] - if tap.HumanFriendly { + switch tap.L2mode { + case KeyboardDebug: src := Mac2charForm(packet[6:12]) dst := Mac2charForm(packet[0:6]) packet[10] = dst packet[11] = src - packet = packet[10:] + size, err = os.Stdout.Write(packet[10:]) + return + case BoardcastAndNodeID: + size, err = os.Stdout.Write(packet[12:]) + return + default: + size, err = os.Stdout.Write(packet) + return } - size, err = os.Stdout.Write(packet) - return } // writes a packet to the device (without any additional headers) func (tap *StdIOTap) Flush() error { return nil diff --git a/tap/tap_udpsock.go b/tap/tap_udpsock.go index c2f8f6d..3f288bb 100644 --- a/tap/tap_udpsock.go +++ b/tap/tap_udpsock.go @@ -3,32 +3,41 @@ package tap import ( "fmt" "net" + + "github.com/KusakabeSi/EtherGuardVPN/config" ) type UdpSockTap struct { - name string - mtu int - recv *net.UDPConn - send *net.UDPAddr - HumanFriendly bool - events chan Event + name string + mtu int + recv *net.UDPConn + send *net.UDPAddr + L2mode L2MODE + macaddr MacAddress + events chan Event } // New creates and returns a new TUN interface for the application. -func CreateUDPSockTAP(interfaceName string, listenAddr *net.UDPAddr, sendAddr *net.UDPAddr, HumanFriendly bool) (tapdev Device, err error) { +func CreateUDPSockTAP(iconfig config.InterfaceConf, listenAddr *net.UDPAddr, sendAddr *net.UDPAddr) (tapdev Device, err error) { // Setup TUN Config listener, err := net.ListenUDP("udp", listenAddr) if err != nil { fmt.Println(err.Error()) } + macaddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID) + if err != nil { + fmt.Println("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix) + return nil, err + } tapdev = &UdpSockTap{ - name: interfaceName, - mtu: 1500, - recv: listener, - send: sendAddr, - HumanFriendly: HumanFriendly, - events: make(chan Event, 1<<5), + name: iconfig.Name, + mtu: 1500, + recv: listener, + send: sendAddr, + macaddr: macaddr, + L2mode: GetL2Mode(iconfig.L2HeaderMode), + events: make(chan Event, 1<<5), } tapdev.Events() <- EventUp return @@ -38,15 +47,24 @@ func CreateUDPSockTAP(interfaceName string, listenAddr *net.UDPAddr, sendAddr *n // Packet on the interface. func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) { - if tap.HumanFriendly { + switch tap.L2mode { + case KeyboardDebug: size, _, err := tap.recv.ReadFromUDP(buf[offset+10:]) packet := buf[offset:] src := Charform2mac(packet[11]) dst := Charform2mac(packet[10]) copy(packet[0:6], dst[:]) copy(packet[6:12], src[:]) - return size - 2 + 12, err - } else { + return size + 10, err + case BoardcastAndNodeID: + size, _, err := tap.recv.ReadFromUDP(buf[offset+12:]) + packet := buf[offset:] + src := tap.macaddr + dst := Charform2mac('b') + copy(packet[0:6], dst[:]) + copy(packet[6:12], src[:]) + return size + 12, err + default: size, _, err := tap.recv.ReadFromUDP(buf[offset:]) return size, err } @@ -54,16 +72,21 @@ func (tap *UdpSockTap) Read(buf []byte, offset int) (int, error) { } // read a packet from the device (without any additional headers) func (tap *UdpSockTap) Write(buf []byte, offset int) (size int, err error) { packet := buf[offset:] - if tap.HumanFriendly { + switch tap.L2mode { + case KeyboardDebug: src := Mac2charForm(packet[6:12]) dst := Mac2charForm(packet[0:6]) packet[10] = dst packet[11] = src size, err = tap.recv.WriteToUDP(packet[10:], tap.send) return + case BoardcastAndNodeID: + size, err = tap.recv.WriteToUDP(packet[12:], tap.send) + return + default: + size, err = tap.recv.WriteToUDP(packet, tap.send) + return } - size, err = tap.recv.WriteToUDP(packet, tap.send) - return } // writes a packet to the device (without any additional headers) func (tap *UdpSockTap) Flush() error { return nil diff --git a/tap/tap_vpp.go b/tap/tap_vpp.go index 0eb5d8b..f566844 100644 --- a/tap/tap_vpp.go +++ b/tap/tap_vpp.go @@ -2,6 +2,7 @@ package tap import ( "context" + "path" "errors" "fmt" @@ -58,7 +59,7 @@ type VppTap struct { } // New creates and returns a new TUN interface for the application. -func CreateVppTAP(interfaceName string, iconfig config.InterfaceConf, loglevel string) (tapdev Device, err error) { +func CreateVppTAP(iconfig config.InterfaceConf, loglevel string) (tapdev Device, err error) { // Setup TUN Config // Set logger log := logger.New() @@ -75,10 +76,20 @@ func CreateVppTAP(interfaceName string, iconfig config.InterfaceConf, loglevel s return logger.ErrorLevel }() libmemif.SetLogger(log) + if os.Getenv(ENV_VPP_MEMIF_SOCKET_DIR) != "" { + vppMemifSocketDir = os.Getenv(ENV_VPP_MEMIF_SOCKET_DIR) + } + if os.Getenv(ENV_VPP_SOCKET_PATH) != "" { + vppApiSocketPath = os.Getenv(ENV_VPP_SOCKET_PATH) + } + if err := os.MkdirAll(vppMemifSocketDir, 0755); err != nil { + log.Fatalln("ERROR: Failed to create VPP memif socket folder " + vppMemifSocketDir) + return nil, err + } // connect to VPP conn, err := govpp.Connect(vppApiSocketPath) if err != nil { - log.Fatalln("ERROR: connecting to VPP failed:", err) + log.Fatalln("ERROR: Connecting to VPP failed:", err) return nil, err } defer conn.Disconnect() @@ -105,18 +116,19 @@ func CreateVppTAP(interfaceName string, iconfig config.InterfaceConf, loglevel s l2service := l2.NewServiceClient(conn) interfacservice := interfaces.NewServiceClient(conn) - vppIfMacAddr, err := ethernet_types.ParseMacAddress(iconfig.MacAddr) + IfMacAddr, err := GetMacAddr(iconfig.MacAddrPrefix, iconfig.VPPIfaceID) if err != nil { - log.Fatalln("ERROR: Failed parse mac address:", iconfig.MacAddr) + log.Fatalln("ERROR: Failed parse mac address:", iconfig.MacAddrPrefix) return nil, err } + vppIfMacAddr := ethernet_types.MacAddress(IfMacAddr) tap := &VppTap{ name: iconfig.Name, mtu: iconfig.MTU, ifuid: iconfig.VPPIfaceID, SwIfIndex: 0, - memifSockPath: vppMemifSocketDir + "/" + iconfig.Name, + memifSockPath: path.Join(vppMemifSocketDir, iconfig.Name+".sock"), secret: config.RandomStr(16, iconfig.Name), logger: log, errors: make(chan error, 1<<5),