-
Notifications
You must be signed in to change notification settings - Fork 36.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce -maxuploadtarget #6622
Conversation
2e5be21
to
a86d41b
Compare
If a user wants to control the total amount transferred, then I don't think MB per day is a good unit to use. If they have a transfer cap, then it is most likely tied to a monthly billing cycle, so MB/month is likely better. (For example, I think Comcast in the US has a 250GB/month cap, so a Comcast customer might like to allow 100GB/month, or something like that.) |
Which could result in all of the 100GB being eaten up on the first few days of the timeframe. Maybe the owner restarts the server mid-month and then serves 200GB of historic blocks that month. |
Once combined with connection throttling, which would make the speed that the 100GB can be 'eaten up' configurable, (which @cfields is working on ) it's less of an issue. |
@casey Thanks. Will fix it. Not sure about limit per month or per day. For now i think keep the day-limit does make things more easy and controllable. |
I need some kind of goal set in kB/second, as I am often forced to shutdown my node for reliable phone calls. :( |
Agree with @luke-jr here, we think about available bandwidth in terms of kB/sec rather than MB/day because that's how it's always reported to us - adverts from ISPs, speed checking websites, P2P torrenting apps etc. |
a09950a
to
397230a
Compare
@NanoAkron: not sure if @luke-jr is for a bandwidth kB/sec limit. Bandwidth throttled peers is not something we should not encourage within bitcoin-core. If a node-operator likes to limit the bandwidth, he can use different tools. What we really should do is reducing bandwidth without impair the network quality and speed. My stats showed me that most traffic is done outbound and most of the outbound traffic is consumed by serving historical blocks (help other nodes to initial sync a new chain). This PR can reduce bandwidth significant while not impair the network quality. There was a discussion on #bitcoin-dev about the -maxuploadtarget (gmaxwell, wumpus, me) http://bitcoinstats.com/irc/bitcoin-dev/logs/2015/09/02#l1441180902.0) |
I don't think you can compare torrent to bitcoin-core serving blocks... Using torrent you are happy to get any transmission speed because it is parallel download anyway. On the contrary, bitcoin-core is doing moving-window download (c.f. #4468). So you always want to fetch the blocks from peers which can upload to you not much slower than your download speed? This PR makes the full node to disconnect from initial-download-peers instead of serving them at lower speed, which sounds like the better solution to me. |
Two questions:
|
Since 0.10 it does not really hurt much anymore to be served by a throttled
peer, as the download algorithm will download in parallel from many, and if
one is significantly slower than others, disconnect it itself.
|
@jonasschnelli To answer your two questions: No, I don't see a benefit. My wording was confusing, so to be clear: I am supporting this PR/commit. (Just as @sipa said, throttling won't help as it results in disconnect anyway) |
Having an "instant" bandwidth limit to work with can enable Core to make intelligent-ish decisions, like not inv'ing/uploading new blocks to more than one peer at a time unless the current-upload peer is downloading at a slow rate. |
Surely we need some sort of scaling to our bandwidth limitations/throttling here - serving historic blocks to unsynced peers could 'trickle-feed' in the background at a few 10s of kB/sec, and anything within the last 60 blocks or so could then be served with greater priority. This would need the unsynced peer to know with certainty the true current block height so that it didn't drop slow inbound connections, because this could be a new attack vector. |
@casey of course, any longer window cap can be divided down. Breaking it up into smaller groups has a side effect of allowing us more freedom to ignore the resource scheduling issue. Imagine that a low monthly cap were widely deployed on the network. Then the whole network might blow through its cap in a few days at the start of the month, and be unwilling to serve blocks for the rest of the month! The daily limit (especially with the arbitrary start point) is less of an issue. @luke-jr Your phone call issue is largely orthogonal to what this is addressing. Good behavior with respect to buffer bloat and general rate restriction are another matter from overall usage. Those need to be address too, but in other PRs. :) |
With the above mentioned comparison bug fixed, I can confirm that the basic functionality works once the limit is crossed: new blocks are relayed without issue, old blocks result in disconnect. |
c9996b1
to
32f685b
Compare
@gmaxwell: Thanks for the review! |
@@ -335,6 +335,7 @@ std::string HelpMessage(HelpMessageMode mode) | |||
strUsage += HelpMessageOpt("-whitebind=<addr>", _("Bind to given address and whitelist peers connecting to it. Use [host]:port notation for IPv6")); | |||
strUsage += HelpMessageOpt("-whitelist=<netmask>", _("Whitelist peers connecting from the given netmask or IP address. Can be specified multiple times.") + | |||
" " + _("Whitelisted peers cannot be DoS banned and their transactions are always relayed, even if they are already in the mempool, useful e.g. for a gateway")); | |||
strUsage += HelpMessageOpt("-maxuploadtarget=<n>", strprintf(_("Tries to keep outbound traffic under the given target, 0 = no limit (default: %d)"), 0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify units (bytes? megabytes?) and window size (seconds, days?)
might want to add a test so that it won't drop the last connection? I'm not sure but if you imagine e.g. someone using -connect and having several peers down already? -- then again is the peer really useful if its fetching old blocks? |
Not sure how useful a peer with height < now-1week is. But it could catch up and then be helpful. Thought, I think we should respect the uploadtarget in the first place. Excluding -whitebind looks more important to me (could be implemented in a follow up PR). |
With respect to forcing a minimum on the argument. Perhaps it should just whine in the logs if you've asked for a value that is too small? One consequence of the current setup is that every restart forces another 144MB of history transfer. (I removed that code in my own copy because it makes the software much easier to test.) |
32f685b
to
9c684ce
Compare
Agreed. That IBD serving is similar to torrent. This is the reason why this PR addresses that part if the upload target has been reached. The rest of your points are QoS topics. IMO this is a router job (or a lower level OS net stack thing). Reducing bandwidth by a throttling feature would reduce than bandwidth regardless of what else is going on on the system. It would also reduce bandwidth – which would be available – if the User is creating a backup or writing a letter in Word. |
Well, the issue is people want to configure it at the app level as many consumer wifi routers don't offer the right features, or people don't know how to use them. |
if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer) | ||
{ | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Braces not required.
Looks good to me. The OP said there is some documentation + tests to complete. |
utACK |
nMaxOutboundLimit = limit; | ||
|
||
if (limit < recommendedMinimum) | ||
LogPrintf("Max outbound target very small (%s) and are very unlikely to be reached, recommended minimum is %s\n", nMaxOutboundLimit, recommendedMinimum); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand this message. The target is too small, thus unlikely to be reached? Isn't it the other way around?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about just using "Warning: max outbound target is very small, recommended minimum is %s"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jonasschnelli I think you can still print nMaxOutboundLimit
, just remove or clarify the unlikely to be reached
as no one will understand this as "likely to overshoot
".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unlike to be reached sounds very much like it will use less bandwidth than specified; so I think this should be changed to "will be overshot" or "very likely to be exceeded." or similar.
@jonasschnelli Interest in performing a squash+rebase+message nits? I'd like to move to merge this. |
Agree @gmaxwell |
I'm currently rebasing and fixing @sdaftuars rpc test. Have plans to fix everything until tmr. |
30922c3
to
095841f
Compare
* -maxuploadtarget can be set in MiB * if <limit> - ( time-left-in-24h-cycle / 600 * MAX_BLOCK_SIZE ) has reach, stop serve blocks older than one week and filtered blocks * no action if limit has reached, no guarantee that the target will not be surpassed * add outbound limit informations to rpc getnettotals
095841f
to
6e60854
Compare
6e60854
to
17a073a
Compare
Rebased. Added @sdaftuar rpc test. Addressed nits. Passes travis. Ready for merge. |
outboundLimit.push_back(Pair("serve_historical_blocks", !CNode::OutboundTargetReached(true))); | ||
outboundLimit.push_back(Pair("bytes_left_in_cycle", CNode::GetOutboundTargetBytesLeft())); | ||
outboundLimit.push_back(Pair("time_left_in_cycle", CNode::GetMaxOutboundTimeLeftInCycle())); | ||
obj.push_back(Pair("uploadtarget", outboundLimit)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'd need to update help getnettotals
as well.
Introduce -maxuploadtarget Cherry-picked from the following upstream PRs: - bitcoin/bitcoin#6622 - bitcoin/bitcoin#6987 - bitcoin/bitcoin#6958 - bitcoin/bitcoin#6984 - bitcoin/bitcoin#6999 Part of #2074.
This is the first PR in a planed series of bandwidth / DOS prevention PRs.
Focus for now is a simple and not over-complex solution to start with.
The
-maxuploadtarget
(in MiB) is a configuration value that make bitcoind try to limit the total outbound traffic. Currently there is no guarantee that the limit target will be fulfilled.If the
target-in-bytes - (time-left-in-24-cycle) / 600 * MAX_BLOCK_SIZE
is reached, stop serve blocks older than one week, stop serve filtered blocks (SPV) immediately.The timeframe for the measurement is currently fixed to 24h.
This is a effective method of reducing traffic and might prevent node operators from getting expensive "traffic exceed"-bills.
Currently the limit also take effect for whitebinded peers.
Over
getnettotals
one can get some upload limit statistics:needs documentation
needs unit/rpc tests