1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# rdmaucma: Trace RDMA Userspace Connection Manager Access Event. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: rdmaucma [-h] 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2023 zhenwei pi 10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# 29-MAY-2023 zhenwei pi Created this. 13*387f9dfdSAndroid Build Coastguard Worker 14*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 15*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 16*387f9dfdSAndroid Build Coastguard Workerfrom socket import inet_ntop, AF_INET, AF_INET6 17*387f9dfdSAndroid Build Coastguard Workerimport socket, struct 18*387f9dfdSAndroid Build Coastguard Workerimport argparse 19*387f9dfdSAndroid Build Coastguard Workerimport ctypes 20*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker# arguments 23*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 24*387f9dfdSAndroid Build Coastguard Worker ./rdmaucma # Trace all RDMA Userspace Connection Manager Access Event 25*387f9dfdSAndroid Build Coastguard Worker""" 26*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 27*387f9dfdSAndroid Build Coastguard Worker description="Trace RDMA Userspace Connection Manager Access Event", 28*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 29*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 30*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-D", "--debug", action="store_true", 31*387f9dfdSAndroid Build Coastguard Worker help="print BPF program before starting (for debugging purposes)") 32*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 33*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 34*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 35*387f9dfdSAndroid Build Coastguard Worker 36*387f9dfdSAndroid Build Coastguard Worker# define BPF program 37*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 38*387f9dfdSAndroid Build Coastguard Worker#include <linux/bpf.h> 39*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 40*387f9dfdSAndroid Build Coastguard Worker#include <rdma/rdma_cm.h> 41*387f9dfdSAndroid Build Coastguard Worker 42*387f9dfdSAndroid Build Coastguard Workerstruct ipv4_data_t { 43*387f9dfdSAndroid Build Coastguard Worker u32 saddr; 44*387f9dfdSAndroid Build Coastguard Worker u32 daddr; 45*387f9dfdSAndroid Build Coastguard Worker u16 sport; 46*387f9dfdSAndroid Build Coastguard Worker u16 dport; 47*387f9dfdSAndroid Build Coastguard Worker int event; 48*387f9dfdSAndroid Build Coastguard Worker}; 49*387f9dfdSAndroid Build Coastguard Worker 50*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(ipv4_events); 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Workerstruct ipv6_data_t { 53*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 saddr; 54*387f9dfdSAndroid Build Coastguard Worker unsigned __int128 daddr; 55*387f9dfdSAndroid Build Coastguard Worker u16 sport; 56*387f9dfdSAndroid Build Coastguard Worker u16 dport; 57*387f9dfdSAndroid Build Coastguard Worker int event; 58*387f9dfdSAndroid Build Coastguard Worker}; 59*387f9dfdSAndroid Build Coastguard Worker 60*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(ipv6_events); 61*387f9dfdSAndroid Build Coastguard Worker 62*387f9dfdSAndroid Build Coastguard Workerint trace_ucma_event_handler(struct pt_regs *ctx, 63*387f9dfdSAndroid Build Coastguard Worker struct rdma_cm_id *cm_id, 64*387f9dfdSAndroid Build Coastguard Worker struct rdma_cm_event *event) 65*387f9dfdSAndroid Build Coastguard Worker{ 66*387f9dfdSAndroid Build Coastguard Worker struct sockaddr_storage *ss = &cm_id->route.addr.src_addr; 67*387f9dfdSAndroid Build Coastguard Worker 68*387f9dfdSAndroid Build Coastguard Worker if (ss->ss_family == AF_INET) { 69*387f9dfdSAndroid Build Coastguard Worker struct ipv4_data_t ipv4_data = { 0 }; 70*387f9dfdSAndroid Build Coastguard Worker struct sockaddr_in *addr4 = (struct sockaddr_in *)ss; 71*387f9dfdSAndroid Build Coastguard Worker ipv4_data.sport = addr4->sin_port; 72*387f9dfdSAndroid Build Coastguard Worker ipv4_data.saddr = addr4->sin_addr.s_addr; 73*387f9dfdSAndroid Build Coastguard Worker 74*387f9dfdSAndroid Build Coastguard Worker addr4 = (struct sockaddr_in *)&cm_id->route.addr.dst_addr; 75*387f9dfdSAndroid Build Coastguard Worker ipv4_data.dport = addr4->sin_port; 76*387f9dfdSAndroid Build Coastguard Worker ipv4_data.daddr = addr4->sin_addr.s_addr; 77*387f9dfdSAndroid Build Coastguard Worker 78*387f9dfdSAndroid Build Coastguard Worker ipv4_data.event = event->event; 79*387f9dfdSAndroid Build Coastguard Worker ipv4_events.perf_submit(ctx, &ipv4_data, sizeof(ipv4_data)); 80*387f9dfdSAndroid Build Coastguard Worker } else if (ss->ss_family == AF_INET6) { 81*387f9dfdSAndroid Build Coastguard Worker struct ipv6_data_t ipv6_data = { 0 }; 82*387f9dfdSAndroid Build Coastguard Worker struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)ss; 83*387f9dfdSAndroid Build Coastguard Worker ipv6_data.sport = addr6->sin6_port; 84*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_data.saddr, sizeof(ipv6_data.saddr), addr6->sin6_addr.in6_u.u6_addr32); 85*387f9dfdSAndroid Build Coastguard Worker 86*387f9dfdSAndroid Build Coastguard Worker addr6 = (struct sockaddr_in6 *)&cm_id->route.addr.dst_addr; 87*387f9dfdSAndroid Build Coastguard Worker ipv6_data.dport = addr6->sin6_port; 88*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&ipv6_data.daddr, sizeof(ipv6_data.daddr), addr6->sin6_addr.in6_u.u6_addr32); 89*387f9dfdSAndroid Build Coastguard Worker 90*387f9dfdSAndroid Build Coastguard Worker ipv6_data.event = event->event; 91*387f9dfdSAndroid Build Coastguard Worker ipv6_events.perf_submit(ctx, &ipv6_data, sizeof(ipv6_data)); 92*387f9dfdSAndroid Build Coastguard Worker } else { 93*387f9dfdSAndroid Build Coastguard Worker return -EPROTONOSUPPORT; 94*387f9dfdSAndroid Build Coastguard Worker } 95*387f9dfdSAndroid Build Coastguard Worker 96*387f9dfdSAndroid Build Coastguard Worker return 0; 97*387f9dfdSAndroid Build Coastguard Worker} 98*387f9dfdSAndroid Build Coastguard Worker""" 99*387f9dfdSAndroid Build Coastguard Worker 100*387f9dfdSAndroid Build Coastguard Worker# debug/dump ebpf enable or not 101*387f9dfdSAndroid Build Coastguard Workerif args.debug or args.ebpf: 102*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 103*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 104*387f9dfdSAndroid Build Coastguard Worker exit() 105*387f9dfdSAndroid Build Coastguard Worker 106*387f9dfdSAndroid Build Coastguard Worker# load BPF program 107*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 108*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="ucma_event_handler", fn_name="trace_ucma_event_handler") 109*387f9dfdSAndroid Build Coastguard Worker 110*387f9dfdSAndroid Build Coastguard Worker# see linux/include/rdma/rdma_cm.h 111*387f9dfdSAndroid Build Coastguard Workerrdma_cm_event = [ 112*387f9dfdSAndroid Build Coastguard Worker "address resolved", 113*387f9dfdSAndroid Build Coastguard Worker "address error", 114*387f9dfdSAndroid Build Coastguard Worker "route resolved ", 115*387f9dfdSAndroid Build Coastguard Worker "route error", 116*387f9dfdSAndroid Build Coastguard Worker "connect request", 117*387f9dfdSAndroid Build Coastguard Worker "connect response", 118*387f9dfdSAndroid Build Coastguard Worker "connect error", 119*387f9dfdSAndroid Build Coastguard Worker "unreachable", 120*387f9dfdSAndroid Build Coastguard Worker "rejected", 121*387f9dfdSAndroid Build Coastguard Worker "established", 122*387f9dfdSAndroid Build Coastguard Worker "disconnected", 123*387f9dfdSAndroid Build Coastguard Worker "device removal", 124*387f9dfdSAndroid Build Coastguard Worker "multicast join", 125*387f9dfdSAndroid Build Coastguard Worker "multicast error", 126*387f9dfdSAndroid Build Coastguard Worker "address change", 127*387f9dfdSAndroid Build Coastguard Worker "timewait exit" ] 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Workerdef print_ipv4_event(cpu, data, size): 130*387f9dfdSAndroid Build Coastguard Worker event = b["ipv4_events"].event(data) 131*387f9dfdSAndroid Build Coastguard Worker 132*387f9dfdSAndroid Build Coastguard Worker cm_event = "unknown event" 133*387f9dfdSAndroid Build Coastguard Worker if event.event < len(rdma_cm_event): 134*387f9dfdSAndroid Build Coastguard Worker cm_event = rdma_cm_event[event.event] 135*387f9dfdSAndroid Build Coastguard Worker 136*387f9dfdSAndroid Build Coastguard Worker print("%-9s %-16s %-6s %-45s %-45s" % (strftime("%H:%M:%S").encode('ascii'), 137*387f9dfdSAndroid Build Coastguard Worker cm_event, "IPv4", 138*387f9dfdSAndroid Build Coastguard Worker inet_ntop(AF_INET, struct.pack("I", event.saddr)) + ":" + str(socket.ntohs(event.sport)), 139*387f9dfdSAndroid Build Coastguard Worker inet_ntop(AF_INET, struct.pack("I", event.daddr)) + ":" + str(socket.ntohs(event.dport)))) 140*387f9dfdSAndroid Build Coastguard Worker 141*387f9dfdSAndroid Build Coastguard Workerdef print_ipv6_event(cpu, data, size): 142*387f9dfdSAndroid Build Coastguard Worker event = b["ipv6_events"].event(data) 143*387f9dfdSAndroid Build Coastguard Worker 144*387f9dfdSAndroid Build Coastguard Worker cm_event = "unknown event" 145*387f9dfdSAndroid Build Coastguard Worker if event.event < len(rdma_cm_event): 146*387f9dfdSAndroid Build Coastguard Worker cm_event = rdma_cm_event[event.event] 147*387f9dfdSAndroid Build Coastguard Worker 148*387f9dfdSAndroid Build Coastguard Worker print("%-9s %-16s %-6s %-45s %-45s" % (strftime("%H:%M:%S").encode('ascii'), 149*387f9dfdSAndroid Build Coastguard Worker cm_event, "IPv6", 150*387f9dfdSAndroid Build Coastguard Worker inet_ntop(AF_INET6, event.saddr) + ":" + str(socket.ntohs(event.sport)), 151*387f9dfdSAndroid Build Coastguard Worker inet_ntop(AF_INET6, event.daddr) + ":" + str(socket.ntohs(event.dport)))) 152*387f9dfdSAndroid Build Coastguard Worker 153*387f9dfdSAndroid Build Coastguard Worker 154*387f9dfdSAndroid Build Coastguard Workerb["ipv4_events"].open_perf_buffer(print_ipv4_event) 155*387f9dfdSAndroid Build Coastguard Workerb["ipv6_events"].open_perf_buffer(print_ipv6_event) 156*387f9dfdSAndroid Build Coastguard Worker 157*387f9dfdSAndroid Build Coastguard Worker# output 158*387f9dfdSAndroid Build Coastguard Workerprint("Tracing RDMA Userspace Connection Manager Access event... Hit Ctrl-C to end.") 159*387f9dfdSAndroid Build Coastguard Worker 160*387f9dfdSAndroid Build Coastguard Worker# address length 39 = max("2001:0db8:3c4d:0015:0000:0000:1a2f:1a2b", "255.255.255.255") 161*387f9dfdSAndroid Build Coastguard Workerprint("%-9s %-16s %-4s %-45s %-45s" % ("Timestamp", "Event", "Family", "Local", "Remote")) 162*387f9dfdSAndroid Build Coastguard Worker 163*387f9dfdSAndroid Build Coastguard Workerwhile (1): 164*387f9dfdSAndroid Build Coastguard Worker try: 165*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 166*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 167*387f9dfdSAndroid Build Coastguard Worker exit() 168