Skip to content

Commit

Permalink
bpf: Pass ext_err to ct_create4 and ct_create6
Browse files Browse the repository at this point in the history
Start passing the new ext_err parameter to ct_create4 and ct_create6
everywhere where possible. Expose the kernel error code returned by
map_update_elem to drop notifications.

As a side effect, ext_err set by policy_can_access_ingress in
ipv{4,6}_host_policy_egress is now also passed to the caller and the
drop notification.

Signed-off-by: Maxim Mikityanskiy <maxim@isovalent.com>
  • Loading branch information
gentoo-root authored and pchaigno committed Apr 18, 2023
1 parent 7bfe101 commit d749a59
Show file tree
Hide file tree
Showing 10 changed files with 206 additions and 132 deletions.
31 changes: 17 additions & 14 deletions bpf/bpf_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ handle_ipv6(struct __ctx_buff *ctx, __u32 secctx, const bool from_host,
#ifdef ENABLE_NODEPORT
if (!from_host) {
if (!ctx_skip_nodeport(ctx)) {
ret = nodeport_lb6(ctx, secctx);
ret = nodeport_lb6(ctx, secctx, ext_err);
/* nodeport_lb6() returns with TC_ACT_REDIRECT for
* traffic to L7 LB. Policy enforcement needs to take
* place after L7 LB has processed the packet, so we
Expand All @@ -216,7 +216,7 @@ handle_ipv6(struct __ctx_buff *ctx, __u32 secctx, const bool from_host,
if (IS_ERR(ret))
return ret;
} else if (!ctx_skip_host_fw(ctx)) {
ret = ipv6_host_policy_ingress(ctx, &remote_id, &trace);
ret = ipv6_host_policy_ingress(ctx, &remote_id, &trace, ext_err);
if (IS_ERR(ret))
return ret;
}
Expand Down Expand Up @@ -480,7 +480,7 @@ handle_ipv4(struct __ctx_buff *ctx, __u32 secctx,
#ifdef ENABLE_NODEPORT
if (!from_host) {
if (!ctx_skip_nodeport(ctx)) {
ret = nodeport_lb4(ctx, secctx);
ret = nodeport_lb4(ctx, secctx, ext_err);
if (ret == NAT_46X64_RECIRC) {
ctx_store_meta(ctx, CB_SRC_LABEL, secctx);
ep_tail_call(ctx, CILIUM_CALL_IPV6_FROM_NETDEV);
Expand Down Expand Up @@ -514,7 +514,7 @@ handle_ipv4(struct __ctx_buff *ctx, __u32 secctx,
return ret;
} else if (!ctx_skip_host_fw(ctx)) {
/* We're on the ingress path of the native device. */
ret = ipv4_host_policy_ingress(ctx, &remote_id, &trace);
ret = ipv4_host_policy_ingress(ctx, &remote_id, &trace, ext_err);
if (IS_ERR(ret))
return ret;
}
Expand Down Expand Up @@ -1259,6 +1259,7 @@ int cil_to_host(struct __ctx_buff *ctx)
int ret = CTX_ACT_OK;
bool traced = false;
__u32 src_id = 0;
__s8 ext_err = 0;

if ((magic & MARK_MAGIC_HOST_MASK) == MARK_MAGIC_ENCRYPT) {
ctx->mark = magic; /* CB_ENCRYPT_MAGIC */
Expand Down Expand Up @@ -1301,12 +1302,12 @@ int cil_to_host(struct __ctx_buff *ctx)
# endif
# ifdef ENABLE_IPV6
case bpf_htons(ETH_P_IPV6):
ret = ipv6_host_policy_ingress(ctx, &src_id, &trace);
ret = ipv6_host_policy_ingress(ctx, &src_id, &trace, &ext_err);
break;
# endif
# ifdef ENABLE_IPV4
case bpf_htons(ETH_P_IP):
ret = ipv4_host_policy_ingress(ctx, &src_id, &trace);
ret = ipv4_host_policy_ingress(ctx, &src_id, &trace, &ext_err);
break;
# endif
default:
Expand All @@ -1319,8 +1320,8 @@ int cil_to_host(struct __ctx_buff *ctx)

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

if (!traced)
send_trace_notify(ctx, TRACE_TO_STACK, src_id, 0, 0,
Expand All @@ -1341,11 +1342,12 @@ int tail_ipv6_host_policy_ingress(struct __ctx_buff *ctx)
};
__u32 src_id = 0;
int ret;
__s8 ext_err = 0;

ret = ipv6_host_policy_ingress(ctx, &src_id, &trace);
ret = ipv6_host_policy_ingress(ctx, &src_id, &trace, &ext_err);
if (IS_ERR(ret))
return send_drop_notify_error(ctx, src_id, ret, CTX_ACT_DROP,
METRIC_INGRESS);
return send_drop_notify_error_ext(ctx, src_id, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);
return ret;
}
#endif /* ENABLE_IPV6 */
Expand All @@ -1361,11 +1363,12 @@ int tail_ipv4_host_policy_ingress(struct __ctx_buff *ctx)
};
__u32 src_id = 0;
int ret;
__s8 ext_err = 0;

ret = ipv4_host_policy_ingress(ctx, &src_id, &trace);
ret = ipv4_host_policy_ingress(ctx, &src_id, &trace, &ext_err);
if (IS_ERR(ret))
return send_drop_notify_error(ctx, src_id, ret, CTX_ACT_DROP,
METRIC_INGRESS);
return send_drop_notify_error_ext(ctx, src_id, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);
return ret;
}
#endif /* ENABLE_IPV4 */
Expand Down
54 changes: 36 additions & 18 deletions bpf/bpf_lxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@
#ifdef ENABLE_PER_PACKET_LB

#ifdef ENABLE_IPV4
static __always_inline int __per_packet_lb_svc_xlate_4(void *ctx, struct iphdr *ip4)
static __always_inline int __per_packet_lb_svc_xlate_4(void *ctx, struct iphdr *ip4,
__s8 *ext_err)
{
struct ipv4_ct_tuple tuple = {};
struct ct_state ct_state_new = {};
Expand Down Expand Up @@ -109,7 +110,7 @@ static __always_inline int __per_packet_lb_svc_xlate_4(void *ctx, struct iphdr *
#endif /* ENABLE_L7_LB */
ret = lb4_local(get_ct_map4(&tuple), ctx, ETH_HLEN, l4_off,
&key, &tuple, svc, &ct_state_new,
has_l4_header, false, &cluster_id);
has_l4_header, false, &cluster_id, ext_err);
if (IS_ERR(ret))
return ret;
}
Expand All @@ -122,7 +123,8 @@ static __always_inline int __per_packet_lb_svc_xlate_4(void *ctx, struct iphdr *
#endif /* ENABLE_IPV4 */

#ifdef ENABLE_IPV6
static __always_inline int __per_packet_lb_svc_xlate_6(void *ctx, struct ipv6hdr *ip6)
static __always_inline int __per_packet_lb_svc_xlate_6(void *ctx, struct ipv6hdr *ip6,
__s8 *ext_err)
{
struct ipv6_ct_tuple tuple = {};
struct ct_state ct_state_new = {};
Expand Down Expand Up @@ -158,7 +160,7 @@ static __always_inline int __per_packet_lb_svc_xlate_6(void *ctx, struct ipv6hdr
}
#endif /* ENABLE_L7_LB */
ret = lb6_local(get_ct_map6(&tuple), ctx, ETH_HLEN, l4_off,
&key, &tuple, svc, &ct_state_new, false);
&key, &tuple, svc, &ct_state_new, false, ext_err);
if (IS_ERR(ret))
return ret;
}
Expand Down Expand Up @@ -464,7 +466,7 @@ static __always_inline int handle_ipv6_from_lxc(struct __ctx_buff *ctx, __u32 *d
ct_state_new.src_sec_id = SECLABEL;
ret = ct_create6(get_ct_map6(tuple), &CT_MAP_ANY6, tuple, ctx,
CT_EGRESS, &ct_state_new, proxy_port > 0, from_l7lb,
NULL);
ext_err);
if (IS_ERR(ret))
return ret;
trace.monitor = TRACE_PAYLOAD_LEN;
Expand Down Expand Up @@ -704,7 +706,8 @@ TAIL_CT_LOOKUP6(CILIUM_CALL_IPV6_CT_EGRESS, tail_ipv6_ct_egress, CT_EGRESS,
is_defined(ENABLE_PER_PACKET_LB),
CILIUM_CALL_IPV6_FROM_LXC_CONT, tail_handle_ipv6_cont)

static __always_inline int __tail_handle_ipv6(struct __ctx_buff *ctx)
static __always_inline int __tail_handle_ipv6(struct __ctx_buff *ctx,
__s8 *ext_err __maybe_unused)
{
void *data, *data_end;
struct ipv6hdr *ip6;
Expand All @@ -731,7 +734,7 @@ static __always_inline int __tail_handle_ipv6(struct __ctx_buff *ctx)

#ifdef ENABLE_PER_PACKET_LB
/* will tailcall internally or return error */
return __per_packet_lb_svc_xlate_6(ctx, ip6);
return __per_packet_lb_svc_xlate_6(ctx, ip6, ext_err);
#else
/* won't be a tailcall, see TAIL_CT_LOOKUP6 */
return tail_ipv6_ct_egress(ctx);
Expand All @@ -741,11 +744,12 @@ static __always_inline int __tail_handle_ipv6(struct __ctx_buff *ctx)
__section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_IPV6_FROM_LXC)
int tail_handle_ipv6(struct __ctx_buff *ctx)
{
int ret = __tail_handle_ipv6(ctx);
__s8 ext_err = 0;
int ret = __tail_handle_ipv6(ctx, &ext_err);

if (IS_ERR(ret))
return send_drop_notify_error(ctx, SECLABEL, ret,
CTX_ACT_DROP, METRIC_EGRESS);
return send_drop_notify_error_ext(ctx, SECLABEL, ret, ext_err,
CTX_ACT_DROP, METRIC_EGRESS);
return ret;
}
#endif /* ENABLE_IPV6 */
Expand Down Expand Up @@ -920,7 +924,7 @@ static __always_inline int handle_ipv4_from_lxc(struct __ctx_buff *ctx, __u32 *d
*/
ret = ct_create4(ct_map, ct_related_map, tuple, ctx,
CT_EGRESS, &ct_state_new, proxy_port > 0, from_l7lb,
NULL);
ext_err);
if (IS_ERR(ret))
return ret;
break;
Expand Down Expand Up @@ -1246,7 +1250,8 @@ TAIL_CT_LOOKUP4(CILIUM_CALL_IPV4_CT_EGRESS, tail_ipv4_ct_egress, CT_EGRESS,
is_defined(ENABLE_PER_PACKET_LB),
CILIUM_CALL_IPV4_FROM_LXC_CONT, tail_handle_ipv4_cont)

static __always_inline int __tail_handle_ipv4(struct __ctx_buff *ctx)
static __always_inline int __tail_handle_ipv4(struct __ctx_buff *ctx,
__s8 *ext_err __maybe_unused)
{
void *data, *data_end;
struct iphdr *ip4;
Expand All @@ -1268,7 +1273,7 @@ static __always_inline int __tail_handle_ipv4(struct __ctx_buff *ctx)

#ifdef ENABLE_PER_PACKET_LB
/* will tailcall internally or return error */
return __per_packet_lb_svc_xlate_4(ctx, ip4);
return __per_packet_lb_svc_xlate_4(ctx, ip4, ext_err);
#else
/* won't be a tailcall, see TAIL_CT_LOOKUP4 */
return tail_ipv4_ct_egress(ctx);
Expand All @@ -1278,11 +1283,12 @@ static __always_inline int __tail_handle_ipv4(struct __ctx_buff *ctx)
__section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_IPV4_FROM_LXC)
int tail_handle_ipv4(struct __ctx_buff *ctx)
{
int ret = __tail_handle_ipv4(ctx);
__s8 ext_err = 0;
int ret = __tail_handle_ipv4(ctx, &ext_err);

if (IS_ERR(ret))
return send_drop_notify_error(ctx, SECLABEL, ret,
CTX_ACT_DROP, METRIC_EGRESS);
return send_drop_notify_error_ext(ctx, SECLABEL, ret, ext_err,
CTX_ACT_DROP, METRIC_EGRESS);
return ret;
}

Expand Down Expand Up @@ -1507,8 +1513,14 @@ ipv6_policy(struct __ctx_buff *ctx, int ifindex, __u32 src_label,

if (ret == CT_NEW) {
ct_state_new.src_sec_id = src_label;
/* ext_err may contain a value from __policy_can_access, and
* ct_create6 overwrites it only if it returns an error itself.
* As the error from __policy_can_access is dropped in that
* case, it's OK to return ext_err from ct_create6 along with
* its error code.
*/
ret = ct_create6(get_ct_map6(tuple), &CT_MAP_ANY6, tuple, ctx, CT_INGRESS,
&ct_state_new, *proxy_port > 0, false, NULL);
&ct_state_new, *proxy_port > 0, false, ext_err);
if (IS_ERR(ret))
return ret;

Expand Down Expand Up @@ -1828,8 +1840,14 @@ ipv4_policy(struct __ctx_buff *ctx, int ifindex, __u32 src_label, enum ct_status
if (ret == CT_NEW) {
ct_state_new.src_sec_id = src_label;
ct_state_new.from_tunnel = from_tunnel;
/* ext_err may contain a value from __policy_can_access, and
* ct_create4 overwrites it only if it returns an error itself.
* As the error from __policy_can_access is dropped in that
* case, it's OK to return ext_err from ct_create4 along with
* its error code.
*/
ret = ct_create4(get_ct_map4(tuple), &CT_MAP_ANY4, tuple, ctx, CT_INGRESS,
&ct_state_new, *proxy_port > 0, false, NULL);
&ct_state_new, *proxy_port > 0, false, ext_err);
if (IS_ERR(ret))
return ret;

Expand Down
38 changes: 23 additions & 15 deletions bpf/bpf_overlay.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@

#ifdef ENABLE_IPV6
static __always_inline int handle_ipv6(struct __ctx_buff *ctx,
__u32 *identity)
__u32 *identity,
__s8 *ext_err __maybe_unused)
{
int ret, l3_off = ETH_HLEN, hdrlen;
struct remote_endpoint_info *info;
Expand All @@ -60,7 +61,7 @@ static __always_inline int handle_ipv6(struct __ctx_buff *ctx,
return DROP_INVALID;
#ifdef ENABLE_NODEPORT
if (!ctx_skip_nodeport(ctx)) {
ret = nodeport_lb6(ctx, *identity);
ret = nodeport_lb6(ctx, *identity, ext_err);
if (ret < 0)
return ret;
}
Expand Down Expand Up @@ -179,11 +180,12 @@ __section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_IPV6_FROM_OVERLAY)
int tail_handle_ipv6(struct __ctx_buff *ctx)
{
__u32 src_identity = 0;
int ret = handle_ipv6(ctx, &src_identity);
__s8 ext_err = 0;
int ret = handle_ipv6(ctx, &src_identity, &ext_err);

if (IS_ERR(ret))
return send_drop_notify_error(ctx, src_identity, ret,
CTX_ACT_DROP, METRIC_INGRESS);
return send_drop_notify_error_ext(ctx, src_identity, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);
return ret;
}
#endif /* ENABLE_IPV6 */
Expand Down Expand Up @@ -211,7 +213,9 @@ static __always_inline int ipv4_host_delivery(struct __ctx_buff *ctx, struct iph
}

#if defined(ENABLE_CLUSTER_AWARE_ADDRESSING) && defined(ENABLE_INTER_CLUSTER_SNAT)
static __always_inline int handle_inter_cluster_revsnat(struct __ctx_buff *ctx, __u32 *src_identity)
static __always_inline int handle_inter_cluster_revsnat(struct __ctx_buff *ctx,
__u32 *src_identity,
__s8 *ext_err)
{
int ret;
struct iphdr *ip4;
Expand All @@ -231,7 +235,7 @@ static __always_inline int handle_inter_cluster_revsnat(struct __ctx_buff *ctx,

*src_identity = identity;

ret = snat_v4_rev_nat(ctx, &target);
ret = snat_v4_rev_nat(ctx, &target, ext_err);
if (ret != NAT_PUNT_TO_STACK && ret != DROP_NAT_NO_MAPPING) {
if (IS_ERR(ret))
return ret;
Expand Down Expand Up @@ -272,16 +276,19 @@ int tail_handle_inter_cluster_revsnat(struct __ctx_buff *ctx)
{
int ret;
__u32 src_identity;
__s8 ext_err = 0;

ret = handle_inter_cluster_revsnat(ctx, &src_identity);
ret = handle_inter_cluster_revsnat(ctx, &src_identity, &ext_err);
if (IS_ERR(ret))
return send_drop_notify_error(ctx, src_identity, ret,
CTX_ACT_DROP, METRIC_INGRESS);
return send_drop_notify_error_ext(ctx, src_identity, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);
return ret;
}
#endif

static __always_inline int handle_ipv4(struct __ctx_buff *ctx, __u32 *identity)
static __always_inline int handle_ipv4(struct __ctx_buff *ctx,
__u32 *identity,
__s8 *ext_err __maybe_unused)
{
struct remote_endpoint_info *info;
void *data_end, *data;
Expand All @@ -305,7 +312,7 @@ static __always_inline int handle_ipv4(struct __ctx_buff *ctx, __u32 *identity)

#ifdef ENABLE_NODEPORT
if (!ctx_skip_nodeport(ctx)) {
int ret = nodeport_lb4(ctx, *identity);
int ret = nodeport_lb4(ctx, *identity, ext_err);

if (ret < 0)
return ret;
Expand Down Expand Up @@ -431,11 +438,12 @@ __section_tail(CILIUM_MAP_CALLS, CILIUM_CALL_IPV4_FROM_OVERLAY)
int tail_handle_ipv4(struct __ctx_buff *ctx)
{
__u32 src_identity = 0;
int ret = handle_ipv4(ctx, &src_identity);
__s8 ext_err = 0;
int ret = handle_ipv4(ctx, &src_identity, &ext_err);

if (IS_ERR(ret))
return send_drop_notify_error(ctx, src_identity, ret,
CTX_ACT_DROP, METRIC_INGRESS);
return send_drop_notify_error_ext(ctx, src_identity, ret, ext_err,
CTX_ACT_DROP, METRIC_INGRESS);
return ret;
}

Expand Down

0 comments on commit d749a59

Please sign in to comment.