Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpf: add ext_err for more callers of tail_call_internal() #30023

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 15 additions & 8 deletions bpf/bpf_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -441,11 +441,13 @@ tail_handle_ipv6(struct __ctx_buff *ctx, __u32 ipcache_srcid, const bool from_ho
if (from_host)
ret = invoke_tailcall_if(is_defined(ENABLE_HOST_FIREWALL),
CILIUM_CALL_IPV6_CONT_FROM_HOST,
tail_handle_ipv6_cont_from_host);
tail_handle_ipv6_cont_from_host,
&ext_err);
else
ret = invoke_tailcall_if(is_defined(ENABLE_HOST_FIREWALL),
CILIUM_CALL_IPV6_CONT_FROM_NETDEV,
tail_handle_ipv6_cont_from_netdev);
tail_handle_ipv6_cont_from_netdev,
&ext_err);
}

/* Catch errors from both handle_ipv6 and invoke_tailcall_if here. */
Expand Down Expand Up @@ -891,11 +893,13 @@ tail_handle_ipv4(struct __ctx_buff *ctx, __u32 ipcache_srcid, const bool from_ho
if (from_host)
ret = invoke_tailcall_if(is_defined(ENABLE_HOST_FIREWALL),
CILIUM_CALL_IPV4_CONT_FROM_HOST,
tail_handle_ipv4_cont_from_host);
tail_handle_ipv4_cont_from_host,
&ext_err);
else
ret = invoke_tailcall_if(is_defined(ENABLE_HOST_FIREWALL),
CILIUM_CALL_IPV4_CONT_FROM_NETDEV,
tail_handle_ipv4_cont_from_netdev);
tail_handle_ipv4_cont_from_netdev,
&ext_err);
}

/* Catch errors from both handle_ipv4 and invoke_tailcall_if here. */
Expand Down Expand Up @@ -1575,6 +1579,7 @@ static __always_inline int
to_host_from_lxc(struct __ctx_buff *ctx __maybe_unused)
{
int ret = CTX_ACT_OK;
__s8 ext_err = 0;
__u16 proto = 0;

if (!validate_ethertype(ctx, &proto)) {
Expand All @@ -1594,7 +1599,8 @@ to_host_from_lxc(struct __ctx_buff *ctx __maybe_unused)
is_defined(ENABLE_IPV6)),
is_defined(DEBUG)),
CILIUM_CALL_IPV6_TO_HOST_POLICY_ONLY,
tail_ipv6_host_policy_ingress);
tail_ipv6_host_policy_ingress,
&ext_err);
break;
# endif
# ifdef ENABLE_IPV4
Expand All @@ -1603,7 +1609,8 @@ to_host_from_lxc(struct __ctx_buff *ctx __maybe_unused)
is_defined(ENABLE_IPV6)),
is_defined(DEBUG)),
CILIUM_CALL_IPV4_TO_HOST_POLICY_ONLY,
tail_ipv4_host_policy_ingress);
tail_ipv4_host_policy_ingress,
&ext_err);
break;
# endif
default:
Expand All @@ -1613,8 +1620,8 @@ to_host_from_lxc(struct __ctx_buff *ctx __maybe_unused)

out:
if (IS_ERR(ret))
return send_drop_notify_error(ctx, 0, ret, CTX_ACT_DROP,
METRIC_INGRESS);
return send_drop_notify_error_ext(ctx, 0, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);
return ret;
}

Expand Down
48 changes: 27 additions & 21 deletions bpf/bpf_lxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ select_ct_map4(struct __ctx_buff *ctx __maybe_unused, int dir __maybe_unused,

#if defined ENABLE_IPV4 || defined ENABLE_IPV6
static __always_inline int drop_for_direction(struct __ctx_buff *ctx,
enum ct_dir dir, __u32 reason)
enum ct_dir dir, __u32 reason,
__s8 ext_err)
{
__u32 dst = 0;
__u32 dst_id = 0;
Expand Down Expand Up @@ -249,8 +250,8 @@ static __always_inline int drop_for_direction(struct __ctx_buff *ctx,
__throw_build_bug();
}

return send_drop_notify(ctx, src_label, dst, dst_id, reason,
CTX_ACT_DROP, m_dir);
return send_drop_notify_ext(ctx, src_label, dst, dst_id, reason,
ext_err, CTX_ACT_DROP, m_dir);
}
#endif /* ENABLE_IPV4 || ENABLE_IPV6 */

Expand All @@ -264,14 +265,15 @@ int NAME(struct __ctx_buff *ctx) \
void *data, *data_end; \
int ret = CTX_ACT_OK; \
struct iphdr *ip4; \
__s8 ext_err = 0; \
__u32 zero = 0; \
void *map; \
\
ct_state = (struct ct_state *)&ct_buffer.ct_state; \
tuple = (struct ipv4_ct_tuple *)&ct_buffer.tuple; \
\
if (!revalidate_data(ctx, &data, &data_end, &ip4)) \
return drop_for_direction(ctx, DIR, DROP_INVALID); \
return drop_for_direction(ctx, DIR, DROP_INVALID, ext_err); \
\
tuple->nexthdr = ip4->protocol; \
tuple->daddr = ip4->daddr; \
Expand All @@ -280,18 +282,20 @@ int NAME(struct __ctx_buff *ctx) \
\
map = select_ct_map4(ctx, DIR, tuple); \
if (!map) \
return drop_for_direction(ctx, DIR, DROP_CT_NO_MAP_FOUND); \
return drop_for_direction(ctx, DIR, DROP_CT_NO_MAP_FOUND, \
ext_err); \
\
ct_buffer.ret = ct_lookup4(map, tuple, ctx, ip4, ct_buffer.l4_off, \
DIR, ct_state, &ct_buffer.monitor); \
if (ct_buffer.ret < 0) \
return drop_for_direction(ctx, DIR, ct_buffer.ret); \
return drop_for_direction(ctx, DIR, ct_buffer.ret, ext_err); \
if (map_update_elem(&CT_TAIL_CALL_BUFFER4, &zero, &ct_buffer, 0) < 0) \
return drop_for_direction(ctx, DIR, DROP_INVALID_TC_BUFFER); \
return drop_for_direction(ctx, DIR, DROP_INVALID_TC_BUFFER, \
ext_err); \
\
ret = invoke_tailcall_if(CONDITION, TARGET_ID, TARGET_NAME); \
ret = invoke_tailcall_if(CONDITION, TARGET_ID, TARGET_NAME, &ext_err); \
if (IS_ERR(ret)) \
return drop_for_direction(ctx, DIR, ret); \
return drop_for_direction(ctx, DIR, ret, ext_err); \
\
return ret; \
}
Expand All @@ -306,37 +310,38 @@ int NAME(struct __ctx_buff *ctx) \
struct ct_state *ct_state; \
void *data, *data_end; \
struct ipv6hdr *ip6; \
__s8 ext_err = 0; \
__u32 zero = 0; \
\
ct_state = (struct ct_state *)&ct_buffer.ct_state; \
tuple = (struct ipv6_ct_tuple *)&ct_buffer.tuple; \
\
if (!revalidate_data(ctx, &data, &data_end, &ip6)) \
return drop_for_direction(ctx, DIR, DROP_INVALID); \
return drop_for_direction(ctx, DIR, DROP_INVALID, ext_err); \
\
tuple->nexthdr = ip6->nexthdr; \
ipv6_addr_copy(&tuple->daddr, (union v6addr *)&ip6->daddr); \
ipv6_addr_copy(&tuple->saddr, (union v6addr *)&ip6->saddr); \
\
hdrlen = ipv6_hdrlen(ctx, &tuple->nexthdr); \
if (hdrlen < 0) \
return drop_for_direction(ctx, DIR, hdrlen); \
return drop_for_direction(ctx, DIR, hdrlen, ext_err); \
\
ct_buffer.l4_off = ETH_HLEN + hdrlen; \
\
ct_buffer.ret = ct_lookup6(get_ct_map6(tuple), tuple, ctx, \
ct_buffer.l4_off, DIR, ct_state, \
&ct_buffer.monitor); \
if (ct_buffer.ret < 0) \
return drop_for_direction(ctx, DIR, ct_buffer.ret); \
return drop_for_direction(ctx, DIR, ct_buffer.ret, ext_err); \
\
if (map_update_elem(&CT_TAIL_CALL_BUFFER6, &zero, &ct_buffer, 0) < 0) \
return drop_for_direction(ctx, DIR, \
DROP_INVALID_TC_BUFFER); \
return drop_for_direction(ctx, DIR, DROP_INVALID_TC_BUFFER, \
ext_err); \
\
ret = invoke_tailcall_if(CONDITION, TARGET_ID, TARGET_NAME); \
ret = invoke_tailcall_if(CONDITION, TARGET_ID, TARGET_NAME, &ext_err); \
if (IS_ERR(ret)) \
return drop_for_direction(ctx, DIR, ret); \
return drop_for_direction(ctx, DIR, ret, ext_err); \
\
return ret; \
}
Expand Down Expand Up @@ -763,7 +768,7 @@ static __always_inline int __tail_handle_ipv6(struct __ctx_buff *ctx,
* are subjected to forwarding into the container.
*/
if (unlikely(is_icmp6_ndp(ctx, ip6, ETH_HLEN)))
return icmp6_ndp_handle(ctx, ETH_HLEN, METRIC_EGRESS);
return icmp6_ndp_handle(ctx, ETH_HLEN, METRIC_EGRESS, ext_err);

if (unlikely(!is_valid_lxc_src_ip(ip6)))
return DROP_INVALID_SIP;
Expand Down Expand Up @@ -2261,6 +2266,7 @@ int handle_policy(struct __ctx_buff *ctx)
{
__u32 src_label = ctx_load_meta(ctx, CB_SRC_LABEL);
__u32 sec_label = SECLABEL;
__s8 ext_err = 0;
__u16 proto;
int ret;

Expand All @@ -2274,15 +2280,15 @@ int handle_policy(struct __ctx_buff *ctx)
case bpf_htons(ETH_P_IPV6):
ret = invoke_tailcall_if(__and(is_defined(ENABLE_IPV4), is_defined(ENABLE_IPV6)),
CILIUM_CALL_IPV6_CT_INGRESS_POLICY_ONLY,
tail_ipv6_ct_ingress_policy_only);
tail_ipv6_ct_ingress_policy_only, &ext_err);
sec_label = SECLABEL_IPV6;
break;
#endif /* ENABLE_IPV6 */
#ifdef ENABLE_IPV4
case bpf_htons(ETH_P_IP):
ret = invoke_tailcall_if(__and(is_defined(ENABLE_IPV4), is_defined(ENABLE_IPV6)),
CILIUM_CALL_IPV4_CT_INGRESS_POLICY_ONLY,
tail_ipv4_ct_ingress_policy_only);
tail_ipv4_ct_ingress_policy_only, &ext_err);
sec_label = SECLABEL_IPV4;
break;
#endif /* ENABLE_IPV4 */
Expand All @@ -2293,8 +2299,8 @@ int handle_policy(struct __ctx_buff *ctx)

out:
if (IS_ERR(ret))
return send_drop_notify(ctx, src_label, sec_label, LXC_ID,
ret, CTX_ACT_DROP, METRIC_INGRESS);
return send_drop_notify_ext(ctx, src_label, sec_label, LXC_ID, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);

return ret;
}
Expand Down
11 changes: 7 additions & 4 deletions bpf/lib/icmp6.h
Original file line number Diff line number Diff line change
Expand Up @@ -346,18 +346,20 @@ int tail_icmp6_handle_ns(struct __ctx_buff *ctx)
* @ctx: socket buffer
* @nh_off: offset to the IPv6 header
* @direction: direction of packet(ingress or egress)
* @ext_err: extended error value
*
* Respond to ICMPv6 Neighbour Solicitation
*
* NOTE: This is terminal function and will cause the BPF program to exit
*/
static __always_inline int icmp6_handle_ns(struct __ctx_buff *ctx, int nh_off,
enum metric_dir direction)
enum metric_dir direction,
__s8 *ext_err)
{
ctx_store_meta(ctx, 0, nh_off);
ctx_store_meta(ctx, 1, direction);

return tail_call_internal(ctx, CILIUM_CALL_HANDLE_ICMP6_NS, NULL);
return tail_call_internal(ctx, CILIUM_CALL_HANDLE_ICMP6_NS, ext_err);
}

static __always_inline bool
Expand All @@ -373,7 +375,8 @@ is_icmp6_ndp(struct __ctx_buff *ctx, const struct ipv6hdr *ip6, int nh_off)
}

static __always_inline int icmp6_ndp_handle(struct __ctx_buff *ctx, int nh_off,
enum metric_dir direction)
enum metric_dir direction,
__s8 *ext_err)
{
__u8 type;

Expand All @@ -382,7 +385,7 @@ static __always_inline int icmp6_ndp_handle(struct __ctx_buff *ctx, int nh_off,

cilium_dbg(ctx, DBG_ICMP6_HANDLE, type, 0);
if (type == ICMP6_NS_MSG_TYPE)
return icmp6_handle_ns(ctx, nh_off, direction);
return icmp6_handle_ns(ctx, nh_off, direction, ext_err);

/* All branching above will have issued a tail call, all
* remaining traffic is subject to forwarding to containers.
Expand Down
10 changes: 5 additions & 5 deletions bpf/lib/tailcall.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,14 @@
#define declare_tailcall_if(COND, NAME) \
__eval(__declare_tailcall_if_, COND)(NAME)

#define __invoke_tailcall_if_0(NAME, FUNC) \
#define __invoke_tailcall_if_0(NAME, FUNC, EXT_ERR) \
FUNC(ctx)
#define __invoke_tailcall_if_1(NAME, FUNC) \
#define __invoke_tailcall_if_1(NAME, FUNC, EXT_ERR) \
({ \
tail_call_internal(ctx, NAME, NULL); \
tail_call_internal(ctx, NAME, EXT_ERR); \
})
#define invoke_tailcall_if(COND, NAME, FUNC) \
__eval(__invoke_tailcall_if_, COND)(NAME, FUNC)
#define invoke_tailcall_if(COND, NAME, FUNC, EXT_ERR) \
__eval(__invoke_tailcall_if_, COND)(NAME, FUNC, EXT_ERR)

#define __invoke_traced_tailcall_if_0(NAME, FUNC, TRACE, EXT_ERR) \
FUNC(ctx, TRACE, EXT_ERR)
Expand Down