Skip to content

Commit a43f08c

Browse files
committed
Merge bitcoin/bitcoin#25832: tracing: network connection tracepoints
e3622a9 tracing: document that peer addrs can be >68 chars (0xb10c) b19b526 tracing: log_p2p_connections.bt example (0xb10c) caa5486 tracing: connection closed tracepoint (0xb10c) b2ad6ed tracing: add misbehaving conn tracepoint (0xb10c) 68c1ef4 tracing: add inbound connection eviction tracepoint (0xb10c) 4d61d52 tracing: add outbound connection tracepoint (0xb10c) 85b2603 tracing: add inbound connection tracepoint (0xb10c) Pull request description: This adds five new tracepoints with documentation and tests for network connections: - established connections with `net:inbound_connection` and `net:outbound_connection` - closed connections (both closed by us or by the peer) with `net:closed_connnection` - inbound connections that we choose to evict with `net:evicted_inbound_connection` - connections that are misbehaving and punished with `net:misbehaving_connection` I've been using these tracepoints for a few months now to monitor connection lifetimes, re-connection frequency by IP and netgroup, misbehavior, peer discouragement, and eviction and more. Together with the two existing P2P message tracepoints they allow for a good overview of local P2P network activity. Also sort-of addresses bitcoin/bitcoin#22006 (comment). I've been back and forth on which arguments to include. For example, `net:evicted_connection` could also include some of the eviction metrics like e.g. `last_block_time`, `min_ping_time`, ... but I've left them out for now. If wanted, this can be added here or in a follow-up. I've tried to minimize a potential performance impact by measuring executed instructions with `gdb` where possible (method described [here](bitcoin/bitcoin#23724 (comment))). I don't think a few hundred extra instructions are too crucial, as connection opens/closes aren't too frequent (compared to e.g. P2P messages). Note: e.g. `CreateNodeFromAcceptedSocket()` usually executes between 80k and 90k instructions for each new inbound connection. | tracepoint | instructions | |----------------------------|--------------------------------------------------------| | net:inbound_connection | 390 ins | | net:outbound_connection | between 700 and 1000 ins | | net:closed_connnection | 473 ins | | net:evicted_inbound_connection | not measured; likely similar to net:closed_connnection | | net:misbehaving_connection | not measured | Also added a bpftrace (tested with v0.14.1) `log_p2p_connections.bt` example script that produces output similar to: ``` Attaching 6 probes... Logging opened, closed, misbehaving, and evicted P2P connections OUTBOUND conn to 127.0.0.1:15287: id=0, type=block-relay-only, network=0, total_out=1 INBOUND conn from 127.0.0.1:45324: id=1, type=inbound, network=0, total_in=1 MISBEHAVING conn id=1, message='getdata message size = 50001' CLOSED conn to 127.0.0.1:15287: id=0, type=block-relay-only, network=0, established=1231006505 EVICTED conn to 127.0.0.1:45324: id=1, type=inbound, network=0, established=1612312312 ``` ACKs for top commit: laanwj: re-ACK e3622a9 vasild: ACK e3622a9 sipa: utACK e3622a9 Tree-SHA512: 1032dcac6fe0ced981715606f82c2db47016407d3accb8f216c978f010da9bc20453e24a167dcc95287f4783b48562ffb90f645bf230990e3df1b9b9a6d4e5d0
2 parents b9c2418 + e3622a9 commit a43f08c

File tree

6 files changed

+515
-5
lines changed

6 files changed

+515
-5
lines changed

contrib/tracing/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,25 @@ $ python3 contrib/tracing/mempool_monitor.py $(pidof bitcoind)
335335
│ 13:10:32Z added c78e87be86c828137a6e7e00a177c03b52202ce4c39029b99904c2a094b9da87 with feerate 11.00 sat/vB (1562 sat, 142 vbytes) │
336336
│ │
337337
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
338+
339+
### log_p2p_connections.bt
340+
341+
A `bpftrace` script to log information about opened, closed, misbehaving, and
342+
evicted P2P connections. Uses the `net:*_connection` tracepoints.
343+
344+
```bash
345+
$ bpftrace contrib/tracing/log_p2p_connections.bt
346+
```
347+
348+
This should produce an output similar to the following.
349+
350+
```bash
351+
Attaching 6 probes...
352+
Logging opened, closed, misbehaving, and evicted P2P connections
353+
OUTBOUND conn to 127.0.0.1:15287: id=0, type=block-relay-only, network=0, total_out=1
354+
INBOUND conn from 127.0.0.1:45324: id=1, type=inbound, network=0, total_in=1
355+
MISBEHAVING conn id=1, score_before=0, score_increase=20, message='getdata message size = 50001', threshold_exceeded=false
356+
CLOSED conn to 127.0.0.1:15287: id=0, type=block-relay-only, network=0, established=1231006505
357+
EVICTED conn to 127.0.0.1:45324: id=1, type=inbound, network=0, established=1612312312
358+
...
338359
```
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#!/usr/bin/env bpftrace
2+
3+
BEGIN
4+
{
5+
printf("Logging opened, closed, misbehaving, and evicted P2P connections\n")
6+
}
7+
8+
usdt:./build/src/bitcoind:net:inbound_connection
9+
{
10+
$id = (int64) arg0;
11+
$addr = str(arg1);
12+
$conn_type = str(arg2);
13+
$network = (int32) arg3;
14+
$existing = (uint64) arg4;
15+
printf("INBOUND conn from %s: id=%ld, type=%s, network=%d, total=%d\n", $addr, $id, $conn_type, $network, $existing);
16+
}
17+
18+
usdt:./build/src/bitcoind:net:outbound_connection
19+
{
20+
$id = (int64) arg0;
21+
$addr = str(arg1);
22+
$conn_type = str(arg2);
23+
$network = (int32) arg3;
24+
$existing = (uint64) arg4;
25+
printf("OUTBOUND conn to %s: id=%ld, type=%s, network=%d, total=%d\n", $addr, $id, $conn_type, $network, $existing);
26+
}
27+
28+
usdt:./build/src/bitcoind:net:closed_connection
29+
{
30+
$id = (int64) arg0;
31+
$addr = str(arg1);
32+
$conn_type = str(arg2);
33+
$network = (int32) arg3;
34+
printf("CLOSED conn to %s: id=%ld, type=%s, network=%d, established=%ld\n", $addr, $id, $conn_type, $network, arg4);
35+
}
36+
37+
usdt:./build/src/bitcoind:net:evicted_inbound_connection
38+
{
39+
$id = (int64) arg0;
40+
$addr = str(arg1);
41+
$conn_type = str(arg2);
42+
$network = (int32) arg3;
43+
printf("EVICTED conn to %s: id=%ld, type=%s, network=%d, established=%ld\n", $addr, $id, $conn_type, $network, arg4);
44+
}
45+
46+
usdt:./build/src/bitcoind:net:misbehaving_connection
47+
{
48+
$id = (int64) arg0;
49+
$message = str(arg1);
50+
printf("MISBEHAVING conn id=%ld, message='%s'\n", $id, $message);
51+
}

doc/tracing.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,17 @@ The currently available tracepoints are listed here.
5555

5656
### Context `net`
5757

58+
[^address-length]: An Onion v3 address with a `:` and a five digit port has 68
59+
chars. However, addresses of peers added with host names might be longer.
60+
5861
#### Tracepoint `net:inbound_message`
5962

6063
Is called when a message is received from a peer over the P2P network. Passes
6164
information about our peer, the connection and the message as arguments.
6265

6366
Arguments passed:
6467
1. Peer ID as `int64`
65-
2. Peer Address and Port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (max. length 68 characters)
68+
2. Peer Address and Port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (normally up to 68 characters[^address-length])
6669
3. Connection Type (inbound, feeler, outbound-full-relay, ...) as `pointer to C-style String` (max. length 20 characters)
6770
4. Message Type (inv, ping, getdata, addrv2, ...) as `pointer to C-style String` (max. length 20 characters)
6871
5. Message Size in bytes as `uint64`
@@ -81,7 +84,7 @@ information about our peer, the connection and the message as arguments.
8184

8285
Arguments passed:
8386
1. Peer ID as `int64`
84-
2. Peer Address and Port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (max. length 68 characters)
87+
2. Peer Address and Port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (normally up to 68 characters[^address-length])
8588
3. Connection Type (inbound, feeler, outbound-full-relay, ...) as `pointer to C-style String` (max. length 20 characters)
8689
4. Message Type (inv, ping, getdata, addrv2, ...) as `pointer to C-style String` (max. length 20 characters)
8790
5. Message Size in bytes as `uint64`
@@ -93,6 +96,62 @@ to user-space in full. Messages longer than a 32kb might be cut off. This can
9396
be detected in tracing scripts by comparing the message size to the length of
9497
the passed message.
9598

99+
#### Tracepoint `net:inbound_connection`
100+
101+
Is called when a new inbound connection is opened to us. Passes information about
102+
the peer and the number of inbound connections including the newly opened connection.
103+
104+
Arguments passed:
105+
1. Peer ID as `int64`
106+
2. Peer address and port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (normally up to 68 characters[^address-length])
107+
3. Connection Type (inbound, feeler, outbound-full-relay, ...) as `pointer to C-style String` (max. length 20 characters)
108+
4. Network the peer connects from as `uint32` (1 = IPv4, 2 = IPv6, 3 = Onion, 4 = I2P, 5 = CJDNS). See `Network` enum in `netaddress.h`.
109+
5. Number of existing inbound connections as `uint64` including the newly opened inbound connection.
110+
111+
#### Tracepoint `net:outbound_connection`
112+
113+
Is called when a new outbound connection is opened by us. Passes information about
114+
the peer and the number of outbound connections including the newly opened connection.
115+
116+
Arguments passed:
117+
1. Peer ID as `int64`
118+
2. Peer address and port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (normally up to 68 characters[^address-length])
119+
3. Connection Type (inbound, feeler, outbound-full-relay, ...) as `pointer to C-style String` (max. length 20 characters)
120+
4. Network of the peer as `uint32` (1 = IPv4, 2 = IPv6, 3 = Onion, 4 = I2P, 5 = CJDNS). See `Network` enum in `netaddress.h`.
121+
5. Number of existing outbound connections as `uint64` including the newly opened outbound connection.
122+
123+
#### Tracepoint `net:evicted_inbound_connection`
124+
125+
Is called when a inbound connection is evicted by us. Passes information about the evicted peer and the time at connection establishment.
126+
127+
Arguments passed:
128+
1. Peer ID as `int64`
129+
2. Peer address and port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (normally up to 68 characters[^address-length])
130+
3. Connection Type (inbound, feeler, outbound-full-relay, ...) as `pointer to C-style String` (max. length 20 characters)
131+
4. Network the peer connects from as `uint32` (1 = IPv4, 2 = IPv6, 3 = Onion, 4 = I2P, 5 = CJDNS). See `Network` enum in `netaddress.h`.
132+
5. Connection established UNIX epoch timestamp in seconds as `uint64`.
133+
134+
#### Tracepoint `net:misbehaving_connection`
135+
136+
Is called when a connection is misbehaving. Passes the peer id and a
137+
reason for the peers misbehavior.
138+
139+
Arguments passed:
140+
1. Peer ID as `int64`.
141+
2. Reason why the peer is misbehaving as `pointer to C-style String` (max. length 128 characters).
142+
143+
#### Tracepoint `net:closed_connection`
144+
145+
Is called when a connection is closed. Passes information about the closed peer
146+
and the time at connection establishment.
147+
148+
Arguments passed:
149+
1. Peer ID as `int64`
150+
2. Peer address and port (IPv4, IPv6, Tor v3, I2P, ...) as `pointer to C-style String` (normally up to 68 characters[^address-length])
151+
3. Connection Type (inbound, feeler, outbound-full-relay, ...) as `pointer to C-style String` (max. length 20 characters)
152+
4. Network the peer connects from as `uint32` (1 = IPv4, 2 = IPv6, 3 = Onion, 4 = I2P, 5 = CJDNS). See `Network` enum in `netaddress.h`.
153+
5. Connection established UNIX epoch timestamp in seconds as `uint64`.
154+
96155
### Context `validation`
97156

98157
#### Tracepoint `validation:block_connected`

src/net.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@
5353
#include <optional>
5454
#include <unordered_map>
5555

56+
TRACEPOINT_SEMAPHORE(net, closed_connection);
57+
TRACEPOINT_SEMAPHORE(net, evicted_inbound_connection);
58+
TRACEPOINT_SEMAPHORE(net, inbound_connection);
59+
TRACEPOINT_SEMAPHORE(net, outbound_connection);
5660
TRACEPOINT_SEMAPHORE(net, outbound_message);
5761

5862
/** Maximum number of block-relay-only anchor connections */
@@ -560,6 +564,13 @@ void CNode::CloseSocketDisconnect()
560564
if (m_sock) {
561565
LogDebug(BCLog::NET, "Resetting socket for peer=%d%s", GetId(), LogIP(fLogIPs));
562566
m_sock.reset();
567+
568+
TRACEPOINT(net, closed_connection,
569+
GetId(),
570+
m_addr_name.c_str(),
571+
ConnectionTypeAsString().c_str(),
572+
ConnectedThroughNetwork(),
573+
Ticks<std::chrono::seconds>(m_connected));
563574
}
564575
m_i2p_sam_session.reset();
565576
}
@@ -1708,6 +1719,12 @@ bool CConnman::AttemptToEvictConnection()
17081719
for (CNode* pnode : m_nodes) {
17091720
if (pnode->GetId() == *node_id_to_evict) {
17101721
LogDebug(BCLog::NET, "selected %s connection for eviction, %s", pnode->ConnectionTypeAsString(), pnode->DisconnectMsg(fLogIPs));
1722+
TRACEPOINT(net, evicted_inbound_connection,
1723+
pnode->GetId(),
1724+
pnode->m_addr_name.c_str(),
1725+
pnode->ConnectionTypeAsString().c_str(),
1726+
pnode->ConnectedThroughNetwork(),
1727+
Ticks<std::chrono::seconds>(pnode->m_connected));
17111728
pnode->fDisconnect = true;
17121729
return true;
17131730
}
@@ -1833,6 +1850,12 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
18331850
m_nodes.push_back(pnode);
18341851
}
18351852
LogDebug(BCLog::NET, "connection from %s accepted\n", addr.ToStringAddrPort());
1853+
TRACEPOINT(net, inbound_connection,
1854+
pnode->GetId(),
1855+
pnode->m_addr_name.c_str(),
1856+
pnode->ConnectionTypeAsString().c_str(),
1857+
pnode->ConnectedThroughNetwork(),
1858+
GetNodeCount(ConnectionDirection::In));
18361859

18371860
// We received a new connection, harvest entropy from the time (and our peer count)
18381861
RandAddEvent((uint32_t)id);
@@ -2995,6 +3018,13 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
29953018
// update connection count by network
29963019
if (pnode->IsManualOrFullOutboundConn()) ++m_network_conn_counts[pnode->addr.GetNetwork()];
29973020
}
3021+
3022+
TRACEPOINT(net, outbound_connection,
3023+
pnode->GetId(),
3024+
pnode->m_addr_name.c_str(),
3025+
pnode->ConnectionTypeAsString().c_str(),
3026+
pnode->ConnectedThroughNetwork(),
3027+
GetNodeCount(ConnectionDirection::Out));
29983028
}
29993029

30003030
Mutex NetEventsInterface::g_msgproc_mutex;

src/net_processing.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
using namespace util::hex_literals;
5959

6060
TRACEPOINT_SEMAPHORE(net, inbound_message);
61+
TRACEPOINT_SEMAPHORE(net, misbehaving_connection);
6162

6263
/** Headers download timeout.
6364
* Timeout = base + per_header * (expected number of headers) */
@@ -1752,6 +1753,10 @@ void PeerManagerImpl::Misbehaving(Peer& peer, const std::string& message)
17521753
const std::string message_prefixed = message.empty() ? "" : (": " + message);
17531754
peer.m_should_discourage = true;
17541755
LogDebug(BCLog::NET, "Misbehaving: peer=%d%s\n", peer.m_id, message_prefixed);
1756+
TRACEPOINT(net, misbehaving_connection,
1757+
peer.m_id,
1758+
message.c_str()
1759+
);
17551760
}
17561761

17571762
void PeerManagerImpl::MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,

0 commit comments

Comments
 (0)