hulk inclusion category: featrue bugzilla: https://atomgit.com/openeuler/kernel/issues/8480 -------------------------------- Add bpf_handle_ingress/egress_ptype kfunc to handle the ingress or egress ptype logic. Signed-off-by: Pu Lehui <pulehui@huawei.com> --- kernel/bpf/verifier.c | 12 ++++++++++-- net/core/filter.c | 42 ++++++++++++++++++++++++++++++++++++++++++ net/ipv4/ip_output.c | 31 +------------------------------ 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 4e0d6c2cb3ed..84d49d6ad825 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10816,6 +10816,8 @@ enum special_kfunc_type { KF_bpf_set_ingress_dev, KF_bpf_set_egress_dev, KF_bpf_get_skb_ethhdr, + KF_bpf_handle_ingress_ptype, + KF_bpf_handle_egress_ptype, #endif }; @@ -10842,6 +10844,8 @@ BTF_ID(func, bpf_set_ingress_dst) BTF_ID(func, bpf_set_ingress_dev) BTF_ID(func, bpf_set_egress_dev) BTF_ID(func, bpf_get_skb_ethhdr) +BTF_ID(func, bpf_handle_ingress_ptype) +BTF_ID(func, bpf_handle_egress_ptype) #endif BTF_SET_END(special_kfunc_set) @@ -10870,6 +10874,8 @@ BTF_ID(func, bpf_set_ingress_dst) BTF_ID(func, bpf_set_ingress_dev) BTF_ID(func, bpf_set_egress_dev) BTF_ID(func, bpf_get_skb_ethhdr) +BTF_ID(func, bpf_handle_ingress_ptype) +BTF_ID(func, bpf_handle_egress_ptype) #endif static bool is_kfunc_ret_null(struct bpf_kfunc_call_arg_meta *meta) @@ -11852,11 +11858,13 @@ static int check_atype_kfunc_compatibility(struct bpf_verifier_env *env, u32 fun #ifdef CONFIG_HISOCK if ((func_id == special_kfunc_list[KF_bpf_set_ingress_dst] || func_id == special_kfunc_list[KF_bpf_set_ingress_dev] || - func_id == special_kfunc_list[KF_bpf_get_skb_ethhdr]) && + func_id == special_kfunc_list[KF_bpf_get_skb_ethhdr] || + func_id == special_kfunc_list[KF_bpf_handle_ingress_ptype]) && env->prog->expected_attach_type != BPF_HISOCK_INGRESS) return -EACCES; - if (func_id == special_kfunc_list[KF_bpf_set_egress_dev] && + if ((func_id == special_kfunc_list[KF_bpf_set_egress_dev] || + func_id == special_kfunc_list[KF_bpf_handle_egress_ptype]) && env->prog->expected_attach_type != BPF_HISOCK_EGRESS) return -EACCES; #endif diff --git a/net/core/filter.c b/net/core/filter.c index 3530e5bde7bd..b2f72c492d26 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -12283,6 +12283,46 @@ bpf_set_egress_dev(struct __sk_buff *skb_ctx, unsigned long _dev) skb->dev = dev; return 0; } + +__bpf_kfunc void bpf_handle_ingress_ptype(struct __sk_buff *skb_ctx) +{ + struct sk_buff *skb = (struct sk_buff *)skb_ctx; + struct list_head *ptype_list = &ptype_all; + struct packet_type *ptype; + + rcu_read_lock(); +again: + list_for_each_entry_rcu(ptype, ptype_list, list) { + if (likely(!skb_orphan_frags_rx(skb, GFP_ATOMIC))) { + refcount_inc(&skb->users); + ptype->func(skb, skb->dev, ptype, skb->dev); + } + } + + if (ptype_list == &ptype_all) { + ptype_list = &skb->dev->ptype_all; + goto again; + } + + rcu_read_unlock(); +} + +__bpf_kfunc void bpf_handle_egress_ptype(struct __sk_buff *skb_ctx) +{ + struct sk_buff *skb = (struct sk_buff *)skb_ctx; + struct net_device *dev, *orig_dev = skb->dev; + + rcu_read_lock(); + dev = skb_dst_dev_rcu(skb); + skb->dev = dev; + skb->protocol = htons(ETH_P_IP); + + if (dev_nit_active(skb->dev)) + dev_queue_xmit_nit(skb, skb->dev); + + skb->dev = orig_dev; + rcu_read_unlock(); +} #endif __diag_pop(); @@ -12327,6 +12367,8 @@ BTF_ID_FLAGS(func, bpf_get_skb_ethhdr) BTF_ID_FLAGS(func, bpf_set_ingress_dev) BTF_ID_FLAGS(func, bpf_set_egress_dev) BTF_ID_FLAGS(func, bpf_skb_change_dev) +BTF_ID_FLAGS(func, bpf_handle_ingress_ptype) +BTF_ID_FLAGS(func, bpf_handle_egress_ptype) BTF_SET8_END(bpf_kfunc_check_set_hisock) #endif diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index a03449ba9740..83e283206d24 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -463,35 +463,6 @@ static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4) } #ifdef CONFIG_HISOCK -static int hisock_egress_redirect_xmit(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - struct netdev_queue *txq; - bool free_skb = true; - int cpu, rc; - - rcu_read_lock_bh(); - - txq = netdev_core_pick_tx(dev, skb, NULL); - cpu = smp_processor_id(); - HARD_TX_LOCK(dev, txq, cpu); - if (!netif_xmit_stopped(txq)) { - rc = netdev_start_xmit(skb, dev, txq, 0); - if (dev_xmit_complete(rc)) - free_skb = false; - } - HARD_TX_UNLOCK(dev, txq); - - rcu_read_unlock_bh(); - - if (free_skb) { - rc = -ENETDOWN; - kfree_skb(skb); - } - - return rc; -} - static int do_hisock_egress_redirect(struct net *net, struct sock *sk, struct sk_buff *skb) { struct iphdr *iph; @@ -501,7 +472,7 @@ static int do_hisock_egress_redirect(struct net *net, struct sock *sk, struct sk skb->dev = skb_dst(skb)->dev; if (skb_mac_header_was_set(skb)) - return hisock_egress_redirect_xmit(skb); + return dev_queue_xmit(skb); iph = ip_hdr(skb); iph_set_totlen(iph, skb->len); -- 2.34.1