|
@@ -64,6 +64,10 @@
|
|
|
#include <net/ip_fib.h>
|
|
|
#include <net/flow.h>
|
|
|
#include <net/arp.h>
|
|
|
+#include <net/ipv6.h>
|
|
|
+#include <linux/seg6_local.h>
|
|
|
+#include <net/seg6.h>
|
|
|
+#include <net/seg6_local.h>
|
|
|
|
|
|
/**
|
|
|
* sk_filter_trim_cap - run a packet through a socket filter
|
|
@@ -3363,28 +3367,6 @@ static const struct bpf_func_proto bpf_xdp_redirect_map_proto = {
|
|
|
.arg3_type = ARG_ANYTHING,
|
|
|
};
|
|
|
|
|
|
-bool bpf_helper_changes_pkt_data(void *func)
|
|
|
-{
|
|
|
- if (func == bpf_skb_vlan_push ||
|
|
|
- func == bpf_skb_vlan_pop ||
|
|
|
- func == bpf_skb_store_bytes ||
|
|
|
- func == bpf_skb_change_proto ||
|
|
|
- func == bpf_skb_change_head ||
|
|
|
- func == bpf_skb_change_tail ||
|
|
|
- func == bpf_skb_adjust_room ||
|
|
|
- func == bpf_skb_pull_data ||
|
|
|
- func == bpf_clone_redirect ||
|
|
|
- func == bpf_l3_csum_replace ||
|
|
|
- func == bpf_l4_csum_replace ||
|
|
|
- func == bpf_xdp_adjust_head ||
|
|
|
- func == bpf_xdp_adjust_meta ||
|
|
|
- func == bpf_msg_pull_data ||
|
|
|
- func == bpf_xdp_adjust_tail)
|
|
|
- return true;
|
|
|
-
|
|
|
- return false;
|
|
|
-}
|
|
|
-
|
|
|
static unsigned long bpf_skb_copy(void *dst_buff, const void *skb,
|
|
|
unsigned long off, unsigned long len)
|
|
|
{
|
|
@@ -4360,6 +4342,264 @@ static const struct bpf_func_proto bpf_skb_fib_lookup_proto = {
|
|
|
.arg4_type = ARG_ANYTHING,
|
|
|
};
|
|
|
|
|
|
+#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
|
|
|
+static int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len)
|
|
|
+{
|
|
|
+ int err;
|
|
|
+ struct ipv6_sr_hdr *srh = (struct ipv6_sr_hdr *)hdr;
|
|
|
+
|
|
|
+ if (!seg6_validate_srh(srh, len))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ switch (type) {
|
|
|
+ case BPF_LWT_ENCAP_SEG6_INLINE:
|
|
|
+ if (skb->protocol != htons(ETH_P_IPV6))
|
|
|
+ return -EBADMSG;
|
|
|
+
|
|
|
+ err = seg6_do_srh_inline(skb, srh);
|
|
|
+ break;
|
|
|
+ case BPF_LWT_ENCAP_SEG6:
|
|
|
+ skb_reset_inner_headers(skb);
|
|
|
+ skb->encapsulation = 1;
|
|
|
+ err = seg6_do_srh_encap(skb, srh, IPPROTO_IPV6);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ bpf_compute_data_pointers(skb);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
|
|
|
+ skb_set_transport_header(skb, sizeof(struct ipv6hdr));
|
|
|
+
|
|
|
+ return seg6_lookup_nexthop(skb, NULL, 0);
|
|
|
+}
|
|
|
+#endif /* CONFIG_IPV6_SEG6_BPF */
|
|
|
+
|
|
|
+BPF_CALL_4(bpf_lwt_push_encap, struct sk_buff *, skb, u32, type, void *, hdr,
|
|
|
+ u32, len)
|
|
|
+{
|
|
|
+ switch (type) {
|
|
|
+#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
|
|
|
+ case BPF_LWT_ENCAP_SEG6:
|
|
|
+ case BPF_LWT_ENCAP_SEG6_INLINE:
|
|
|
+ return bpf_push_seg6_encap(skb, type, hdr, len);
|
|
|
+#endif
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto bpf_lwt_push_encap_proto = {
|
|
|
+ .func = bpf_lwt_push_encap,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+ .arg3_type = ARG_PTR_TO_MEM,
|
|
|
+ .arg4_type = ARG_CONST_SIZE
|
|
|
+};
|
|
|
+
|
|
|
+BPF_CALL_4(bpf_lwt_seg6_store_bytes, struct sk_buff *, skb, u32, offset,
|
|
|
+ const void *, from, u32, len)
|
|
|
+{
|
|
|
+#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
|
|
|
+ struct seg6_bpf_srh_state *srh_state =
|
|
|
+ this_cpu_ptr(&seg6_bpf_srh_states);
|
|
|
+ void *srh_tlvs, *srh_end, *ptr;
|
|
|
+ struct ipv6_sr_hdr *srh;
|
|
|
+ int srhoff = 0;
|
|
|
+
|
|
|
+ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
|
|
|
+ srh_tlvs = (void *)((char *)srh + ((srh->first_segment + 1) << 4));
|
|
|
+ srh_end = (void *)((char *)srh + sizeof(*srh) + srh_state->hdrlen);
|
|
|
+
|
|
|
+ ptr = skb->data + offset;
|
|
|
+ if (ptr >= srh_tlvs && ptr + len <= srh_end)
|
|
|
+ srh_state->valid = 0;
|
|
|
+ else if (ptr < (void *)&srh->flags ||
|
|
|
+ ptr + len > (void *)&srh->segments)
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ if (unlikely(bpf_try_make_writable(skb, offset + len)))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ memcpy(skb->data + offset, from, len);
|
|
|
+ return 0;
|
|
|
+#else /* CONFIG_IPV6_SEG6_BPF */
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto bpf_lwt_seg6_store_bytes_proto = {
|
|
|
+ .func = bpf_lwt_seg6_store_bytes,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+ .arg3_type = ARG_PTR_TO_MEM,
|
|
|
+ .arg4_type = ARG_CONST_SIZE
|
|
|
+};
|
|
|
+
|
|
|
+BPF_CALL_4(bpf_lwt_seg6_action, struct sk_buff *, skb,
|
|
|
+ u32, action, void *, param, u32, param_len)
|
|
|
+{
|
|
|
+#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
|
|
|
+ struct seg6_bpf_srh_state *srh_state =
|
|
|
+ this_cpu_ptr(&seg6_bpf_srh_states);
|
|
|
+ struct ipv6_sr_hdr *srh;
|
|
|
+ int srhoff = 0;
|
|
|
+ int err;
|
|
|
+
|
|
|
+ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
|
|
|
+ return -EINVAL;
|
|
|
+ srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
|
|
|
+
|
|
|
+ if (!srh_state->valid) {
|
|
|
+ if (unlikely((srh_state->hdrlen & 7) != 0))
|
|
|
+ return -EBADMSG;
|
|
|
+
|
|
|
+ srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
|
|
|
+ if (unlikely(!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3)))
|
|
|
+ return -EBADMSG;
|
|
|
+
|
|
|
+ srh_state->valid = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ switch (action) {
|
|
|
+ case SEG6_LOCAL_ACTION_END_X:
|
|
|
+ if (param_len != sizeof(struct in6_addr))
|
|
|
+ return -EINVAL;
|
|
|
+ return seg6_lookup_nexthop(skb, (struct in6_addr *)param, 0);
|
|
|
+ case SEG6_LOCAL_ACTION_END_T:
|
|
|
+ if (param_len != sizeof(int))
|
|
|
+ return -EINVAL;
|
|
|
+ return seg6_lookup_nexthop(skb, NULL, *(int *)param);
|
|
|
+ case SEG6_LOCAL_ACTION_END_B6:
|
|
|
+ err = bpf_push_seg6_encap(skb, BPF_LWT_ENCAP_SEG6_INLINE,
|
|
|
+ param, param_len);
|
|
|
+ if (!err)
|
|
|
+ srh_state->hdrlen =
|
|
|
+ ((struct ipv6_sr_hdr *)param)->hdrlen << 3;
|
|
|
+ return err;
|
|
|
+ case SEG6_LOCAL_ACTION_END_B6_ENCAP:
|
|
|
+ err = bpf_push_seg6_encap(skb, BPF_LWT_ENCAP_SEG6,
|
|
|
+ param, param_len);
|
|
|
+ if (!err)
|
|
|
+ srh_state->hdrlen =
|
|
|
+ ((struct ipv6_sr_hdr *)param)->hdrlen << 3;
|
|
|
+ return err;
|
|
|
+ default:
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+#else /* CONFIG_IPV6_SEG6_BPF */
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto bpf_lwt_seg6_action_proto = {
|
|
|
+ .func = bpf_lwt_seg6_action,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+ .arg3_type = ARG_PTR_TO_MEM,
|
|
|
+ .arg4_type = ARG_CONST_SIZE
|
|
|
+};
|
|
|
+
|
|
|
+BPF_CALL_3(bpf_lwt_seg6_adjust_srh, struct sk_buff *, skb, u32, offset,
|
|
|
+ s32, len)
|
|
|
+{
|
|
|
+#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
|
|
|
+ struct seg6_bpf_srh_state *srh_state =
|
|
|
+ this_cpu_ptr(&seg6_bpf_srh_states);
|
|
|
+ void *srh_end, *srh_tlvs, *ptr;
|
|
|
+ struct ipv6_sr_hdr *srh;
|
|
|
+ struct ipv6hdr *hdr;
|
|
|
+ int srhoff = 0;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
|
|
|
+ return -EINVAL;
|
|
|
+ srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
|
|
|
+
|
|
|
+ srh_tlvs = (void *)((unsigned char *)srh + sizeof(*srh) +
|
|
|
+ ((srh->first_segment + 1) << 4));
|
|
|
+ srh_end = (void *)((unsigned char *)srh + sizeof(*srh) +
|
|
|
+ srh_state->hdrlen);
|
|
|
+ ptr = skb->data + offset;
|
|
|
+
|
|
|
+ if (unlikely(ptr < srh_tlvs || ptr > srh_end))
|
|
|
+ return -EFAULT;
|
|
|
+ if (unlikely(len < 0 && (void *)((char *)ptr - len) > srh_end))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ if (len > 0) {
|
|
|
+ ret = skb_cow_head(skb, len);
|
|
|
+ if (unlikely(ret < 0))
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ ret = bpf_skb_net_hdr_push(skb, offset, len);
|
|
|
+ } else {
|
|
|
+ ret = bpf_skb_net_hdr_pop(skb, offset, -1 * len);
|
|
|
+ }
|
|
|
+
|
|
|
+ bpf_compute_data_pointers(skb);
|
|
|
+ if (unlikely(ret < 0))
|
|
|
+ return ret;
|
|
|
+
|
|
|
+ hdr = (struct ipv6hdr *)skb->data;
|
|
|
+ hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
|
|
|
+
|
|
|
+ srh_state->hdrlen += len;
|
|
|
+ srh_state->valid = 0;
|
|
|
+ return 0;
|
|
|
+#else /* CONFIG_IPV6_SEG6_BPF */
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto bpf_lwt_seg6_adjust_srh_proto = {
|
|
|
+ .func = bpf_lwt_seg6_adjust_srh,
|
|
|
+ .gpl_only = false,
|
|
|
+ .ret_type = RET_INTEGER,
|
|
|
+ .arg1_type = ARG_PTR_TO_CTX,
|
|
|
+ .arg2_type = ARG_ANYTHING,
|
|
|
+ .arg3_type = ARG_ANYTHING,
|
|
|
+};
|
|
|
+
|
|
|
+bool bpf_helper_changes_pkt_data(void *func)
|
|
|
+{
|
|
|
+ if (func == bpf_skb_vlan_push ||
|
|
|
+ func == bpf_skb_vlan_pop ||
|
|
|
+ func == bpf_skb_store_bytes ||
|
|
|
+ func == bpf_skb_change_proto ||
|
|
|
+ func == bpf_skb_change_head ||
|
|
|
+ func == bpf_skb_change_tail ||
|
|
|
+ func == bpf_skb_adjust_room ||
|
|
|
+ func == bpf_skb_pull_data ||
|
|
|
+ func == bpf_clone_redirect ||
|
|
|
+ func == bpf_l3_csum_replace ||
|
|
|
+ func == bpf_l4_csum_replace ||
|
|
|
+ func == bpf_xdp_adjust_head ||
|
|
|
+ func == bpf_xdp_adjust_meta ||
|
|
|
+ func == bpf_msg_pull_data ||
|
|
|
+ func == bpf_xdp_adjust_tail ||
|
|
|
+ func == bpf_lwt_push_encap ||
|
|
|
+ func == bpf_lwt_seg6_store_bytes ||
|
|
|
+ func == bpf_lwt_seg6_adjust_srh ||
|
|
|
+ func == bpf_lwt_seg6_action
|
|
|
+ )
|
|
|
+ return true;
|
|
|
+
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
static const struct bpf_func_proto *
|
|
|
bpf_base_func_proto(enum bpf_func_id func_id)
|
|
|
{
|
|
@@ -4543,33 +4783,6 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static const struct bpf_func_proto *
|
|
|
-lwt_inout_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
-{
|
|
|
- switch (func_id) {
|
|
|
- case BPF_FUNC_skb_load_bytes:
|
|
|
- return &bpf_skb_load_bytes_proto;
|
|
|
- case BPF_FUNC_skb_pull_data:
|
|
|
- return &bpf_skb_pull_data_proto;
|
|
|
- case BPF_FUNC_csum_diff:
|
|
|
- return &bpf_csum_diff_proto;
|
|
|
- case BPF_FUNC_get_cgroup_classid:
|
|
|
- return &bpf_get_cgroup_classid_proto;
|
|
|
- case BPF_FUNC_get_route_realm:
|
|
|
- return &bpf_get_route_realm_proto;
|
|
|
- case BPF_FUNC_get_hash_recalc:
|
|
|
- return &bpf_get_hash_recalc_proto;
|
|
|
- case BPF_FUNC_perf_event_output:
|
|
|
- return &bpf_skb_event_output_proto;
|
|
|
- case BPF_FUNC_get_smp_processor_id:
|
|
|
- return &bpf_get_smp_processor_id_proto;
|
|
|
- case BPF_FUNC_skb_under_cgroup:
|
|
|
- return &bpf_skb_under_cgroup_proto;
|
|
|
- default:
|
|
|
- return bpf_base_func_proto(func_id);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
static const struct bpf_func_proto *
|
|
|
sock_ops_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
{
|
|
@@ -4635,6 +4848,44 @@ sk_skb_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static const struct bpf_func_proto *
|
|
|
+lwt_out_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
+{
|
|
|
+ switch (func_id) {
|
|
|
+ case BPF_FUNC_skb_load_bytes:
|
|
|
+ return &bpf_skb_load_bytes_proto;
|
|
|
+ case BPF_FUNC_skb_pull_data:
|
|
|
+ return &bpf_skb_pull_data_proto;
|
|
|
+ case BPF_FUNC_csum_diff:
|
|
|
+ return &bpf_csum_diff_proto;
|
|
|
+ case BPF_FUNC_get_cgroup_classid:
|
|
|
+ return &bpf_get_cgroup_classid_proto;
|
|
|
+ case BPF_FUNC_get_route_realm:
|
|
|
+ return &bpf_get_route_realm_proto;
|
|
|
+ case BPF_FUNC_get_hash_recalc:
|
|
|
+ return &bpf_get_hash_recalc_proto;
|
|
|
+ case BPF_FUNC_perf_event_output:
|
|
|
+ return &bpf_skb_event_output_proto;
|
|
|
+ case BPF_FUNC_get_smp_processor_id:
|
|
|
+ return &bpf_get_smp_processor_id_proto;
|
|
|
+ case BPF_FUNC_skb_under_cgroup:
|
|
|
+ return &bpf_skb_under_cgroup_proto;
|
|
|
+ default:
|
|
|
+ return bpf_base_func_proto(func_id);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto *
|
|
|
+lwt_in_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
+{
|
|
|
+ switch (func_id) {
|
|
|
+ case BPF_FUNC_lwt_push_encap:
|
|
|
+ return &bpf_lwt_push_encap_proto;
|
|
|
+ default:
|
|
|
+ return lwt_out_func_proto(func_id, prog);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static const struct bpf_func_proto *
|
|
|
lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
{
|
|
@@ -4666,7 +4917,22 @@ lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
case BPF_FUNC_set_hash_invalid:
|
|
|
return &bpf_set_hash_invalid_proto;
|
|
|
default:
|
|
|
- return lwt_inout_func_proto(func_id, prog);
|
|
|
+ return lwt_out_func_proto(func_id, prog);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static const struct bpf_func_proto *
|
|
|
+lwt_seg6local_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
|
|
|
+{
|
|
|
+ switch (func_id) {
|
|
|
+ case BPF_FUNC_lwt_seg6_store_bytes:
|
|
|
+ return &bpf_lwt_seg6_store_bytes_proto;
|
|
|
+ case BPF_FUNC_lwt_seg6_action:
|
|
|
+ return &bpf_lwt_seg6_action_proto;
|
|
|
+ case BPF_FUNC_lwt_seg6_adjust_srh:
|
|
|
+ return &bpf_lwt_seg6_adjust_srh_proto;
|
|
|
+ default:
|
|
|
+ return lwt_out_func_proto(func_id, prog);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4774,7 +5040,6 @@ static bool lwt_is_valid_access(int off, int size,
|
|
|
return bpf_skb_is_valid_access(off, size, type, prog, info);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/* Attach type specific accesses */
|
|
|
static bool __sock_filter_check_attach_type(int off,
|
|
|
enum bpf_access_type access_type,
|
|
@@ -6348,13 +6613,23 @@ const struct bpf_prog_ops cg_skb_prog_ops = {
|
|
|
.test_run = bpf_prog_test_run_skb,
|
|
|
};
|
|
|
|
|
|
-const struct bpf_verifier_ops lwt_inout_verifier_ops = {
|
|
|
- .get_func_proto = lwt_inout_func_proto,
|
|
|
+const struct bpf_verifier_ops lwt_in_verifier_ops = {
|
|
|
+ .get_func_proto = lwt_in_func_proto,
|
|
|
.is_valid_access = lwt_is_valid_access,
|
|
|
.convert_ctx_access = bpf_convert_ctx_access,
|
|
|
};
|
|
|
|
|
|
-const struct bpf_prog_ops lwt_inout_prog_ops = {
|
|
|
+const struct bpf_prog_ops lwt_in_prog_ops = {
|
|
|
+ .test_run = bpf_prog_test_run_skb,
|
|
|
+};
|
|
|
+
|
|
|
+const struct bpf_verifier_ops lwt_out_verifier_ops = {
|
|
|
+ .get_func_proto = lwt_out_func_proto,
|
|
|
+ .is_valid_access = lwt_is_valid_access,
|
|
|
+ .convert_ctx_access = bpf_convert_ctx_access,
|
|
|
+};
|
|
|
+
|
|
|
+const struct bpf_prog_ops lwt_out_prog_ops = {
|
|
|
.test_run = bpf_prog_test_run_skb,
|
|
|
};
|
|
|
|
|
@@ -6369,6 +6644,16 @@ const struct bpf_prog_ops lwt_xmit_prog_ops = {
|
|
|
.test_run = bpf_prog_test_run_skb,
|
|
|
};
|
|
|
|
|
|
+const struct bpf_verifier_ops lwt_seg6local_verifier_ops = {
|
|
|
+ .get_func_proto = lwt_seg6local_func_proto,
|
|
|
+ .is_valid_access = lwt_is_valid_access,
|
|
|
+ .convert_ctx_access = bpf_convert_ctx_access,
|
|
|
+};
|
|
|
+
|
|
|
+const struct bpf_prog_ops lwt_seg6local_prog_ops = {
|
|
|
+ .test_run = bpf_prog_test_run_skb,
|
|
|
+};
|
|
|
+
|
|
|
const struct bpf_verifier_ops cg_sock_verifier_ops = {
|
|
|
.get_func_proto = sock_filter_func_proto,
|
|
|
.is_valid_access = sock_filter_is_valid_access,
|