Skip to content

Commit

Permalink
eBPF packet translation tracker
Browse files Browse the repository at this point in the history
Signed-off-by: Mohamed Mahmoud <[email protected]>
  • Loading branch information
msherif1234 committed Nov 22, 2024
1 parent 0de6a01 commit 0695f51
Show file tree
Hide file tree
Showing 91 changed files with 8,498 additions and 1,743 deletions.
1 change: 1 addition & 0 deletions bpf/configs.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ volatile const u8 enable_flows_filtering = 0;
volatile const u16 dns_port = 0;
volatile const u8 enable_network_events_monitoring = 0;
volatile const u8 network_events_monitoring_groupid = 0;
volatile const u8 enable_pkt_transformation_tracking = 0;
#endif //__CONFIGS_H__
5 changes: 5 additions & 0 deletions bpf/flows.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@
*/
#include "network_events_monitoring.h"

/*
* Defines packets transformation tracker
*/
#include "pkt_transformation.h"

static inline int flow_monitor(struct __sk_buff *skb, u8 direction) {
// If sampling is defined, will only parse 1 out of "sampling" flows
if (sampling > 1 && (bpf_get_prandom_u32() % sampling) != 0) {
Expand Down
10 changes: 3 additions & 7 deletions bpf/flows_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@

#include "utils.h"

// remove the comment below to enable debug prints
//#define ENABLE_BPF_PRINTK
#ifdef ENABLE_BPF_PRINTK
#define BPF_PRINTK(fmt, args...) bpf_printk(fmt, ##args)
#else
#define BPF_PRINTK(fmt, args...)
#endif
#define BPF_PRINTK(fmt, args...) \
if (trace_messages) \
bpf_printk(fmt, ##args)

static __always_inline int is_zero_ip(u8 *ip, u8 len) {
for (int i = 0; i < len; i++) {
Expand Down
13 changes: 7 additions & 6 deletions bpf/headers/vmlinux_amd64.h
Original file line number Diff line number Diff line change
Expand Up @@ -22484,10 +22484,17 @@ union nf_conntrack_proto {

struct nf_ct_ext;

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conn {
struct nf_conntrack ct_general;
spinlock_t lock;
u32 timeout;
struct nf_conntrack_zone zone;
struct nf_conntrack_tuple_hash tuplehash[2];
long unsigned int status;
possible_net_t ct_net;
Expand All @@ -22499,12 +22506,6 @@ struct nf_conn {
union nf_conntrack_proto proto;
};

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct xt_action_param;

struct xt_mtchk_param;
Expand Down
13 changes: 7 additions & 6 deletions bpf/headers/vmlinux_arm64.h
Original file line number Diff line number Diff line change
Expand Up @@ -22582,10 +22582,17 @@ union nf_conntrack_proto {

struct nf_ct_ext;

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conn {
struct nf_conntrack ct_general;
spinlock_t lock;
u32 timeout;
struct nf_conntrack_zone zone;
struct nf_conntrack_tuple_hash tuplehash[2];
long unsigned int status;
possible_net_t ct_net;
Expand All @@ -22597,12 +22604,6 @@ struct nf_conn {
union nf_conntrack_proto proto;
};

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct icmphdr {
__u8 type;
__u8 code;
Expand Down
13 changes: 7 additions & 6 deletions bpf/headers/vmlinux_ppc64le.h
Original file line number Diff line number Diff line change
Expand Up @@ -67125,10 +67125,17 @@ union nf_conntrack_proto {

struct nf_ct_ext;

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conn {
struct nf_conntrack ct_general;
spinlock_t lock;
u32 timeout;
struct nf_conntrack_zone zone;
struct nf_conntrack_tuple_hash tuplehash[2];
long unsigned int status;
possible_net_t ct_net;
Expand Down Expand Up @@ -133097,12 +133104,6 @@ struct nf_hook_entries_rcu_head {
void *allocation;
};

struct nf_conntrack_zone {
u16 id;
u8 flags;
u8 dir;
};

struct nf_conntrack_tuple;

struct nf_ct_hook {
Expand Down
180 changes: 180 additions & 0 deletions bpf/pkt_transformation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* Packets Transformations tracker eBPF hooks.
*/

#ifndef __PKT_TRANSFORMATION_H__
#define __PKT_TRANSFORMATION_H__

#include "utils.h"

#define s6_addr in6_u.u6_addr8

static inline void dump_xlated_flow(struct translated_flow_t *flow) {
BPF_PRINTK("zone_id %d sport %d dport %d icmpId %d\n", flow->zone_id, flow->sport, flow->dport,
flow->icmp_id);
int i;
for (i = 0; i < IP_MAX_LEN; i += 4) {
BPF_PRINTK("scrIP[%d]:%d.%d.%d.%d\n", i, flow->saddr[0 + i], flow->saddr[1 + i],
flow->saddr[2 + i], flow->saddr[3 + i]);
}
for (i = 0; i < IP_MAX_LEN; i += 4) {
BPF_PRINTK("dstIP[%d]:%d.%d.%d.%d\n", i, flow->daddr[0 + i], flow->daddr[1 + i],
flow->daddr[2 + i], flow->daddr[3 + i]);
}
}

static inline void parse_tuple(struct nf_conntrack_tuple *t, struct translated_flow_t *flow,
u16 zone_id, u16 family, bool invert) {
__builtin_memset(flow, 0, sizeof(*flow));
if (invert) {
flow->dport = bpf_ntohs(t->src.u.all);
flow->sport = bpf_ntohs(t->dst.u.all);

switch (family) {
case AF_INET:
__builtin_memcpy(flow->saddr, ip4in6, sizeof(ip4in6));
__builtin_memcpy(flow->daddr, ip4in6, sizeof(ip4in6));
bpf_probe_read(flow->daddr + sizeof(ip4in6), sizeof(u32), &t->src.u3.in.s_addr);
bpf_probe_read(flow->saddr + sizeof(ip4in6), sizeof(u32), &t->dst.u3.in.s_addr);
break;

case AF_INET6:
bpf_probe_read(flow->daddr, IP_MAX_LEN, &t->src.u3.in6.s6_addr);
bpf_probe_read(flow->saddr, IP_MAX_LEN, &t->dst.u3.in6.s6_addr);
break;
}
} else {
flow->dport = bpf_ntohs(t->dst.u.all);
flow->sport = bpf_ntohs(t->src.u.all);

switch (family) {
case AF_INET:
__builtin_memcpy(flow->saddr, ip4in6, sizeof(ip4in6));
__builtin_memcpy(flow->daddr, ip4in6, sizeof(ip4in6));
bpf_probe_read(flow->daddr + sizeof(ip4in6), sizeof(u32), &t->dst.u3.in.s_addr);
bpf_probe_read(flow->saddr + sizeof(ip4in6), sizeof(u32), &t->src.u3.in.s_addr);
break;

case AF_INET6:
bpf_probe_read(flow->daddr, IP_MAX_LEN, &t->dst.u3.in6.s6_addr);
bpf_probe_read(flow->saddr, IP_MAX_LEN, &t->src.u3.in6.s6_addr);
break;
}
}
flow->icmp_id = t->src.u.icmp.id;
flow->zone_id = zone_id;
dump_xlated_flow(flow);
}

static inline long translate_lookup_and_update_flow(flow_id *id, u16 flags,
struct nf_conntrack_tuple *orig_t,
struct nf_conntrack_tuple *reply_t, u64 len,
u16 zone_id, u16 family) {
long ret = 0;
u64 current_time = bpf_ktime_get_ns();
struct translated_flow_t orig;

parse_tuple(orig_t, &orig, zone_id, family, false);

// update id with original flow info
__builtin_memcpy(id->src_ip, orig.saddr, IP_MAX_LEN);
__builtin_memcpy(id->dst_ip, orig.daddr, IP_MAX_LEN);
id->src_port = orig.sport;
id->dst_port = orig.dport;

flow_metrics *aggregate_flow = bpf_map_lookup_elem(&aggregated_flows, id);
if (aggregate_flow != NULL) {
aggregate_flow->end_mono_time_ts = current_time;
parse_tuple(reply_t, &aggregate_flow->translated_flow, zone_id, family, true);
ret = bpf_map_update_elem(&aggregated_flows, id, aggregate_flow, BPF_EXIST);
if (trace_messages && ret != 0) {
bpf_printk("error packet translation updating flow %d\n", ret);
}
return ret;
}

// there is no matching flows so lets create new one and add the xlation
flow_metrics new_flow = {
.start_mono_time_ts = current_time,
.end_mono_time_ts = current_time,
.packets = 1,
.bytes = len,
.flags = flags,
};
parse_tuple(reply_t, &new_flow.translated_flow, zone_id, family, true);
ret = bpf_map_update_elem(&aggregated_flows, id, &new_flow, BPF_ANY);
if (trace_messages && ret != 0) {
bpf_printk("error packet translation creating new flow %d\n", ret);
}

return ret;
}

static inline int trace_nat_manip_pkt(struct nf_conn *ct, struct sk_buff *skb) {
struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
u16 family = 0, flags = 0, zone_id = 0;
u8 dscp = 0, protocol = 0;
long ret = 0;
u64 len = 0;
flow_id id;

if (!enable_pkt_transformation_tracking) {
return 0;
}
__builtin_memset(&id, 0, sizeof(id));

bpf_probe_read(&tuplehash, sizeof(tuplehash), &ct->tuplehash);

bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id);
bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id);

struct nf_conntrack_tuple *orig_tuple = &tuplehash[IP_CT_DIR_ORIGINAL].tuple;
struct nf_conntrack_tuple *reply_tuple = &tuplehash[IP_CT_DIR_REPLY].tuple;

len = BPF_CORE_READ(skb, len);
id.if_index = BPF_CORE_READ(skb, skb_iif);
// read L2 info
core_fill_in_l2(skb, &id, &family);

// read L3 info
core_fill_in_l3(skb, &id, family, &protocol, &dscp);

// read L4 info
switch (protocol) {
case IPPROTO_TCP:
core_fill_in_tcp(skb, &id, &flags);
break;
case IPPROTO_UDP:
core_fill_in_udp(skb, &id);
break;
case IPPROTO_SCTP:
core_fill_in_sctp(skb, &id);
break;
case IPPROTO_ICMP:
core_fill_in_icmpv4(skb, &id);
break;
case IPPROTO_ICMPV6:
core_fill_in_icmpv6(skb, &id);
break;
default:
fill_in_others_protocol(&id, protocol);
}

BPF_PRINTK("Xlat: protocol %d flags 0x%x family %d dscp %d\n", protocol, flags, family, dscp);

bpf_probe_read(&zone_id, sizeof(zone_id), &ct->zone.id);
ret =
translate_lookup_and_update_flow(&id, flags, orig_tuple, reply_tuple, len, zone_id, family);

return ret;
}

SEC("kprobe/nf_nat_manip_pkt")
int BPF_KPROBE(track_nat_manip_pkt) {
struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx);
struct nf_conn *ct = (struct nf_conn *)PT_REGS_PARM2(ctx);

return trace_nat_manip_pkt(ct, skb);
}

#endif /* __PKT_TRANSFORMATION_H__ */
11 changes: 11 additions & 0 deletions bpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,14 @@ typedef struct flow_metrics_t {
u64 flow_rtt;
u8 network_events_idx;
u8 network_events[MAX_NETWORK_EVENTS][MAX_EVENT_MD];
struct translated_flow_t {
u8 saddr[IP_MAX_LEN];
u8 daddr[IP_MAX_LEN];
u16 sport;
u16 dport;
u16 zone_id;
u8 icmp_id;
} __attribute__((packed)) translated_flow;
} __attribute__((packed)) flow_metrics;

// Force emitting struct pkt_drops into the ELF.
Expand Down Expand Up @@ -241,4 +249,7 @@ struct filter_value_t {
// Force emitting struct filter_value_t into the ELF.
const struct filter_value_t *unused9 __attribute__((unused));

// Force emitting struct translated_flow_t into the ELF.
const struct translated_flow_t *unused11 __attribute__((unused));

#endif /* __TYPES_H__ */
8 changes: 6 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ require (
github.com/containernetworking/cni v1.1.2 // indirect
github.com/containernetworking/plugins v1.2.0 // indirect
github.com/coreos/go-iptables v0.6.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
Expand Down Expand Up @@ -109,11 +109,12 @@ require (
github.com/safchain/ethtool v0.3.1-0.20231027162144-83e5e0097c91 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/urfave/cli/v2 v2.2.0 // indirect
github.com/urfave/cli/v2 v2.27.2 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect
Expand Down Expand Up @@ -151,3 +152,6 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

// HACK
replace github.com/ovn-org/ovn-kubernetes/go-controller => github.com/npinaeva/ovn-kubernetes/go-controller v0.0.0-20241022150829-c03e72d94693
Loading

0 comments on commit 0695f51

Please sign in to comment.