mirror of
https://github.com/tailscale/tailscale.git
synced 2025-04-21 22:21:41 +00:00
wgengine, wgengine/filter: minor doc, style, performance, locking changes
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
parent
6284454ae5
commit
2e420ad8b6
@ -2,6 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package filter contains a stateful packet filter.
|
||||||
package filter
|
package filter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -17,14 +18,17 @@ import (
|
|||||||
|
|
||||||
type filterState struct {
|
type filterState struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
lru *lru.Cache
|
lru *lru.Cache // of tuple
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter is a stateful packet filter.
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
matches Matches
|
matches Matches
|
||||||
state *filterState
|
state *filterState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Response is a verdict: either a Drop, Accept, or noVerdict skip to
|
||||||
|
// continue processing.
|
||||||
type Response int
|
type Response int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -46,6 +50,7 @@ func (r Response) String() string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunFlags controls the filter's debug log verbosity at runtime.
|
||||||
type RunFlags int
|
type RunFlags int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -62,27 +67,34 @@ type tuple struct {
|
|||||||
DstPort uint16
|
DstPort uint16
|
||||||
}
|
}
|
||||||
|
|
||||||
const LRU_MAX = 512 // max entries in UDP LRU cache
|
const lruMax = 512 // max entries in UDP LRU cache
|
||||||
|
|
||||||
|
// MatchAllowAll matches all packets.
|
||||||
var MatchAllowAll = Matches{
|
var MatchAllowAll = Matches{
|
||||||
Match{[]IPPortRange{IPPortRangeAny}, []IP{IPAny}},
|
Match{[]IPPortRange{IPPortRangeAny}, []IP{IPAny}},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAllowAll returns a packet filter that accepts everything.
|
||||||
func NewAllowAll() *Filter {
|
func NewAllowAll() *Filter {
|
||||||
return New(MatchAllowAll, nil)
|
return New(MatchAllowAll, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewAllowNone returns a packet filter that rejects everything.
|
||||||
func NewAllowNone() *Filter {
|
func NewAllowNone() *Filter {
|
||||||
return New(nil, nil)
|
return New(nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New creates a new packet Filter with the given Matches rules.
|
||||||
|
// If shareStateWith is non-nil, the returned filter shares state
|
||||||
|
// with the previous one, to enable rules to be changed at runtime
|
||||||
|
// without breaking existing flows.
|
||||||
func New(matches Matches, shareStateWith *Filter) *Filter {
|
func New(matches Matches, shareStateWith *Filter) *Filter {
|
||||||
var state *filterState
|
var state *filterState
|
||||||
if shareStateWith != nil {
|
if shareStateWith != nil {
|
||||||
state = shareStateWith.state
|
state = shareStateWith.state
|
||||||
} else {
|
} else {
|
||||||
state = &filterState{
|
state = &filterState{
|
||||||
lru: lru.New(LRU_MAX),
|
lru: lru.New(lruMax),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
f := &Filter{
|
f := &Filter{
|
||||||
@ -200,9 +212,10 @@ func (f *Filter) runOut(q *packet.QDecode) (r Response, why string) {
|
|||||||
// TODO(apenwarr): create sessions on ICMP Echo Request too.
|
// TODO(apenwarr): create sessions on ICMP Echo Request too.
|
||||||
if q.IPProto == packet.UDP {
|
if q.IPProto == packet.UDP {
|
||||||
t := tuple{q.DstIP, q.SrcIP, q.DstPort, q.SrcPort}
|
t := tuple{q.DstIP, q.SrcIP, q.DstPort, q.SrcPort}
|
||||||
|
var ti interface{} = t // allocate once, rather than twice inside mutex
|
||||||
|
|
||||||
f.state.mu.Lock()
|
f.state.mu.Lock()
|
||||||
f.state.lru.Add(t, t)
|
f.state.lru.Add(ti, ti)
|
||||||
f.state.mu.Unlock()
|
f.state.mu.Unlock()
|
||||||
}
|
}
|
||||||
return Accept, "ok out"
|
return Accept, "ok out"
|
||||||
|
@ -36,19 +36,21 @@ type userspaceEngine struct {
|
|||||||
router Router
|
router Router
|
||||||
magicConn *magicsock.Conn
|
magicConn *magicsock.Conn
|
||||||
linkMon *monitor.Mon
|
linkMon *monitor.Mon
|
||||||
filt *filter.Filter
|
|
||||||
|
|
||||||
wgLock sync.Mutex // serializes all wgdev operations
|
wgLock sync.Mutex // serializes all wgdev operations; see lock order comment below
|
||||||
lastReconfig string
|
lastReconfig string
|
||||||
lastCfg wgcfg.Config
|
lastCfg wgcfg.Config
|
||||||
lastRoutes string
|
lastRoutes string
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex // guards following; see lock order comment below
|
||||||
|
filt *filter.Filter
|
||||||
statusCallback StatusCallback
|
statusCallback StatusCallback
|
||||||
peerSequence []wgcfg.Key
|
peerSequence []wgcfg.Key
|
||||||
endpoints []string
|
endpoints []string
|
||||||
pingers map[wgcfg.Key]context.CancelFunc // mu must be held to call CancelFunc
|
pingers map[wgcfg.Key]context.CancelFunc // mu must be held to call CancelFunc
|
||||||
linkState *interfaces.State
|
linkState *interfaces.State
|
||||||
|
|
||||||
|
// Lock ordering: wgLock, then mu.
|
||||||
}
|
}
|
||||||
|
|
||||||
type Loggify struct {
|
type Loggify struct {
|
||||||
@ -382,12 +384,12 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, dnsDomains []string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *userspaceEngine) GetFilter() *filter.Filter {
|
func (e *userspaceEngine) GetFilter() *filter.Filter {
|
||||||
|
e.mu.Lock()
|
||||||
|
defer e.mu.Unlock()
|
||||||
return e.filt
|
return e.filt
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *userspaceEngine) SetFilter(filt *filter.Filter) {
|
func (e *userspaceEngine) SetFilter(filt *filter.Filter) {
|
||||||
e.filt = filt
|
|
||||||
|
|
||||||
var filtin, filtout func(b []byte) device.FilterResult
|
var filtin, filtout func(b []byte) device.FilterResult
|
||||||
if filt == nil {
|
if filt == nil {
|
||||||
e.logf("wgengine: nil filter provided; no access restrictions.\n")
|
e.logf("wgengine: nil filter provided; no access restrictions.\n")
|
||||||
@ -429,6 +431,10 @@ func (e *userspaceEngine) SetFilter(filt *filter.Filter) {
|
|||||||
defer e.wgLock.Unlock()
|
defer e.wgLock.Unlock()
|
||||||
|
|
||||||
e.wgdev.SetFilterInOut(filtin, filtout)
|
e.wgdev.SetFilterInOut(filtin, filtout)
|
||||||
|
|
||||||
|
e.mu.Lock()
|
||||||
|
e.filt = filt
|
||||||
|
e.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *userspaceEngine) SetStatusCallback(cb StatusCallback) {
|
func (e *userspaceEngine) SetStatusCallback(cb StatusCallback) {
|
||||||
|
@ -101,7 +101,7 @@ type Engine interface {
|
|||||||
// sends an updated network map.
|
// sends an updated network map.
|
||||||
Reconfig(cfg *wgcfg.Config, dnsDomains []string) error
|
Reconfig(cfg *wgcfg.Config, dnsDomains []string) error
|
||||||
|
|
||||||
// GetFilter returns the current packet filter, if any
|
// GetFilter returns the current packet filter, if any.
|
||||||
GetFilter() *filter.Filter
|
GetFilter() *filter.Filter
|
||||||
|
|
||||||
// SetFilter updates the packet filter.
|
// SetFilter updates the packet filter.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user