|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
2 | 2 | /* Copyright (c) 2020 Mellanox Technologies. */ |
3 | 3 |
|
4 | | -#include <net/dst_metadata.h> |
5 | 4 | #include <linux/netdevice.h> |
6 | 5 | #include <linux/if_macvlan.h> |
7 | 6 | #include <linux/list.h> |
@@ -665,230 +664,54 @@ void mlx5e_rep_tc_netdevice_event_unregister(struct mlx5e_rep_priv *rpriv) |
665 | 664 | mlx5e_rep_indr_block_unbind); |
666 | 665 | } |
667 | 666 |
|
668 | | -static bool mlx5e_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb, |
669 | | - struct mlx5e_tc_update_priv *tc_priv, |
670 | | - u32 tunnel_id) |
671 | | -{ |
672 | | - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; |
673 | | - struct tunnel_match_enc_opts enc_opts = {}; |
674 | | - struct mlx5_rep_uplink_priv *uplink_priv; |
675 | | - struct mlx5e_rep_priv *uplink_rpriv; |
676 | | - struct metadata_dst *tun_dst; |
677 | | - struct tunnel_match_key key; |
678 | | - u32 tun_id, enc_opts_id; |
679 | | - struct net_device *dev; |
680 | | - int err; |
681 | | - |
682 | | - enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK; |
683 | | - tun_id = tunnel_id >> ENC_OPTS_BITS; |
684 | | - |
685 | | - if (!tun_id) |
686 | | - return true; |
687 | | - |
688 | | - uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); |
689 | | - uplink_priv = &uplink_rpriv->uplink_priv; |
690 | | - |
691 | | - err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key); |
692 | | - if (err) { |
693 | | - netdev_dbg(priv->netdev, |
694 | | - "Couldn't find tunnel for tun_id: %d, err: %d\n", |
695 | | - tun_id, err); |
696 | | - return false; |
697 | | - } |
698 | | - |
699 | | - if (enc_opts_id) { |
700 | | - err = mapping_find(uplink_priv->tunnel_enc_opts_mapping, |
701 | | - enc_opts_id, &enc_opts); |
702 | | - if (err) { |
703 | | - netdev_dbg(priv->netdev, |
704 | | - "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n", |
705 | | - enc_opts_id, err); |
706 | | - return false; |
707 | | - } |
708 | | - } |
709 | | - |
710 | | - if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { |
711 | | - tun_dst = __ip_tun_set_dst(key.enc_ipv4.src, key.enc_ipv4.dst, |
712 | | - key.enc_ip.tos, key.enc_ip.ttl, |
713 | | - key.enc_tp.dst, TUNNEL_KEY, |
714 | | - key32_to_tunnel_id(key.enc_key_id.keyid), |
715 | | - enc_opts.key.len); |
716 | | - } else if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { |
717 | | - tun_dst = __ipv6_tun_set_dst(&key.enc_ipv6.src, &key.enc_ipv6.dst, |
718 | | - key.enc_ip.tos, key.enc_ip.ttl, |
719 | | - key.enc_tp.dst, 0, TUNNEL_KEY, |
720 | | - key32_to_tunnel_id(key.enc_key_id.keyid), |
721 | | - enc_opts.key.len); |
722 | | - } else { |
723 | | - netdev_dbg(priv->netdev, |
724 | | - "Couldn't restore tunnel, unsupported addr_type: %d\n", |
725 | | - key.enc_control.addr_type); |
726 | | - return false; |
727 | | - } |
728 | | - |
729 | | - if (!tun_dst) { |
730 | | - netdev_dbg(priv->netdev, "Couldn't restore tunnel, no tun_dst\n"); |
731 | | - return false; |
732 | | - } |
733 | | - |
734 | | - tun_dst->u.tun_info.key.tp_src = key.enc_tp.src; |
735 | | - |
736 | | - if (enc_opts.key.len) |
737 | | - ip_tunnel_info_opts_set(&tun_dst->u.tun_info, |
738 | | - enc_opts.key.data, |
739 | | - enc_opts.key.len, |
740 | | - enc_opts.key.dst_opt_type); |
741 | | - |
742 | | - skb_dst_set(skb, (struct dst_entry *)tun_dst); |
743 | | - dev = dev_get_by_index(&init_net, key.filter_ifindex); |
744 | | - if (!dev) { |
745 | | - netdev_dbg(priv->netdev, |
746 | | - "Couldn't find tunnel device with ifindex: %d\n", |
747 | | - key.filter_ifindex); |
748 | | - return false; |
749 | | - } |
750 | | - |
751 | | - /* Set fwd_dev so we do dev_put() after datapath */ |
752 | | - tc_priv->fwd_dev = dev; |
753 | | - |
754 | | - skb->dev = dev; |
755 | | - |
756 | | - return true; |
757 | | -} |
758 | | - |
759 | | -static bool mlx5e_restore_skb_chain(struct sk_buff *skb, u32 chain, u32 reg_c1, |
760 | | - struct mlx5e_tc_update_priv *tc_priv) |
761 | | -{ |
762 | | - struct mlx5e_priv *priv = netdev_priv(skb->dev); |
763 | | - u32 tunnel_id = (reg_c1 >> ESW_TUN_OFFSET) & TUNNEL_ID_MASK; |
764 | | - |
765 | | - if (chain) { |
766 | | - struct mlx5_rep_uplink_priv *uplink_priv; |
767 | | - struct mlx5e_rep_priv *uplink_rpriv; |
768 | | - struct tc_skb_ext *tc_skb_ext; |
769 | | - struct mlx5_eswitch *esw; |
770 | | - u32 zone_restore_id; |
771 | | - |
772 | | - tc_skb_ext = tc_skb_ext_alloc(skb); |
773 | | - if (!tc_skb_ext) { |
774 | | - WARN_ON(1); |
775 | | - return false; |
776 | | - } |
777 | | - tc_skb_ext->chain = chain; |
778 | | - zone_restore_id = reg_c1 & ESW_ZONE_ID_MASK; |
779 | | - esw = priv->mdev->priv.eswitch; |
780 | | - uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); |
781 | | - uplink_priv = &uplink_rpriv->uplink_priv; |
782 | | - if (!mlx5e_tc_ct_restore_flow(uplink_priv->ct_priv, skb, |
783 | | - zone_restore_id)) |
784 | | - return false; |
785 | | - } |
786 | | - |
787 | | - return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id); |
788 | | -} |
789 | | - |
790 | | -static void mlx5_rep_tc_post_napi_receive(struct mlx5e_tc_update_priv *tc_priv) |
791 | | -{ |
792 | | - if (tc_priv->fwd_dev) |
793 | | - dev_put(tc_priv->fwd_dev); |
794 | | -} |
795 | | - |
796 | | -static void mlx5e_restore_skb_sample(struct mlx5e_priv *priv, struct sk_buff *skb, |
797 | | - struct mlx5_mapped_obj *mapped_obj, |
798 | | - struct mlx5e_tc_update_priv *tc_priv) |
799 | | -{ |
800 | | - if (!mlx5e_restore_tunnel(priv, skb, tc_priv, mapped_obj->sample.tunnel_id)) { |
801 | | - netdev_dbg(priv->netdev, |
802 | | - "Failed to restore tunnel info for sampled packet\n"); |
803 | | - return; |
804 | | - } |
805 | | - mlx5e_tc_sample_skb(skb, mapped_obj); |
806 | | - mlx5_rep_tc_post_napi_receive(tc_priv); |
807 | | -} |
808 | | - |
809 | | -static bool mlx5e_restore_skb_int_port(struct mlx5e_priv *priv, struct sk_buff *skb, |
810 | | - struct mlx5_mapped_obj *mapped_obj, |
811 | | - struct mlx5e_tc_update_priv *tc_priv, |
812 | | - bool *forward_tx, |
813 | | - u32 reg_c1) |
814 | | -{ |
815 | | - u32 tunnel_id = (reg_c1 >> ESW_TUN_OFFSET) & TUNNEL_ID_MASK; |
816 | | - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; |
817 | | - struct mlx5_rep_uplink_priv *uplink_priv; |
818 | | - struct mlx5e_rep_priv *uplink_rpriv; |
819 | | - |
820 | | - /* Tunnel restore takes precedence over int port restore */ |
821 | | - if (tunnel_id) |
822 | | - return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id); |
823 | | - |
824 | | - uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); |
825 | | - uplink_priv = &uplink_rpriv->uplink_priv; |
826 | | - |
827 | | - if (mlx5e_tc_int_port_dev_fwd(uplink_priv->int_port_priv, skb, |
828 | | - mapped_obj->int_port_metadata, forward_tx)) { |
829 | | - /* Set fwd_dev for future dev_put */ |
830 | | - tc_priv->fwd_dev = skb->dev; |
831 | | - |
832 | | - return true; |
833 | | - } |
834 | | - |
835 | | - return false; |
836 | | -} |
837 | | - |
838 | 667 | void mlx5e_rep_tc_receive(struct mlx5_cqe64 *cqe, struct mlx5e_rq *rq, |
839 | 668 | struct sk_buff *skb) |
840 | 669 | { |
841 | | - u32 reg_c1 = be32_to_cpu(cqe->ft_metadata); |
| 670 | + u32 reg_c0, reg_c1, zone_restore_id, tunnel_id; |
842 | 671 | struct mlx5e_tc_update_priv tc_priv = {}; |
843 | | - struct mlx5_mapped_obj mapped_obj; |
| 672 | + struct mlx5_rep_uplink_priv *uplink_priv; |
| 673 | + struct mlx5e_rep_priv *uplink_rpriv; |
| 674 | + struct mlx5_tc_ct_priv *ct_priv; |
| 675 | + struct mapping_ctx *mapping_ctx; |
844 | 676 | struct mlx5_eswitch *esw; |
845 | | - bool forward_tx = false; |
846 | 677 | struct mlx5e_priv *priv; |
847 | | - u32 reg_c0; |
848 | | - int err; |
849 | 678 |
|
850 | 679 | reg_c0 = (be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK); |
851 | 680 | if (!reg_c0 || reg_c0 == MLX5_FS_DEFAULT_FLOW_TAG) |
852 | 681 | goto forward; |
853 | 682 |
|
854 | | - /* If reg_c0 is not equal to the default flow tag then skb->mark |
| 683 | + /* If mapped_obj_id is not equal to the default flow tag then skb->mark |
855 | 684 | * is not supported and must be reset back to 0. |
856 | 685 | */ |
857 | 686 | skb->mark = 0; |
858 | 687 |
|
859 | 688 | priv = netdev_priv(skb->dev); |
860 | 689 | esw = priv->mdev->priv.eswitch; |
861 | | - err = mapping_find(esw->offloads.reg_c0_obj_pool, reg_c0, &mapped_obj); |
862 | | - if (err) { |
863 | | - netdev_dbg(priv->netdev, |
864 | | - "Couldn't find mapped object for reg_c0: %d, err: %d\n", |
865 | | - reg_c0, err); |
866 | | - goto free_skb; |
867 | | - } |
| 690 | + mapping_ctx = esw->offloads.reg_c0_obj_pool; |
| 691 | + reg_c1 = be32_to_cpu(cqe->ft_metadata); |
| 692 | + zone_restore_id = reg_c1 & ESW_ZONE_ID_MASK; |
| 693 | + tunnel_id = (reg_c1 >> ESW_TUN_OFFSET) & TUNNEL_ID_MASK; |
868 | 694 |
|
869 | | - if (mapped_obj.type == MLX5_MAPPED_OBJ_CHAIN) { |
870 | | - if (!mlx5e_restore_skb_chain(skb, mapped_obj.chain, reg_c1, &tc_priv) && |
871 | | - !mlx5_ipsec_is_rx_flow(cqe)) |
872 | | - goto free_skb; |
873 | | - } else if (mapped_obj.type == MLX5_MAPPED_OBJ_SAMPLE) { |
874 | | - mlx5e_restore_skb_sample(priv, skb, &mapped_obj, &tc_priv); |
875 | | - goto free_skb; |
876 | | - } else if (mapped_obj.type == MLX5_MAPPED_OBJ_INT_PORT_METADATA) { |
877 | | - if (!mlx5e_restore_skb_int_port(priv, skb, &mapped_obj, &tc_priv, |
878 | | - &forward_tx, reg_c1)) |
879 | | - goto free_skb; |
880 | | - } else { |
881 | | - netdev_dbg(priv->netdev, "Invalid mapped object type: %d\n", mapped_obj.type); |
| 695 | + uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH); |
| 696 | + uplink_priv = &uplink_rpriv->uplink_priv; |
| 697 | + ct_priv = uplink_priv->ct_priv; |
| 698 | + |
| 699 | + if (!mlx5_ipsec_is_rx_flow(cqe) && |
| 700 | + !mlx5e_tc_update_skb(cqe, skb, mapping_ctx, reg_c0, ct_priv, zone_restore_id, tunnel_id, |
| 701 | + &tc_priv)) |
882 | 702 | goto free_skb; |
883 | | - } |
884 | 703 |
|
885 | 704 | forward: |
886 | | - if (forward_tx) |
| 705 | + if (tc_priv.skb_done) |
| 706 | + goto free_skb; |
| 707 | + |
| 708 | + if (tc_priv.forward_tx) |
887 | 709 | dev_queue_xmit(skb); |
888 | 710 | else |
889 | 711 | napi_gro_receive(rq->cq.napi, skb); |
890 | 712 |
|
891 | | - mlx5_rep_tc_post_napi_receive(&tc_priv); |
| 713 | + if (tc_priv.fwd_dev) |
| 714 | + dev_put(tc_priv.fwd_dev); |
892 | 715 |
|
893 | 716 | return; |
894 | 717 |
|
|
0 commit comments