Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 54 additions & 55 deletions Documentation/network/l2-announcements.rst

Large diffs are not rendered by default.

66 changes: 51 additions & 15 deletions bpf/bpf_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1018,14 +1018,26 @@ static __always_inline int do_netdev_encrypt_encap(struct __ctx_buff *ctx, __u32
#endif /* ENABLE_IPSEC && TUNNEL_MODE */

#ifdef ENABLE_L2_ANNOUNCEMENTS
static __always_inline int handle_l2_announcement(struct __ctx_buff *ctx)
static __always_inline int handle_l2_announcement(struct __ctx_buff *ctx,
struct ipv6hdr* ip6)
{
union macaddr mac = THIS_INTERFACE_MAC;
union macaddr smac;
__be32 sip;
__be32 tip;
struct l2_responder_v4_key key;
struct l2_responder_v4_stats *stats;
union {
struct {
__be32 sip;
__be32 tip;
struct l2_responder_v4_key key;
} __maybe_unused v4;

struct {
union v6addr sip;
union v6addr tip;
struct l2_responder_v6_key __maybe_unused key;
} __maybe_unused v6;
}d;

struct l2_responder_stats *stats;
int ret;
__u32 index = RUNTIME_CONFIG_AGENT_LIVENESS;
__u64 *time;
Expand All @@ -1041,22 +1053,38 @@ static __always_inline int handle_l2_announcement(struct __ctx_buff *ctx)
if (ktime_get_ns() - (*time) > L2_ANNOUNCEMENTS_MAX_LIVENESS)
return CTX_ACT_OK;

if (!arp_validate(ctx, &mac, &smac, &sip, &tip))
return CTX_ACT_OK;
if (!ip6) {
if (!arp_validate(ctx, &mac, &smac, &d.v4.sip, &d.v4.tip))
return CTX_ACT_OK;

key.ip4 = tip;
key.ifindex = ctx->ingress_ifindex;
stats = map_lookup_elem(&L2_RESPONDER_MAP4, &key);
if (!stats)
return CTX_ACT_OK;
d.v4.key.ip4 = d.v4.tip;
d.v4.key.ifindex = ctx->ingress_ifindex;
stats = map_lookup_elem(&L2_RESPONDER_MAP4, &d.v4.key);
if (!stats)
return CTX_ACT_OK;

ret = arp_respond(ctx, &mac, d.v4.tip, &smac, d.v4.sip, 0);
} else {

if (!icmp6_ndisc_validate(ctx, ip6, &mac, &smac, &d.v6.sip,
&d.v6.tip))
return CTX_ACT_OK;

ret = arp_respond(ctx, &mac, tip, &smac, sip, 0);
d.v6.key.ip6 = d.v6.tip;
d.v6.key.ifindex = ctx->ingress_ifindex;
stats = map_lookup_elem(&L2_RESPONDER_MAP6, &d.v6.key);
if (!stats)
return CTX_ACT_OK;
int l3_off = (__u8*)ip6 - (__u8*)ctx_data(ctx);
ret = send_icmp6_ndisc_adv(ctx, l3_off, &mac, false);
}

if (ret == CTX_ACT_REDIRECT)
__sync_fetch_and_add(&stats->responses_sent, 1);

return ret;
};
}

#endif

static __always_inline int
Expand All @@ -1076,6 +1104,7 @@ do_netdev(struct __ctx_buff *ctx, __u16 proto, const bool from_host)
int __maybe_unused hdrlen = 0;
__u8 __maybe_unused next_proto = 0;
__s8 __maybe_unused ext_err = 0;
__u8 __maybe_unused next_hdr;
int ret;

#ifdef ENABLE_IPSEC
Expand Down Expand Up @@ -1148,7 +1177,7 @@ do_netdev(struct __ctx_buff *ctx, __u16 proto, const bool from_host)
send_trace_notify(ctx, obs_point, UNKNOWN_ID, UNKNOWN_ID, TRACE_EP_ID_UNKNOWN,
ctx->ingress_ifindex, trace.reason, trace.monitor);
#ifdef ENABLE_L2_ANNOUNCEMENTS
ret = handle_l2_announcement(ctx);
ret = handle_l2_announcement(ctx, NULL);
#else
ret = CTX_ACT_OK;
#endif
Expand All @@ -1159,6 +1188,13 @@ do_netdev(struct __ctx_buff *ctx, __u16 proto, const bool from_host)
if (!revalidate_data_pull(ctx, &data, &data_end, &ip6))
return send_drop_notify_error(ctx, identity, DROP_INVALID,
CTX_ACT_DROP, METRIC_INGRESS);
#ifdef ENABLE_L2_ANNOUNCEMENTS
if (ip6->nexthdr == NEXTHDR_ICMP) {
ret = handle_l2_announcement(ctx, ip6);
if (ret != CTX_ACT_OK)
break;
}
#endif /*ENABLE_L2_ANNOUNCEMENTS */

identity = resolve_srcid_ipv6(ctx, ip6, identity, &ipcache_srcid, from_host);
ctx_store_meta(ctx, CB_SRC_LABEL, identity);
Expand Down
30 changes: 29 additions & 1 deletion bpf/lib/icmp6.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/* Copyright Authors of Cilium */

#if !defined(__LIB_ICMP6__) && defined(ENABLE_IPV6)
#ifndef __LIB_ICMP6__
#define __LIB_ICMP6__

#include <linux/icmpv6.h>
Expand Down Expand Up @@ -477,4 +477,32 @@ icmp6_host_handle(struct __ctx_buff *ctx, int l4_off, __s8 *ext_err, bool handle
#endif /* ENABLE_HOST_FIREWALL */
}

static __always_inline bool
icmp6_ndisc_validate(struct __ctx_buff *ctx, struct ipv6hdr* ip6,
union macaddr *mac,
union macaddr *smac,
union v6addr* sip,
union v6addr *tip)
{
__u8 nexthdr;
struct icmp6hdr* icmp;

int l3_off = (__u8*)ip6 - (__u8*)ctx_data(ctx);
int l4_off = ipv6_hdrlen_offset(ctx, &nexthdr, l3_off);
if (l4_off < 0 || nexthdr != NEXTHDR_ICMP)
return false;

icmp = (struct icmp6hdr*) ((__u8*)ctx_data(ctx) + l4_off);
if (icmp->icmp6_type != ICMP6_NS_MSG_TYPE)
return false;

/* Extract fields */
eth_load_saddr(ctx, &smac->addr[0], 0);
eth_load_daddr(ctx, &mac->addr[0], 0);
ipv6_load_saddr(ctx, l3_off, sip);
ipv6_load_daddr(ctx, l3_off, tip);

return true;
}

#endif
18 changes: 16 additions & 2 deletions bpf/lib/maps.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,19 +194,33 @@ struct l2_responder_v4_key {
__u32 ifindex;
};

struct l2_responder_v4_stats {
struct l2_responder_stats {
__u64 responses_sent;
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, struct l2_responder_v4_key);
__type(value, struct l2_responder_v4_stats);
__type(value, struct l2_responder_stats);
__uint(pinning, LIBBPF_PIN_BY_NAME);
__uint(max_entries, L2_RESPONSER_MAP4_SIZE);
__uint(map_flags, BPF_F_NO_PREALLOC);
} L2_RESPONDER_MAP4 __section_maps_btf;

struct l2_responder_v6_key {
union v6addr ip6;
__u32 ifindex;
};

struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, struct l2_responder_v6_key);
__type(value, struct l2_responder_stats);
__uint(pinning, LIBBPF_PIN_BY_NAME);
__uint(max_entries, L2_RESPONSER_MAP6_SIZE);
__uint(map_flags, BPF_F_NO_PREALLOC);
} L2_RESPONDER_MAP6 __section_maps_btf;

#ifdef ENABLE_SRV6
# define SRV6_VRF_MAP(IP_FAMILY) \
struct { \
Expand Down
2 changes: 2 additions & 0 deletions bpf/node_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ DEFINE_IPV6(HOST_IP, 0xbe, 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0xa, 0x
#define NODE_MAP_V2 test_cilium_node_map
#define ENCRYPT_MAP test_cilium_encrypt_state
#define L2_RESPONDER_MAP4 test_cilium_l2_responder_v4
#define L2_RESPONDER_MAP6 test_cilium_l2_responder_v6
#define RATELIMIT_MAP test_cilium_ratelimit
#define RATELIMIT_METRICS_MAP test_cilium_ratelimit_metrics
#define TUNNEL_MAP test_cilium_tunnel_map
Expand Down Expand Up @@ -205,6 +206,7 @@ DEFINE_IPV6(HOST_IP, 0xbe, 0xef, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0xa, 0x
#define SRV6_POLICY_MAP_SIZE 16384
#define SRV6_SID_MAP_SIZE 16384
#define L2_RESPONSER_MAP4_SIZE 4096
#define L2_RESPONSER_MAP6_SIZE 4096
#define POLICY_PROG_MAP_SIZE ENDPOINTS_MAP_SIZE
#define IPV4_FRAG_DATAGRAMS_MAP test_cilium_ipv4_frag_datagrams
#define CILIUM_IPV4_FRAG_MAP_MAX_ENTRIES 8192
Expand Down
8 changes: 8 additions & 0 deletions bpf/tests/pktgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ static volatile const __u8 mac_zero[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

#define v4_all IPV4(0, 0, 0, 0)

/* IPv6 addresses for hosts, external to the cluster */
static volatile const __section(".rodata") __u8 v6_ext_one[] = {0xfd, 0x03, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};

/* IPv6 addresses for pods in the cluster */
static volatile const __section(".rodata") __u8 v6_pod_one[] = {0xfd, 0x04, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};
Expand All @@ -81,6 +85,10 @@ static volatile const __section(".rodata") __u8 v6_node_two[] = {0xfd, 0x06, 0,
static volatile const __section(".rodata") __u8 v6_node_three[] = {0xfd, 0x07, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 3};

/* IPv6 addresses for services in the cluster */
static volatile const __section(".rodata") __u8 v6_svc_one[] = {0xfd, 0x10, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1};

/* Source port to be used by a client */
#define tcp_src_one __bpf_htons(22330)
#define tcp_src_two __bpf_htons(33440)
Expand Down
2 changes: 1 addition & 1 deletion bpf/tests/tc_l2_announcement.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ SETUP("tc", "1_happy_path")
int l2_announcement_arp_happy_path_setup(struct __ctx_buff *ctx)
{
struct l2_responder_v4_key key;
struct l2_responder_v4_stats value = {0};
struct l2_responder_stats value = {0};
__u32 index;
__u64 time;

Expand Down
Loading