Cancelable netlink writes and better response correlation

This commit is contained in:
Jason A. Donenfeld 2018-05-14 14:18:26 +02:00
parent 795f76cffa
commit 021724a535

View file

@ -545,7 +545,11 @@ func receive6(sock int, buff []byte, end *NativeEndpoint) (int, error) {
} }
func (bind *NativeBind) routineRouteListener(device *Device) { func (bind *NativeBind) routineRouteListener(device *Device) {
var reqPeer map[uint32]*Peer type peerEndpointPtr struct {
peer *Peer
endpoint *Endpoint
}
var reqPeer map[uint32]peerEndpointPtr
defer unix.Close(bind.netlinkSock) defer unix.Close(bind.netlinkSock)
@ -594,34 +598,28 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
if reqPeer == nil { if reqPeer == nil {
break break
} }
peer, ok := reqPeer[hdr.Seq] pePtr, ok := reqPeer[hdr.Seq]
if !ok { if !ok {
break break
} }
peer.mutex.RLock() pePtr.peer.mutex.Lock()
if peer.endpoint == nil || peer.endpoint.(*NativeEndpoint) == nil { if &pePtr.peer.endpoint != pePtr.endpoint {
peer.mutex.RUnlock() pePtr.peer.mutex.Unlock()
break break
} }
if peer.endpoint.(*NativeEndpoint).isV6 || peer.endpoint.(*NativeEndpoint).src4().ifindex == 0 { if uint32(pePtr.peer.endpoint.(*NativeEndpoint).src4().ifindex) == ifidx {
peer.mutex.RUnlock() pePtr.peer.mutex.Unlock()
break break
} }
if uint32(peer.endpoint.(*NativeEndpoint).src4().ifindex) == ifidx { pePtr.peer.endpoint.(*NativeEndpoint).ClearSrc()
peer.mutex.RUnlock() pePtr.peer.mutex.Unlock()
break
}
peer.mutex.RUnlock()
peer.mutex.Lock()
peer.endpoint.(*NativeEndpoint).ClearSrc()
peer.mutex.Unlock()
} }
attr = attr[attrhdr.Len:] attr = attr[attrhdr.Len:]
} }
} }
break break
} }
reqPeer = make(map[uint32]*Peer) reqPeer = make(map[uint32]peerEndpointPtr)
go func() { go func() {
device.peers.mutex.RLock() device.peers.mutex.RLock()
i := uint32(1) i := uint32(1)
@ -672,10 +670,16 @@ func (bind *NativeBind) routineRouteListener(device *Device) {
uint32(bind.lastMark), uint32(bind.lastMark),
} }
nlmsg.hdr.Len = uint32(unsafe.Sizeof(nlmsg)) nlmsg.hdr.Len = uint32(unsafe.Sizeof(nlmsg))
reqPeer[i] = peer reqPeer[i] = peerEndpointPtr{
peer: peer,
endpoint: &peer.endpoint,
}
peer.mutex.RUnlock() peer.mutex.RUnlock()
i++ i++
unix.Write(bind.netlinkSock, (*[unsafe.Sizeof(nlmsg)]byte)(unsafe.Pointer(&nlmsg))[:]) _, err := bind.netlinkCancel.Write((*[unsafe.Sizeof(nlmsg)]byte)(unsafe.Pointer(&nlmsg))[:])
if err != nil {
break
}
} }
device.peers.mutex.RUnlock() device.peers.mutex.RUnlock()
}() }()