|
111 | 111 | return 0;
|
112 | 112 | };
|
113 | 113 |
|
| 114 | +BPF_PERF_OUTPUT(outbound_connections); |
| 115 | +int trace_outbound_connection(struct pt_regs *ctx) { |
| 116 | + struct NewConnection outbound = {}; |
| 117 | + void *conn_type_pointer = NULL, *address_pointer = NULL; |
| 118 | + bpf_usdt_readarg(1, ctx, &outbound.conn.id); |
| 119 | + bpf_usdt_readarg(2, ctx, &address_pointer); |
| 120 | + bpf_usdt_readarg(3, ctx, &conn_type_pointer); |
| 121 | + bpf_usdt_readarg(4, ctx, &outbound.conn.network); |
| 122 | + bpf_usdt_readarg(5, ctx, &outbound.existing); |
| 123 | + bpf_probe_read_user_str(&outbound.conn.addr, sizeof(outbound.conn.addr), address_pointer); |
| 124 | + bpf_probe_read_user_str(&outbound.conn.type, sizeof(outbound.conn.type), conn_type_pointer); |
| 125 | + outbound_connections.perf_submit(ctx, &outbound, sizeof(outbound)); |
| 126 | + return 0; |
| 127 | +}; |
| 128 | +
|
114 | 129 | """
|
115 | 130 |
|
116 | 131 |
|
@@ -148,6 +163,7 @@ def skip_test_if_missing_module(self):
|
148 | 163 | def run_test(self):
|
149 | 164 | self.p2p_message_tracepoint_test()
|
150 | 165 | self.inbound_conn_tracepoint_test()
|
| 166 | + self.outbound_conn_tracepoint_test() |
151 | 167 |
|
152 | 168 | def p2p_message_tracepoint_test(self):
|
153 | 169 | # Tests the net:inbound_message and net:outbound_message tracepoints
|
@@ -263,5 +279,46 @@ def handle_inbound_connection(_, data, __):
|
263 | 279 | for node in testnodes:
|
264 | 280 | node.peer_disconnect()
|
265 | 281 |
|
| 282 | + def outbound_conn_tracepoint_test(self): |
| 283 | + self.log.info("hook into the net:outbound_connection tracepoint") |
| 284 | + ctx = USDT(pid=self.nodes[0].process.pid) |
| 285 | + ctx.enable_probe(probe="net:outbound_connection", |
| 286 | + fn_name="trace_outbound_connection") |
| 287 | + bpf = BPF(text=net_tracepoints_program, usdt_contexts=[ctx], debug=0, cflags=["-Wno-error=implicit-function-declaration"]) |
| 288 | + |
| 289 | + # that the handle_* function succeeds. |
| 290 | + EXPECTED_OUTBOUND_CONNECTIONS = 2 |
| 291 | + EXPECTED_CONNECTION_TYPE = "feeler" |
| 292 | + outbound_connections = [] |
| 293 | + |
| 294 | + def handle_outbound_connection(_, data, __): |
| 295 | + event = ctypes.cast(data, ctypes.POINTER(NewConnection)).contents |
| 296 | + self.log.info(f"handle_outbound_connection(): {event}") |
| 297 | + outbound_connections.append(event) |
| 298 | + |
| 299 | + bpf["outbound_connections"].open_perf_buffer( |
| 300 | + handle_outbound_connection) |
| 301 | + |
| 302 | + self.log.info( |
| 303 | + f"connect {EXPECTED_OUTBOUND_CONNECTIONS} P2P test nodes to our bitcoind node") |
| 304 | + testnodes = list() |
| 305 | + for p2p_idx in range(EXPECTED_OUTBOUND_CONNECTIONS): |
| 306 | + testnode = P2PInterface() |
| 307 | + self.nodes[0].add_outbound_p2p_connection( |
| 308 | + testnode, p2p_idx=p2p_idx, connection_type=EXPECTED_CONNECTION_TYPE) |
| 309 | + testnodes.append(testnode) |
| 310 | + bpf.perf_buffer_poll(timeout=200) |
| 311 | + |
| 312 | + assert_equal(EXPECTED_OUTBOUND_CONNECTIONS, len(outbound_connections)) |
| 313 | + for outbound_connection in outbound_connections: |
| 314 | + assert outbound_connection.conn.id > 0 |
| 315 | + assert outbound_connection.existing > 0 |
| 316 | + assert_equal(EXPECTED_CONNECTION_TYPE, outbound_connection.conn.conn_type.decode('utf-8')) |
| 317 | + assert_equal(NETWORK_TYPE_UNROUTABLE, outbound_connection.conn.network) |
| 318 | + |
| 319 | + bpf.cleanup() |
| 320 | + for node in testnodes: |
| 321 | + node.peer_disconnect() |
| 322 | + |
266 | 323 | if __name__ == '__main__':
|
267 | 324 | NetTracepointTest(__file__).main()
|
0 commit comments