Skip to content

Commit

Permalink
extend flow filter apis to introduce peerCIDR and make it part of the…
Browse files Browse the repository at this point in the history
… key

Signed-off-by: Mohamed Mahmoud <[email protected]>
  • Loading branch information
msherif1234 committed Jan 8, 2025
1 parent 7c29f2a commit 01e6b2a
Show file tree
Hide file tree
Showing 17 changed files with 247 additions and 168 deletions.
125 changes: 57 additions & 68 deletions bpf/flows_filter.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,75 @@
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++) {
if (ip[i] != 0) {
BPF_PRINTK("ip not zero ip[%d]:%d\n", i, ip[i]);
return 0;
}
}
return 1;
}
static __always_inline int flow_filter_setup_lookup_key(flow_id *id, struct filter_key_t *key,
u8 *len, u8 *offset, bool use_src_ip,
u16 eth_protocol) {

static __always_inline int is_equal_ip(u8 *ip1, u8 *ip2, u8 len) {
for (int i = 0; i < len; i++) {
if (ip1[i] != ip2[i]) {
BPF_PRINTK("ip mismatched ip1[%d]:%d not equal to ip2[%d]:%d\n", i, ip1[i], i, ip2[i]);
return 0;
if (eth_protocol == ETH_P_IP) {
*len = sizeof(u32);
*offset = sizeof(ip4in6);
if (use_src_ip) {
__builtin_memcpy(key->ip_data, id->src_ip + *offset, *len);
} else {
__builtin_memcpy(key->ip_data, id->dst_ip + *offset, *len);
}
key->prefix_len = 32;
} else if (eth_protocol == ETH_P_IPV6) {
*len = IP_MAX_LEN;
*offset = 0;
if (use_src_ip) {
__builtin_memcpy(key->ip_data, id->src_ip + *offset, *len);
} else {
__builtin_memcpy(key->ip_data, id->dst_ip + *offset, *len);
}
key->prefix_len = 128;
} else {
return -1;
}
return 1;
return 0;
}

static __always_inline int do_flow_filter_lookup(flow_id *id, struct filter_key_t *key,
filter_action *action, u8 len, u8 offset,
u16 flags, u32 drop_reason, u32 *sampling,
u8 direction) {
u8 direction, bool use_src_ip, u16 eth_protocol) {
int result = 0;

struct filter_value_t *rule = (struct filter_value_t *)bpf_map_lookup_elem(&filter_map, key);

if (rule) {
BPF_PRINTK("rule found drop_reason %d flags %d\n", drop_reason, flags);
BPF_PRINTK("rule found drop_reason %d flags %d do_peerCIDR_lookup %d\n", drop_reason, flags,
rule->do_peerCIDR_lookup);
result++;
if (rule->do_peerCIDR_lookup) {
struct filter_key_t peerKey;
__builtin_memset(&peerKey, 0, sizeof(peerKey));
// PeerCIDR lookup will will target the opposite IP compared to original CIDR lookup
// In other words in cidr is using srcIP then peerCIDR will be the dstIP
if (flow_filter_setup_lookup_key(id, &peerKey, &len, &offset, use_src_ip,
eth_protocol) < 0) {
BPF_PRINTK("peerCIDR failed to setup lookup key\n");
result = 0;
goto end;
}

u8 *peer_result = (u8 *)bpf_map_lookup_elem(&peer_filter_map, &peerKey);
if (peer_result) {
if (*peer_result == 0) {
BPF_PRINTK("peerCIDR mismatched\n");
result = 0;
goto end;
} else {
BPF_PRINTK("peerCIDR matched\n");
result++;
}
} else {
BPF_PRINTK("peerCIDR couldn't find a matching key\n");
result = 0;
goto end;
}
}

if (rule->action != MAX_FILTER_ACTIONS) {
BPF_PRINTK("action matched: %d\n", rule->action);
*action = rule->action;
Expand Down Expand Up @@ -160,27 +198,6 @@ static __always_inline int do_flow_filter_lookup(flow_id *id, struct filter_key_
goto end;
}

if (!is_zero_ip(rule->ip, len)) {
// for Ingress side we can filter using dstIP and for Egress side we can filter using srcIP
if (direction == INGRESS) {
if (is_equal_ip(rule->ip, id->dst_ip + offset, len)) {
BPF_PRINTK("dstIP matched\n");
result++;
} else {
result = 0;
goto end;
}
} else {
if (is_equal_ip(rule->ip, id->src_ip + offset, len)) {
BPF_PRINTK("srcIP matched\n");
result++;
} else {
result = 0;
goto end;
}
}
}

if (rule->direction != MAX_DIRECTION) {
if (rule->direction == direction) {
BPF_PRINTK("direction matched\n");
Expand All @@ -206,34 +223,6 @@ static __always_inline int do_flow_filter_lookup(flow_id *id, struct filter_key_
return result;
}

static __always_inline int flow_filter_setup_lookup_key(flow_id *id, struct filter_key_t *key,
u8 *len, u8 *offset, bool use_src_ip,
u16 eth_protocol) {

if (eth_protocol == ETH_P_IP) {
*len = sizeof(u32);
*offset = sizeof(ip4in6);
if (use_src_ip) {
__builtin_memcpy(key->ip_data, id->src_ip + *offset, *len);
} else {
__builtin_memcpy(key->ip_data, id->dst_ip + *offset, *len);
}
key->prefix_len = 32;
} else if (eth_protocol == ETH_P_IPV6) {
*len = IP_MAX_LEN;
*offset = 0;
if (use_src_ip) {
__builtin_memcpy(key->ip_data, id->src_ip + *offset, *len);
} else {
__builtin_memcpy(key->ip_data, id->dst_ip + *offset, *len);
}
key->prefix_len = 128;
} else {
return -1;
}
return 0;
}

/*
* check if the flow match filter rule and return >= 1 if the flow is to be dropped
*/
Expand All @@ -254,7 +243,7 @@ static __always_inline int is_flow_filtered(flow_id *id, filter_action *action,
}

result = do_flow_filter_lookup(id, &key, action, len, offset, flags, drop_reason, sampling,
direction);
direction, false, eth_protocol);
// we have a match so return
if (result > 0) {
return result;
Expand All @@ -267,7 +256,7 @@ static __always_inline int is_flow_filtered(flow_id *id, filter_action *action,
}

return do_flow_filter_lookup(id, &key, action, len, offset, flags, drop_reason, sampling,
direction);
direction, true, eth_protocol);
}

#endif //__FLOWS_FILTER_H__
12 changes: 11 additions & 1 deletion bpf/maps_definition.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct {
__uint(pinning, LIBBPF_PIN_BY_NAME);
} global_counters SEC(".maps");

// LPM trie map used to filter traffic by IP address CIDR and direction
// LPM trie map used to filter traffic by IP address CIDR
struct {
__uint(type, BPF_MAP_TYPE_LPM_TRIE);
__type(key, struct filter_key_t);
Expand All @@ -69,4 +69,14 @@ struct {
__uint(pinning, LIBBPF_PIN_BY_NAME);
} filter_map SEC(".maps");

// LPM trie map used to filter traffic by peer IP address CIDR
struct {
__uint(type, BPF_MAP_TYPE_LPM_TRIE);
__type(key, struct filter_key_t);
__type(value, u8);
__uint(max_entries, MAX_FILTER_ENTRIES);
__uint(map_flags, BPF_F_NO_PREALLOC);
__uint(pinning, LIBBPF_PIN_BY_NAME);
} peer_filter_map SEC(".maps");

#endif //__MAPS_DEFINITION_H__
4 changes: 2 additions & 2 deletions bpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,8 +269,8 @@ struct filter_value_t {
tcp_flags tcpFlags;
u8 filter_drops;
u32 sample;
u8 ip[IP_MAX_LEN];
} __attribute__((packed));
u8 do_peerCIDR_lookup;
} filter_value;

// Force emitting enums/structs into the ELF
const struct filter_value_t *unused12 __attribute__((unused));
Expand Down
3 changes: 2 additions & 1 deletion hack/build-bytecode-images-multi.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ MAPS='{
"packets_record":"perf_event_array",
"dns_flows":"hash",
"global_counters":"per_cpu_array",
"filter_map":"lpm_trie"
"filter_map":"lpm_trie",
"peer_filter_map":"lpm_trie"
}'

if [[ ${OCI_BIN} == "docker" ]]; then
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ func FlowsAgent(cfg *Config) (*Flows, error) {
FilterIPCIDR: r.FilterIPCIDR,
FilterProtocol: r.FilterProtocol,
FilterPeerIP: r.FilterPeerIP,
FilterPeerCIDR: r.FilterPeerCIDR,
FilterDestinationPort: tracer.ConvertFilterPortsToInstr(r.FilterDestinationPort, r.FilterDestinationPortRange, r.FilterDestinationPorts),
FilterSourcePort: tracer.ConvertFilterPortsToInstr(r.FilterSourcePort, r.FilterSourcePortRange, r.FilterSourcePorts),
FilterPort: tracer.ConvertFilterPortsToInstr(r.FilterPort, r.FilterPortRange, r.FilterPorts),
Expand Down
3 changes: 3 additions & 0 deletions pkg/agent/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ type FlowFilter struct {
FilterDrops bool `json:"drops,omitempty"`
// FilterSample is the sample rate this matching flow will use
FilterSample uint32 `json:"sample,omitempty"`
// FilterPeerCIDR is the PeerIP CIDR to filter flows.
// Example: 10.10.10.0/24 or 100:100:100:100::/64, default is 0.0.0.0/0
FilterPeerCIDR string `json:"peer_cidr,omitempty"`
}

type Config struct {
Expand Down
1 change: 1 addition & 0 deletions pkg/agent/packets_agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ func PacketsAgent(cfg *Config) (*Packets, error) {
FilterIPCIDR: r.FilterIPCIDR,
FilterProtocol: r.FilterProtocol,
FilterPeerIP: r.FilterPeerIP,
FilterPeerCIDR: r.FilterPeerCIDR,
FilterDestinationPort: tracer.ConvertFilterPortsToInstr(r.FilterDestinationPort, r.FilterDestinationPortRange, r.FilterDestinationPorts),
FilterSourcePort: tracer.ConvertFilterPortsToInstr(r.FilterSourcePort, r.FilterSourcePortRange, r.FilterSourcePorts),
FilterPort: tracer.ConvertFilterPortsToInstr(r.FilterPort, r.FilterPortRange, r.FilterPorts),
Expand Down
48 changes: 27 additions & 21 deletions pkg/ebpf/bpf_arm64_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_arm64_bpfel.o
Binary file not shown.
48 changes: 27 additions & 21 deletions pkg/ebpf/bpf_powerpc_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified pkg/ebpf/bpf_powerpc_bpfel.o
Binary file not shown.
Loading

0 comments on commit 01e6b2a

Please sign in to comment.