From ec63f38ba2bbc3b2c9ec82abffef3c798201458e Mon Sep 17 00:00:00 2001 From: testscript Date: Tue, 21 Feb 2023 20:51:28 +0800 Subject: [PATCH] fix sendpacket race condition --- .vscode/launch.json | 5 +- device/device.go | 11 ++-- device/receive.go | 14 ++--- device/receivesendproc.go | 51 +++++++++++++----- device/send.go | 22 +++----- .../super_mode/.EgNet_edge002.yaml.swp | Bin 0 -> 12288 bytes example_config/super_mode/README.md | 6 +-- example_config/super_mode/README_zh.md | 6 +-- mtypes/config.go | 1 + 9 files changed, 72 insertions(+), 44 deletions(-) create mode 100644 example_config/super_mode/.EgNet_edge002.yaml.swp diff --git a/.vscode/launch.json b/.vscode/launch.json index d7c442c..283fdae 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -22,7 +22,9 @@ "program": "${workspaceFolder}", "buildFlags": "-tags 'novpp'", "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, - "args":["-config","example_config/p2p_mode/EgNet_edge4.yaml","-mode","edge"/*,"-example"*/], + "args":["-config","example_config/super_mode/EgNet_edge002.yaml","-mode","edge"/*,"-example"*/], + "asRoot": true, + "console": "integratedTerminal", }, { "name": "Launch GenCfg", @@ -44,5 +46,6 @@ "env": {"CGO_CFLAGS":"-I/usr/include/memif"}, "args":["-config","example_config/static_mode/path.txt","-mode","solve"], } + ] } \ No newline at end of file diff --git a/device/device.go b/device/device.go index 2054b97..66a1e1d 100644 --- a/device/device.go +++ b/device/device.go @@ -77,6 +77,7 @@ type Device struct { state_hashes mtypes.StateHash event_tryendpoint chan struct{} + chan_send_packet chan *packet_send_params EdgeConfigPath string EdgeConfig *mtypes.EdgeConfig @@ -137,10 +138,9 @@ type IdAndTime struct { // There are three states: down, up, closed. // Transitions: // -// down -----+ -// ↑↓ ↓ -// up -> closed -// +// down -----+ +// ↑↓ ↓ +// up -> closed type deviceState uint32 //go:generate go run golang.org/x/tools/cmd/stringer -type deviceState -trimprefix=deviceState @@ -355,6 +355,7 @@ func NewDevice(tapDevice tap.Device, id mtypes.Vertex, bind conn.Bind, logger *L device.indexTable.Init() device.PopulatePools() device.Chan_Device_Initialized = make(chan struct{}, 1<<5) + device.chan_send_packet = make(chan *packet_send_params, 1<<15) if IsSuperNode { device.SuperConfigPath = configpath device.SuperConfig = sconfig @@ -378,7 +379,7 @@ func NewDevice(tapDevice tap.Device, id mtypes.Vertex, bind conn.Bind, logger *L device.SuperConfig.DampingFilterRadius = device.EdgeConfig.DynamicRoute.DampingFilterRadius } - + go device.RoutineSendPacket() go func() { <-device.Chan_Device_Initialized if device.LogLevel.LogInternal { diff --git a/device/receive.go b/device/receive.go index ef16929..dce343f 100644 --- a/device/receive.go +++ b/device/receive.go @@ -17,14 +17,14 @@ import ( "sync/atomic" "time" - "github.com/google/gopacket" - "github.com/google/gopacket/layers" "golang.org/x/crypto/chacha20poly1305" "github.com/KusakabeSi/EtherGuard-VPN/conn" "github.com/KusakabeSi/EtherGuard-VPN/mtypes" "github.com/KusakabeSi/EtherGuard-VPN/path" "github.com/KusakabeSi/EtherGuard-VPN/tap" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" ) type QueueHandshakeElement struct { @@ -563,12 +563,12 @@ func (peer *Peer) RoutineSequentialReceiver() { } else { l2ttl = l2ttl - 1 if dst_nodeID == mtypes.NodeID_Broadcast { //Regular transfer algorithm - device.TransitBoardcastPacket(src_nodeID, peer.ID, elem.Type, l2ttl, elem.packet, MessageTransportOffsetContent) + go device.TransitBoardcastPacket(src_nodeID, peer.ID, elem.Type, l2ttl, elem.packet, MessageTransportOffsetContent) } else if dst_nodeID == mtypes.NodeID_Spread { // Control Message will try send to every know node regardless the connectivity skip_list := make(map[mtypes.Vertex]bool) skip_list[src_nodeID] = true //Don't send to conimg peer and source peer skip_list[peer.ID] = true - device.SpreadPacket(skip_list, elem.Type, l2ttl, elem.packet, MessageTransportOffsetContent) + go device.SpreadPacket(skip_list, elem.Type, l2ttl, elem.packet, MessageTransportOffsetContent) } else { next_id := device.graph.Next(device.ID, dst_nodeID) @@ -612,8 +612,10 @@ func (peer *Peer) RoutineSequentialReceiver() { if device.LogLevel.LogNormal { packet_len := len(elem.packet) - path.EgHeaderLen fmt.Printf("Normal: Recv Len:%v S:%v D:%v TTL:%v From:%v IP:%v:\n", strconv.Itoa(packet_len), src_nodeID.ToString(), dst_nodeID.ToString(), elem.TTL, peer.ID.ToString(), peer.GetEndpointDstStr()) - packet := gopacket.NewPacket(elem.packet[path.EgHeaderLen:], layers.LayerTypeEthernet, gopacket.Default) - fmt.Println(packet.Dump()) + if device.LogLevel.DumpNormal { + packet := gopacket.NewPacket(elem.packet[path.EgHeaderLen:], layers.LayerTypeEthernet, gopacket.Default) + fmt.Println(packet.Dump()) + } } src_macaddr := tap.GetSrcMacAddr(elem.packet[path.EgHeaderLen:]) if !tap.IsNotUnicast(src_macaddr) { diff --git a/device/receivesendproc.go b/device/receivesendproc.go index d5378b9..162d9e0 100644 --- a/device/receivesendproc.go +++ b/device/receivesendproc.go @@ -29,6 +29,14 @@ import ( "github.com/google/gopacket/layers" ) +type packet_send_params struct { + peer *Peer + usage path.Usage + ttl uint8 + packet []byte + offset int +} + func (device *Device) SendPacket(peer *Peer, usage path.Usage, ttl uint8, packet []byte, offset int) { if peer == nil { return @@ -48,8 +56,10 @@ func (device *Device) SendPacket(peer *Peer, usage path.Usage, ttl uint8, packet dst_nodeID := EgHeader.GetDst() packet_len := len(packet) - path.EgHeaderLen fmt.Printf("Normal: Send Len:%v S:%v D:%v TTL:%v To:%v IP:%v:\n", packet_len, device.ID.ToString(), dst_nodeID.ToString(), ttl, peer.ID.ToString(), peer.GetEndpointDstStr()) - packet := gopacket.NewPacket(packet[path.EgHeaderLen:], layers.LayerTypeEthernet, gopacket.Default) - fmt.Println(packet.Dump()) + if device.LogLevel.DumpNormal { + packet_dump := gopacket.NewPacket(packet[path.EgHeaderLen:], layers.LayerTypeEthernet, gopacket.Default) + fmt.Println(packet_dump.Dump()) + } } } if device.LogLevel.LogControl { @@ -63,16 +73,32 @@ func (device *Device) SendPacket(peer *Peer, usage path.Usage, ttl uint8, packet } } - var elem *QueueOutboundElement - elem = device.NewOutboundElement() - copy(elem.buffer[offset:offset+len(packet)], packet) - elem.Type = usage - elem.TTL = ttl - elem.packet = elem.buffer[offset : offset+len(packet)] - if peer.isRunning.Get() { - peer.StagePacket(elem) - elem = nil - peer.SendStagedPackets() + device.chan_send_packet <- &packet_send_params{ + peer: peer, + usage: usage, + ttl: ttl, + packet: packet, + offset: offset, + } +} + +func (device *Device) RoutineSendPacket() { + for { + var elem *QueueOutboundElement + elem = device.NewOutboundElement() + params := <-device.chan_send_packet + offset := params.offset + packet := params.packet + peer := params.peer + copy(elem.buffer[offset:offset+len(packet)], packet) + elem.Type = params.usage + elem.TTL = params.ttl + elem.packet = elem.buffer[offset : offset+len(packet)] + if peer.isRunning.Get() { + peer.StagePacket(elem) + elem = nil + peer.SendStagedPackets() + } } } @@ -82,6 +108,7 @@ func (device *Device) BoardcastPacket(skip_list map[mtypes.Vertex]bool, usage pa send_list[node_id] = false } device.peers.RLock() + fmt.Printf("Transit: Boardcast to %v\n", send_list) for node_id, should_send := range send_list { if should_send { peer_out := device.peers.IDMap[node_id] diff --git a/device/send.go b/device/send.go index 03501ae..2d7bab0 100644 --- a/device/send.go +++ b/device/send.go @@ -219,15 +219,11 @@ func (device *Device) RoutineReadFromTUN() { device.log.Verbosef("Routine: TUN reader - started") - var elem *QueueOutboundElement + elem := &QueueOutboundElement{ + buffer: &[MaxMessageSize]byte{}, + } for { - if elem != nil { - device.PutMessageBuffer(elem.buffer) - device.PutOutboundElement(elem) - } - elem = device.NewOutboundElement() - // read packet offset := MessageTransportHeaderSize @@ -288,14 +284,12 @@ func (device *Device) RoutineReadFromTUN() { if device.LogLevel.LogNormal { packet_len := len(elem.packet) - path.EgHeaderLen fmt.Printf("Normal: Send Len:%v S:%v D:%v TTL:%v To:%v IP:%v:\n", packet_len, device.ID.ToString(), dst_nodeID.ToString(), elem.TTL, peer.ID.ToString(), peer.GetEndpointDstStr()) - packet := gopacket.NewPacket(elem.packet[path.EgHeaderLen:], layers.LayerTypeEthernet, gopacket.Default) - fmt.Println(packet.Dump()) - } - if peer.isRunning.Get() { - peer.StagePacket(elem) - elem = nil - peer.SendStagedPackets() + if device.LogLevel.DumpNormal { + packet_dump := gopacket.NewPacket(elem.packet[path.EgHeaderLen:], layers.LayerTypeEthernet, gopacket.Default) + fmt.Println(packet_dump.Dump()) + } } + device.SendPacket(peer, elem.Type, elem.TTL, elem.packet, offset) } } else { device.BoardcastPacket(make(map[mtypes.Vertex]bool, 0), elem.Type, elem.TTL, elem.packet, offset) diff --git a/example_config/super_mode/.EgNet_edge002.yaml.swp b/example_config/super_mode/.EgNet_edge002.yaml.swp new file mode 100644 index 0000000000000000000000000000000000000000..845ae01951afa0d8db64866c021b1047a9245a35 GIT binary patch literal 12288 zcmeI2PmCi+6~=1=`9sJiE5ad2LFz0>8xgkM-EMn4Ek$8wJUioA+vy$KGn+-QDR-Cc z9=E%DtE=ttM2JXSB9M?c5N@2v6)B3u0l}3-iiD65;*tYg(838t35T5WRogQjydLEW zQT6DjcD+|suj;E;)rYCBaZqb$72PCwt`Ktcl4gt14%!lH6vTMQWA$td@)AGpl|JEo%~WOuzd>IMBmnk9_i9mPH? zZ1E)(*1@JH}l@D_LzyaDckJK!atgJ-}Oz`vd# zu5jsiS@Odt{%bOl(KK8wZi7MS}4$4IQm)7^KOL z#crImX*Xn!_Sz4KhUdB#i9{D!M0Jq{QGbw8o%xyWMRT_ZM$FW`FwT5ku*hSP(7kwc zt}zXRX%?L`iis{ejd_33&0zSTO~!ekq8B}AE9yxcho|;=Xls?xTxB#?8CUcur>aka z$d4!K`RPbA%XqBQ1Xlu=Jv0sI1)f#ab0vEr<;xwF^d9wCH;#u(5$uZ`#fu!)MGo^K zhpqSHxc|W9imT1mYO}f8ylibDCuO?k>)33&ZRi_k!qJMkr8SK_X<8)jx_ok9gC5UX zcT%KqCAZ-xI&n0?GX?{GZ{>G3XZ>s1KEq87{zTTBRS$k{Yn3|ktTd@)9A76r3+EzJJ3A6dw|Ysnj{O~j~0 zz4%OGbKa~q43fIM0$W=sr)fAh5_xWH<8teUTkCL~90MVe)F~8L-?nHH=#xQwlxJw+ zXm~ebViNNqoN(n~-K=|)O%KYBRv#JrJL~@K!_IVc=aoB?Y;f2*?(R05VcIV??8iVrT{gaU?R;;xqc!i{X_nS}x4c<+ftzJoY>qmI2RmiHwsX>N_l7qP zb_RjiKdjx}Ug`~vujSWw_3>yidZ%cY%JU#CjM&i*M}w1cYussW?sz9vBiK9Ijn?{| zovB%(gQHt1x5Jxz8~3W)#f@16NPi~sS^6z3m_Un;S(8oXr}I2PtGHN>|%7jAM~eW|>r{5gi5IKDHy1X;hE<=l2$hd36kNk#R6$ID*IjZEMDSv{bE) zU6clx*<1;8_oAjiAtNV&uZQZh8 zBz5aXZSzd3qWo}HS&w4tx7&3`vru-iJgxkSxuadZO5`SM(h)Xuel;Ao!gEutDwoib zDq6dY`i#$Z{IKhH`|}0BlFPHiTGI{unNG{q>TwW_sOO1y-t*9j8#9_hQc~nd_ErmMi*NSvLxn z^fjm_$8j2Bz3gmmI@K+wBzr$_-Ax|gsE{+YEqiXO-N0uopFHX;>4G7(rwNo2G$DB^ J$#0%RJ_Qac3s3+6 literal 0 HcmV?d00001 diff --git a/example_config/super_mode/README.md b/example_config/super_mode/README.md index 2396013..4a13abb 100644 --- a/example_config/super_mode/README.md +++ b/example_config/super_mode/README.md @@ -400,9 +400,9 @@ To avoid this issue, please use the external IP of the supernode in the edge con ## Quick start Run this example_config (please open three terminals): ```bash -./etherguard-go -config example_config/super_mode/Node_super.yaml -mode super -./etherguard-go -config example_config/super_mode/Node_edge001.yaml -mode edge -./etherguard-go -config example_config/super_mode/Node_edge002.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_super.yaml -mode super +./etherguard-go -config example_config/super_mode/EgNet_edge001.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge002.yaml -mode edge ``` Because it is in `stdio` mode, stdin will be read into the VPN network Please type in one of the edge windows diff --git a/example_config/super_mode/README_zh.md b/example_config/super_mode/README_zh.md index 2780685..d4dc12c 100644 --- a/example_config/super_mode/README_zh.md +++ b/example_config/super_mode/README_zh.md @@ -414,9 +414,9 @@ Relay node其實也是一個edge node,只不過被設定成為interface=dummy 在**不同terminal**分別執行以下命令 ```bash -./etherguard-go -config example_config/super_mode/Node_super.yaml -mode super -./etherguard-go -config example_config/super_mode/Node_edge001.yaml -mode edge -./etherguard-go -config example_config/super_mode/Node_edge002.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_super.yaml -mode super +./etherguard-go -config example_config/super_mode/EgNet_edge001.yaml -mode edge +./etherguard-go -config example_config/super_mode/EgNet_edge002.yaml -mode edge ``` 因為是stdio模式,stdin會讀入VPN網路 請在其中一個edge視窗中鍵入 diff --git a/mtypes/config.go b/mtypes/config.go index d549ba4..535646e 100644 --- a/mtypes/config.go +++ b/mtypes/config.go @@ -108,6 +108,7 @@ type LoggerInfo struct { LogLevel string `yaml:"LogLevel"` LogTransit bool `yaml:"LogTransit"` LogNormal bool `yaml:"LogNormal"` + DumpNormal bool `yaml:"DumpNormal"` LogControl bool `yaml:"LogControl"` LogInternal bool `yaml:"LogInternal"` LogNTP bool `yaml:"LogNTP"`