github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/shaper/shaper_linux.go (about) 1 /* 2 * Copyright (C) 2019 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package shaper 19 20 import ( 21 "github.com/pkg/errors" 22 "github.com/rs/zerolog/log" 23 24 "github.com/mysteriumnetwork/go-wondershaper/wondershaper" 25 "github.com/mysteriumnetwork/node/config" 26 ) 27 28 type linuxShaper struct { 29 ws *wondershaper.Shaper 30 listener eventListener 31 listenTopic string 32 } 33 34 type linuxShaperNoop struct{} 35 36 func (s *linuxShaperNoop) Start(interfaceName string) error { 37 return nil 38 } 39 40 func (s *linuxShaperNoop) Clear(interfaceName string) { 41 return 42 } 43 44 func create(listener eventListener) Shaper { 45 // return a noop filter if userspace flag is set 46 if config.GetBool(config.FlagUserspace) { 47 return &linuxShaperNoop{} 48 } 49 50 ws := wondershaper.New() 51 ws.Stdout = log.Logger 52 ws.Stderr = log.Logger 53 return &linuxShaper{ 54 ws: ws, 55 listener: listener, 56 listenTopic: config.AppTopicConfig(config.FlagShaperEnabled.Name), 57 } 58 } 59 60 // Start applies shaping configuration on the specified interface and then continuously ensures it. 61 func (s *linuxShaper) Start(interfaceName string) error { 62 applyLimits := func() error { 63 s.ws.Clear(interfaceName) 64 65 if config.GetBool(config.FlagShaperEnabled) { 66 err := s.ws.LimitDownlink(interfaceName, int(config.GetUInt64(config.FlagShaperBandwidth))*8) 67 if err != nil { 68 log.Error().Err(err).Msg("Could not limit download speed") 69 return err 70 } 71 err = s.ws.LimitUplink(interfaceName, int(config.GetUInt64(config.FlagShaperBandwidth))*8) 72 if err != nil { 73 log.Error().Err(err).Msg("Could not limit upload speed") 74 return err 75 } 76 } 77 return nil 78 } 79 80 err := s.listener.SubscribeAsync(s.listenTopic, applyLimits) 81 if err != nil { 82 return errors.Wrap(err, "could not subscribe to topic: "+s.listenTopic) 83 } 84 85 return applyLimits() 86 } 87 88 // Clear clears shaping rules. 89 func (s *linuxShaper) Clear(interfaceName string) { 90 s.ws.Clear(interfaceName) 91 }