Skip to content

Commit

Permalink
comments on kernel structs and internal.NativeEndian in Go application
Browse files Browse the repository at this point in the history
  • Loading branch information
gmichelo committed Mar 29, 2022
1 parent 9ebaa1d commit d8c5f63
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 17 deletions.
Binary file modified examples/tcprtt/bpf_bpfeb.o
Binary file not shown.
Binary file modified examples/tcprtt/bpf_bpfel.o
Binary file not shown.
14 changes: 4 additions & 10 deletions examples/tcprtt/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"os/signal"
"syscall"

"github.com/cilium/ebpf/internal"
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/ringbuf"
"github.com/cilium/ebpf/rlimit"
Expand Down Expand Up @@ -93,7 +94,7 @@ func readLoop(rd *ringbuf.Reader) {
}

// Parse the ringbuf event entry into a bpfEvent structure.
if err := binary.Read(bytes.NewBuffer(record.RawSample), binary.BigEndian, &event); err != nil {
if err := binary.Read(bytes.NewBuffer(record.RawSample), internal.NativeEndian, &event); err != nil {
log.Printf("parsing ringbuf event: %s", err)
continue
}
Expand All @@ -103,21 +104,14 @@ func readLoop(rd *ringbuf.Reader) {
event.Sport,
intToIP(event.Daddr),
event.Dport,
littleToBigEndian(event.Srtt),
event.Srtt,
)
}
}

// intToIP converts IPv4 number to net.IP
func intToIP(ipNum uint32) net.IP {
ip := make(net.IP, 4)
binary.BigEndian.PutUint32(ip, ipNum)
internal.NativeEndian.PutUint32(ip, ipNum)
return ip
}

// littleToBigEndian converts LittleEndian uint32 to BigEndian
func littleToBigEndian(rtt uint32) uint32 {
buf := make([]byte, 4)
binary.LittleEndian.PutUint32(buf, rtt)
return binary.BigEndian.Uint32(buf)
}
44 changes: 37 additions & 7 deletions examples/tcprtt/tcprtt.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,59 @@

char LICENSE[] SEC("license") = "Dual MIT/GPL";

/**
* Note: for CO-RE relocatable eBPF programs, __attribute__((preserve_access_index))
* preserves the offset of the specified fields in the original kernel struct.
* So here we don't need to include "vmlinux.h". Instead we only need to define
* the kernel struct and their fields the eBPF program actually requires.
*/

/**
* struct sock_common is the minimal network layer representation of sockets.
* This is a simplified copy of the same kernel's struct:
* (https://elixir.bootlin.com/linux/latest/source/include/net/sock.h#L163).
* This copy contains only the fields needed for this example to
* fetch the source and destination port numbers and IP addresses.
*/
struct sock_common {
union {
struct {
// skc_daddr is destination IP address
__be32 skc_daddr;
// skc_rcv_saddr is the source IP address
__be32 skc_rcv_saddr;
};
};
union {
unsigned int skc_hash;
__u16 skc_u16hashes[2];
};
union {
struct {
// skc_dport is the destination TCP/UDP port
__be16 skc_dport;
// skc_num is the source TCP/UDP port
__u16 skc_num;
};
};
// skc_family is the network address family (2 for IPV4)
short unsigned int skc_family;
} __attribute__((preserve_access_index));
} __attribute__((preserve_access_index));


/**
* struct sock is the network layer representation of sockets.
* This is a simplified copy of the same kernel's struct:
* (https://elixir.bootlin.com/linux/latest/source/include/net/sock.h#L355).
* This copy is needed only to access struct sock_common.
*/
struct sock {
struct sock_common __sk_common;
} __attribute__((preserve_access_index));


/**
* struct tcp_sock is the Linux representation of a TCP socket.
* This is a simplified copy of the same kernel's struct:
* https://elixir.bootlin.com/linux/latest/source/include/linux/tcp.h#L145
* For this example we only need srtt_us to read the smoothed RTT.
*/
struct tcp_sock {
u32 srtt_us;
} __attribute__((preserve_access_index));
Expand All @@ -60,6 +89,7 @@ int BPF_PROG(tcp_close, struct sock *sk) {
return 0;
}

// The input struct sock is actually a tcp_sock, so we can type-cast
struct tcp_sock *ts = bpf_skc_to_tcp_sock(sk);
if (!ts) {
return 0;
Expand All @@ -73,8 +103,8 @@ int BPF_PROG(tcp_close, struct sock *sk) {

tcp_info->saddr = sk->__sk_common.skc_rcv_saddr;
tcp_info->daddr = sk->__sk_common.skc_daddr;
tcp_info->dport = sk->__sk_common.skc_dport;
tcp_info->sport = bpf_htons(sk->__sk_common.skc_num);
tcp_info->dport = bpf_ntohs(sk->__sk_common.skc_dport);
tcp_info->sport = sk->__sk_common.skc_num;

tcp_info->srtt = ts->srtt_us >> 3;
tcp_info->srtt /= 1000;
Expand Down

0 comments on commit d8c5f63

Please sign in to comment.