Move bytes rate limits to a different rlp key

This commit is contained in:
Andrea Maria Piana 2020-06-09 09:21:13 +02:00
parent c5577418b7
commit 35e95d1568
8 changed files with 72 additions and 38 deletions

View File

@ -66,8 +66,10 @@ type WakuHost interface {
LightClientModeConnectionRestricted() bool LightClientModeConnectionRestricted() bool
// ConfirmationsEnabled returns true if message confirmations are enabled. // ConfirmationsEnabled returns true if message confirmations are enabled.
ConfirmationsEnabled() bool ConfirmationsEnabled() bool
// RateLimits returns the current rate limits for the host // PacketRateLimits returns the current rate limits for the host
RateLimits() RateLimits PacketRateLimits() RateLimits
// BytesRateLimits returns the current rate limits for the host
BytesRateLimits() RateLimits
// MinPow returns the MinPow for the host // MinPow returns the MinPow for the host
MinPow() float64 MinPow() float64
// BloomFilterMode returns whether the host is using bloom filter // BloomFilterMode returns whether the host is using bloom filter

View File

@ -62,15 +62,12 @@ func (MetricsRateLimiterHandler) ExceedIPLimit() error {
} }
// RateLimits contains information about rate limit settings. // RateLimits contains information about rate limit settings.
// It is exchanged using rateLimitingCode packet or in the handshake. // It's agnostic on what it's being rate limited on (bytes or number of packets currently)
// It's exchanged with the status-update packet code
type RateLimits struct { type RateLimits struct {
PacketIPLimits uint64 // packets per second from a single IP (default 0, no limits) IPLimits uint64 // amount per second from a single IP (default 0, no limits)
PacketPeerIDLimits uint64 // packets per second from a single peer ID (default 0, no limits) PeerIDLimits uint64 // amount per second from a single peer ID (default 0, no limits)
PacketTopicLimits uint64 // packets per second from a single topic (default 0, no limits) TopicLimits uint64 // amount per second from a single topic (default 0, no limits)
BytesIPLimits uint64 // bytes per second from a single IP (default 0, no limits)
BytesPeerIDLimits uint64 // bytes per second from a single peer ID (default 0, no limits)
BytesTopicLimits uint64 // bytes per second from a single topic (default 0, no limits)
} }
func (r RateLimits) IsZero() bool { func (r RateLimits) IsZero() bool {
@ -125,10 +122,10 @@ var defaultPeerRateLimiterConfig = PeerRateLimiterConfig{
// PeerRateLimiter represents a rate limiter that limits communication between Peers // PeerRateLimiter represents a rate limiter that limits communication between Peers
type PeerRateLimiter struct { type PeerRateLimiter struct {
packetPeerIDThrottler *tb.Throttler packetPeerIDThrottler *tb.Throttler
packetIpThrottler *tb.Throttler packetIPThrottler *tb.Throttler
bytesPeerIDThrottler *tb.Throttler bytesPeerIDThrottler *tb.Throttler
bytesIpThrottler *tb.Throttler bytesIPThrottler *tb.Throttler
PacketLimitPerSecIP int64 PacketLimitPerSecIP int64
PacketLimitPerSecPeerID int64 PacketLimitPerSecPeerID int64
@ -150,9 +147,9 @@ func NewPeerRateLimiter(cfg *PeerRateLimiterConfig, handlers ...RateLimiterHandl
return &PeerRateLimiter{ return &PeerRateLimiter{
packetPeerIDThrottler: tb.NewThrottler(time.Millisecond * 100), packetPeerIDThrottler: tb.NewThrottler(time.Millisecond * 100),
packetIpThrottler: tb.NewThrottler(time.Millisecond * 100), packetIPThrottler: tb.NewThrottler(time.Millisecond * 100),
bytesPeerIDThrottler: tb.NewThrottler(time.Millisecond * 100), bytesPeerIDThrottler: tb.NewThrottler(time.Millisecond * 100),
bytesIpThrottler: tb.NewThrottler(time.Millisecond * 100), bytesIPThrottler: tb.NewThrottler(time.Millisecond * 100),
PacketLimitPerSecIP: cfg.PacketLimitPerSecIP, PacketLimitPerSecIP: cfg.PacketLimitPerSecIP,
PacketLimitPerSecPeerID: cfg.PacketLimitPerSecPeerID, PacketLimitPerSecPeerID: cfg.PacketLimitPerSecPeerID,
BytesLimitPerSecIP: cfg.BytesLimitPerSecIP, BytesLimitPerSecIP: cfg.BytesLimitPerSecIP,
@ -256,10 +253,10 @@ func (r *PeerRateLimiter) throttleIP(ip string, size uint32) bool {
var bytesLimiterResponse bool var bytesLimiterResponse bool
if r.PacketLimitPerSecIP != 0 { if r.PacketLimitPerSecIP != 0 {
packetLimiterResponse = r.packetIpThrottler.Halt(ip, 1, r.PacketLimitPerSecIP) packetLimiterResponse = r.packetIPThrottler.Halt(ip, 1, r.PacketLimitPerSecIP)
} }
if r.BytesLimitPerSecIP != 0 { if r.BytesLimitPerSecIP != 0 {
bytesLimiterResponse = r.bytesIpThrottler.Halt(ip, int64(size), r.BytesLimitPerSecIP) bytesLimiterResponse = r.bytesIPThrottler.Halt(ip, int64(size), r.BytesLimitPerSecIP)
} }
return packetLimiterResponse || bytesLimiterResponse return packetLimiterResponse || bytesLimiterResponse

View File

@ -135,7 +135,7 @@ func TestPeerBytesLimiterHandler(t *testing.T) {
msg, err := rw1.ReadMsg() msg, err := rw1.ReadMsg()
require.NoError(t, err) require.NoError(t, err)
require.EqualValues(t, 101, msg.Code) require.EqualValues(t, 101, msg.Code)
msg.Discard() require.NoError(t, msg.Discard())
} }
close(done) close(done)
}() }()

View File

@ -40,7 +40,7 @@ type StatusOptions struct {
func StatusOptionsFromHost(host common.WakuHost) StatusOptions { func StatusOptionsFromHost(host common.WakuHost) StatusOptions {
opts := StatusOptions{} opts := StatusOptions{}
rateLimits := host.RateLimits() rateLimits := host.PacketRateLimits()
opts.RateLimits = &rateLimits opts.RateLimits = &rateLimits
lightNode := host.LightClientMode() lightNode := host.LightClientMode()

View File

@ -48,8 +48,10 @@ type Peer struct {
// In that case no envelope is accepted. // In that case no envelope is accepted.
fullNode bool fullNode bool
confirmationsEnabled bool confirmationsEnabled bool
rateLimitsMu sync.Mutex packetRateLimitsMu sync.Mutex
rateLimits common.RateLimits packetRateLimits common.RateLimits
bytesRateLimitsMu sync.Mutex
bytesRateLimits common.RateLimits
known mapset.Set // Messages already known by the peer to avoid wasting bandwidth known mapset.Set // Messages already known by the peer to avoid wasting bandwidth
} }
@ -488,8 +490,11 @@ func (p *Peer) setOptions(peerOptions StatusOptions) error {
if peerOptions.ConfirmationsEnabled != nil { if peerOptions.ConfirmationsEnabled != nil {
p.confirmationsEnabled = *peerOptions.ConfirmationsEnabled p.confirmationsEnabled = *peerOptions.ConfirmationsEnabled
} }
if peerOptions.RateLimits != nil { if peerOptions.PacketRateLimits != nil {
p.setRateLimits(*peerOptions.RateLimits) p.setPacketRateLimits(*peerOptions.PacketRateLimits)
}
if peerOptions.BytesRateLimits != nil {
p.setBytesRateLimits(*peerOptions.BytesRateLimits)
} }
return nil return nil
@ -591,10 +596,16 @@ func (p *Peer) setTopicInterest(topicInterest []common.TopicType) {
p.bloomFilter = nil p.bloomFilter = nil
} }
func (p *Peer) setRateLimits(r common.RateLimits) { func (p *Peer) setPacketRateLimits(r common.RateLimits) {
p.rateLimitsMu.Lock() p.packetRateLimitsMu.Lock()
p.rateLimits = r p.packetRateLimits = r
p.rateLimitsMu.Unlock() p.packetRateLimitsMu.Unlock()
}
func (p *Peer) setBytesRateLimits(r common.RateLimits) {
p.bytesRateLimitsMu.Lock()
p.bytesRateLimits = r
p.bytesRateLimitsMu.Unlock()
} }
// topicOrBloomMatch matches against topic-interest if topic interest // topicOrBloomMatch matches against topic-interest if topic interest

View File

@ -34,15 +34,19 @@ type StatusOptions struct {
BloomFilter []byte `rlp:"key=1"` BloomFilter []byte `rlp:"key=1"`
LightNodeEnabled *bool `rlp:"key=2"` LightNodeEnabled *bool `rlp:"key=2"`
ConfirmationsEnabled *bool `rlp:"key=3"` ConfirmationsEnabled *bool `rlp:"key=3"`
RateLimits *common.RateLimits `rlp:"key=4"` PacketRateLimits *common.RateLimits `rlp:"key=4"`
TopicInterest []common.TopicType `rlp:"key=5"` TopicInterest []common.TopicType `rlp:"key=5"`
BytesRateLimits *common.RateLimits `rlp:"key=6"`
} }
func StatusOptionsFromHost(host common.WakuHost) StatusOptions { func StatusOptionsFromHost(host common.WakuHost) StatusOptions {
opts := StatusOptions{} opts := StatusOptions{}
rateLimits := host.RateLimits() packetRateLimits := host.PacketRateLimits()
opts.RateLimits = &rateLimits opts.PacketRateLimits = &packetRateLimits
bytesRateLimits := host.BytesRateLimits()
opts.BytesRateLimits = &bytesRateLimits
lightNode := host.LightClientMode() lightNode := host.LightClientMode()
opts.LightNodeEnabled = &lightNode opts.LightNodeEnabled = &lightNode
@ -114,8 +118,12 @@ func (o StatusOptions) WithDefaults() StatusOptions {
o.ConfirmationsEnabled = &confirmationsEnabled o.ConfirmationsEnabled = &confirmationsEnabled
} }
if o.RateLimits == nil { if o.PacketRateLimits == nil {
o.RateLimits = &common.RateLimits{} o.PacketRateLimits = &common.RateLimits{}
}
if o.BytesRateLimits == nil {
o.BytesRateLimits = &common.RateLimits{}
} }
if o.BloomFilter == nil { if o.BloomFilter == nil {

View File

@ -20,12 +20,17 @@ func TestEncodeDecodeRLP(t *testing.T) {
BloomFilter: common.TopicType{0xaa, 0xbb, 0xcc, 0xdd}.ToBloom(), BloomFilter: common.TopicType{0xaa, 0xbb, 0xcc, 0xdd}.ToBloom(),
LightNodeEnabled: &lightNodeEnabled, LightNodeEnabled: &lightNodeEnabled,
ConfirmationsEnabled: &confirmationsEnabled, ConfirmationsEnabled: &confirmationsEnabled,
RateLimits: &common.RateLimits{ PacketRateLimits: &common.RateLimits{
IPLimits: 10, IPLimits: 10,
PeerIDLimits: 5, PeerIDLimits: 5,
TopicLimits: 1, TopicLimits: 1,
}, },
TopicInterest: []common.TopicType{{0x01}, {0x02}, {0x03}, {0x04}}, TopicInterest: []common.TopicType{{0x01}, {0x02}, {0x03}, {0x04}},
BytesRateLimits: &common.RateLimits{
IPLimits: 10,
PeerIDLimits: 5,
TopicLimits: 1,
},
} }
data, err := rlp.EncodeToBytes(opts) data, err := rlp.EncodeToBytes(opts)
require.NoError(t, err) require.NoError(t, err)
@ -73,6 +78,7 @@ func TestInitRLPKeyFields(t *testing.T) {
3: 3, 3: 3,
4: 4, 4: 4,
5: 5, 5: 5,
6: 6,
} }
kfi := map[statusOptionKey]int{ kfi := map[statusOptionKey]int{
0: 0, 0: 0,
@ -81,6 +87,7 @@ func TestInitRLPKeyFields(t *testing.T) {
3: 3, 3: 3,
4: 4, 4: 4,
5: 5, 5: 5,
6: 6,
} }
// Test that the kfi length matches the inited global keyFieldIdx length // Test that the kfi length matches the inited global keyFieldIdx length

View File

@ -394,16 +394,25 @@ func (w *Waku) LightClientModeConnectionRestricted() bool {
return w.settings.RestrictLightClientsConn return w.settings.RestrictLightClientsConn
} }
// RateLimiting returns RateLimits information. // PacketRateLimiting returns RateLimits information for packets
func (w *Waku) RateLimits() common.RateLimits { func (w *Waku) PacketRateLimits() common.RateLimits {
if w.rateLimiter == nil { if w.rateLimiter == nil {
return common.RateLimits{} return common.RateLimits{}
} }
return common.RateLimits{ return common.RateLimits{
PacketIPLimits: uint64(w.rateLimiter.PacketLimitPerSecIP), IPLimits: uint64(w.rateLimiter.PacketLimitPerSecIP),
PacketPeerIDLimits: uint64(w.rateLimiter.PacketLimitPerSecPeerID), PeerIDLimits: uint64(w.rateLimiter.PacketLimitPerSecPeerID),
BytesIPLimits: uint64(w.rateLimiter.BytesLimitPerSecIP), }
BytesPeerIDLimits: uint64(w.rateLimiter.BytesLimitPerSecPeerID), }
// BytesRateLimiting returns RateLimits information for bytes
func (w *Waku) BytesRateLimits() common.RateLimits {
if w.rateLimiter == nil {
return common.RateLimits{}
}
return common.RateLimits{
IPLimits: uint64(w.rateLimiter.BytesLimitPerSecIP),
PeerIDLimits: uint64(w.rateLimiter.BytesLimitPerSecPeerID),
} }
} }