167ab160eSEdward Cree /* SPDX-License-Identifier: GPL-2.0-only */ 267ab160eSEdward Cree /**************************************************************************** 367ab160eSEdward Cree * Driver for Solarflare network controllers and boards 467ab160eSEdward Cree * Copyright 2019 Solarflare Communications Inc. 567ab160eSEdward Cree * Copyright 2020-2022 Xilinx Inc. 667ab160eSEdward Cree * 767ab160eSEdward Cree * This program is free software; you can redistribute it and/or modify it 867ab160eSEdward Cree * under the terms of the GNU General Public License version 2 as published 967ab160eSEdward Cree * by the Free Software Foundation, incorporated herein by reference. 1067ab160eSEdward Cree */ 1167ab160eSEdward Cree 1267ab160eSEdward Cree #ifndef EFX_TC_H 1367ab160eSEdward Cree #define EFX_TC_H 149dc0cad2SEdward Cree #include <net/flow_offload.h> 15f54a28a2SEdward Cree #include <linux/rhashtable.h> 1667ab160eSEdward Cree #include "net_driver.h" 1725730d8bSEdward Cree #include "tc_counters.h" 1867ab160eSEdward Cree 19c178dff3SEdward Cree #define IS_ALL_ONES(v) (!(typeof (v))~(v)) 20c178dff3SEdward Cree 21746224cdSEdward Cree static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) 22746224cdSEdward Cree { 23746224cdSEdward Cree return !memchr_inv(addr, 0xff, sizeof(*addr)); 24746224cdSEdward Cree } 25746224cdSEdward Cree 26b4da4235SEdward Cree struct efx_tc_encap_action; /* see tc_encap_actions.h */ 27b4da4235SEdward Cree 2867ab160eSEdward Cree struct efx_tc_action_set { 2905ccd8d8SEdward Cree u16 vlan_push:2; 3005ccd8d8SEdward Cree u16 vlan_pop:2; 3117654d84SEdward Cree u16 decap:1; 3267ab160eSEdward Cree u16 deliver:1; 3305ccd8d8SEdward Cree __be16 vlan_tci[2]; /* TCIs for vlan_push */ 3405ccd8d8SEdward Cree __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ 352e0f1eb0SEdward Cree struct efx_tc_counter_index *count; 36b4da4235SEdward Cree struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ 377e5e7d80SEdward Cree struct list_head encap_user; /* entry on encap_md->users list */ 387e5e7d80SEdward Cree struct efx_tc_action_set_list *user; /* Only populated if encap_md */ 399a14f2e3SEdward Cree struct list_head count_user; /* entry on counter->users list, if encap */ 4067ab160eSEdward Cree u32 dest_mport; 4167ab160eSEdward Cree u32 fw_id; /* index of this entry in firmware actions table */ 4267ab160eSEdward Cree struct list_head list; 4367ab160eSEdward Cree }; 4467ab160eSEdward Cree 4567ab160eSEdward Cree struct efx_tc_match_fields { 4667ab160eSEdward Cree /* L1 */ 4767ab160eSEdward Cree u32 ingress_port; 48d902e1a7SEdward Cree u8 recirc_id; 496d1c604dSEdward Cree /* L2 (inner when encap) */ 506d1c604dSEdward Cree __be16 eth_proto; 516d1c604dSEdward Cree __be16 vlan_tci[2], vlan_proto[2]; 526d1c604dSEdward Cree u8 eth_saddr[ETH_ALEN], eth_daddr[ETH_ALEN]; 53c178dff3SEdward Cree /* L3 (when IP) */ 54c178dff3SEdward Cree u8 ip_proto, ip_tos, ip_ttl; 55c178dff3SEdward Cree __be32 src_ip, dst_ip; 56c178dff3SEdward Cree #ifdef CONFIG_IPV6 57c178dff3SEdward Cree struct in6_addr src_ip6, dst_ip6; 58c178dff3SEdward Cree #endif 595ca7ef29SEdward Cree bool ip_frag, ip_firstfrag; 605d1d24daSEdward Cree /* L4 */ 615d1d24daSEdward Cree __be16 l4_sport, l4_dport; /* Ports (UDP, TCP) */ 625d1d24daSEdward Cree __be16 tcp_flags; 63b9d5c9b7SEdward Cree /* Encap. The following are *outer* fields. Note that there are no 64b9d5c9b7SEdward Cree * outer eth (L2) fields; this is because TC doesn't have them. 65b9d5c9b7SEdward Cree */ 66b9d5c9b7SEdward Cree __be32 enc_src_ip, enc_dst_ip; 67b9d5c9b7SEdward Cree struct in6_addr enc_src_ip6, enc_dst_ip6; 68b9d5c9b7SEdward Cree u8 enc_ip_tos, enc_ip_ttl; 69b9d5c9b7SEdward Cree __be16 enc_sport, enc_dport; 70b9d5c9b7SEdward Cree __be32 enc_keyid; /* e.g. VNI, VSID */ 71b9d5c9b7SEdward Cree }; 72b9d5c9b7SEdward Cree 73b9d5c9b7SEdward Cree static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask) 74b9d5c9b7SEdward Cree { 75b9d5c9b7SEdward Cree return mask->enc_src_ip || mask->enc_dst_ip || 76b9d5c9b7SEdward Cree !ipv6_addr_any(&mask->enc_src_ip6) || 77b9d5c9b7SEdward Cree !ipv6_addr_any(&mask->enc_dst_ip6) || mask->enc_ip_tos || 78b9d5c9b7SEdward Cree mask->enc_ip_ttl || mask->enc_sport || mask->enc_dport; 79b9d5c9b7SEdward Cree } 80b9d5c9b7SEdward Cree 813c9561c0SEdward Cree /** 823c9561c0SEdward Cree * enum efx_tc_em_pseudo_type - &struct efx_tc_encap_match pseudo type 833c9561c0SEdward Cree * 843c9561c0SEdward Cree * These are used to classify "pseudo" encap matches, which don't refer 853c9561c0SEdward Cree * to an entry in hardware but rather indicate that a section of the 863c9561c0SEdward Cree * match space is in use by another Outer Rule. 873c9561c0SEdward Cree * 883c9561c0SEdward Cree * @EFX_TC_EM_DIRECT: real HW entry in Outer Rule table; not a pseudo. 893c9561c0SEdward Cree * Hardware index in &struct efx_tc_encap_match.fw_id is valid. 903c9561c0SEdward Cree * @EFX_TC_EM_PSEUDO_MASK: registered by an encap match which includes a 91b6583d5eSEdward Cree * match on an optional field (currently ip_tos and/or udp_sport), 92b6583d5eSEdward Cree * to prevent an overlapping encap match _without_ optional fields. 933c9561c0SEdward Cree * The pseudo encap match may be referenced again by an encap match 94b6583d5eSEdward Cree * with different values for these fields, but all masks must match the 95b6583d5eSEdward Cree * first (stored in our child_* fields). 963c9561c0SEdward Cree */ 973c9561c0SEdward Cree enum efx_tc_em_pseudo_type { 983c9561c0SEdward Cree EFX_TC_EM_DIRECT, 993c9561c0SEdward Cree EFX_TC_EM_PSEUDO_MASK, 1003c9561c0SEdward Cree }; 1013c9561c0SEdward Cree 102b9d5c9b7SEdward Cree struct efx_tc_encap_match { 103b9d5c9b7SEdward Cree __be32 src_ip, dst_ip; 104b9d5c9b7SEdward Cree struct in6_addr src_ip6, dst_ip6; 105b9d5c9b7SEdward Cree __be16 udp_dport; 106b6583d5eSEdward Cree __be16 udp_sport, udp_sport_mask; 10756beb35dSEdward Cree u8 ip_tos, ip_tos_mask; 108746224cdSEdward Cree struct rhash_head linkage; 1092245eb00SEdward Cree enum efx_encap_type tun_type; 1103c9561c0SEdward Cree u8 child_ip_tos_mask; 111b6583d5eSEdward Cree __be16 child_udp_sport_mask; 112746224cdSEdward Cree refcount_t ref; 1133c9561c0SEdward Cree enum efx_tc_em_pseudo_type type; 114b9d5c9b7SEdward Cree u32 fw_id; /* index of this entry in firmware encap match table */ 1153c9561c0SEdward Cree struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */ 11667ab160eSEdward Cree }; 11767ab160eSEdward Cree 11867ab160eSEdward Cree struct efx_tc_match { 11967ab160eSEdward Cree struct efx_tc_match_fields value; 12067ab160eSEdward Cree struct efx_tc_match_fields mask; 121b9d5c9b7SEdward Cree struct efx_tc_encap_match *encap; 12267ab160eSEdward Cree }; 12367ab160eSEdward Cree 12467ab160eSEdward Cree struct efx_tc_action_set_list { 12567ab160eSEdward Cree struct list_head list; 12667ab160eSEdward Cree u32 fw_id; 12767ab160eSEdward Cree }; 12867ab160eSEdward Cree 12967ab160eSEdward Cree struct efx_tc_flow_rule { 130f54a28a2SEdward Cree unsigned long cookie; 131f54a28a2SEdward Cree struct rhash_head linkage; 13267ab160eSEdward Cree struct efx_tc_match match; 13367ab160eSEdward Cree struct efx_tc_action_set_list acts; 134b4da4235SEdward Cree struct efx_tc_action_set_list *fallback; /* what to use when unready? */ 13567ab160eSEdward Cree u32 fw_id; 13667ab160eSEdward Cree }; 13767ab160eSEdward Cree 13867ab160eSEdward Cree enum efx_tc_rule_prios { 139d902e1a7SEdward Cree EFX_TC_PRIO_TC, /* Rule inserted by TC */ 14067ab160eSEdward Cree EFX_TC_PRIO_DFLT, /* Default switch rule; one of efx_tc_default_rules */ 14167ab160eSEdward Cree EFX_TC_PRIO__NUM 14267ab160eSEdward Cree }; 14367ab160eSEdward Cree 1443bf969e8SEdward Cree struct efx_tc_table_field_fmt { 1453bf969e8SEdward Cree u16 field_id; 1463bf969e8SEdward Cree u16 lbn; 1473bf969e8SEdward Cree u16 width; 1483bf969e8SEdward Cree u8 masking; 1493bf969e8SEdward Cree u8 scheme; 1503bf969e8SEdward Cree }; 1513bf969e8SEdward Cree 1523bf969e8SEdward Cree struct efx_tc_table_desc { 1533bf969e8SEdward Cree u16 type; 1543bf969e8SEdward Cree u16 key_width; 1553bf969e8SEdward Cree u16 resp_width; 1563bf969e8SEdward Cree u16 n_keys; 1573bf969e8SEdward Cree u16 n_resps; 1583bf969e8SEdward Cree u16 n_prios; 1593bf969e8SEdward Cree u8 flags; 1603bf969e8SEdward Cree u8 scheme; 1613bf969e8SEdward Cree struct efx_tc_table_field_fmt *keys; 1623bf969e8SEdward Cree struct efx_tc_table_field_fmt *resps; 1633bf969e8SEdward Cree }; 1643bf969e8SEdward Cree 1653bf969e8SEdward Cree struct efx_tc_table_ct { /* TABLE_ID_CONNTRACK_TABLE */ 1663bf969e8SEdward Cree struct efx_tc_table_desc desc; 1673bf969e8SEdward Cree bool hooked; 1683bf969e8SEdward Cree struct { /* indices of named fields within @desc.keys */ 1693bf969e8SEdward Cree u8 eth_proto_idx; 1703bf969e8SEdward Cree u8 ip_proto_idx; 1713bf969e8SEdward Cree u8 src_ip_idx; /* either v4 or v6 */ 1723bf969e8SEdward Cree u8 dst_ip_idx; 1733bf969e8SEdward Cree u8 l4_sport_idx; 1743bf969e8SEdward Cree u8 l4_dport_idx; 1753bf969e8SEdward Cree u8 zone_idx; /* for TABLE_FIELD_ID_DOMAIN */ 1763bf969e8SEdward Cree } keys; 1773bf969e8SEdward Cree struct { /* indices of named fields within @desc.resps */ 1783bf969e8SEdward Cree u8 dnat_idx; 1793bf969e8SEdward Cree u8 nat_ip_idx; 1803bf969e8SEdward Cree u8 l4_natport_idx; 1813bf969e8SEdward Cree u8 mark_idx; 1823bf969e8SEdward Cree u8 counter_id_idx; 1833bf969e8SEdward Cree } resps; 1843bf969e8SEdward Cree }; 1853bf969e8SEdward Cree 18667ab160eSEdward Cree /** 18767ab160eSEdward Cree * struct efx_tc_state - control plane data for TC offload 18867ab160eSEdward Cree * 1897ce3e235SEdward Cree * @caps: MAE capabilities reported by MCDI 1909dc0cad2SEdward Cree * @block_list: List of &struct efx_tc_block_binding 191f54a28a2SEdward Cree * @mutex: Used to serialise operations on TC hashtables 19219a0c989SEdward Cree * @counter_ht: Hashtable of TC counters (FW IDs and counter values) 19319a0c989SEdward Cree * @counter_id_ht: Hashtable mapping TC counter cookies to counters 194b4da4235SEdward Cree * @encap_ht: Hashtable of TC encap actions 195746224cdSEdward Cree * @encap_match_ht: Hashtable of TC encap matches 196f54a28a2SEdward Cree * @match_action_ht: Hashtable of TC match-action rules 197c3bb5c6aSEdward Cree * @ct_zone_ht: Hashtable of TC conntrack flowtable bindings 198*1909387fSEdward Cree * @ct_ht: Hashtable of TC conntrack flow entries 1997e5e7d80SEdward Cree * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) 2003bf969e8SEdward Cree * @meta_ct: MAE table layout for conntrack table 201e37f3b15SEdward Cree * @reps_mport_id: MAE port allocated for representor RX 202e37f3b15SEdward Cree * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) 203e37f3b15SEdward Cree * @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) 204e37f3b15SEdward Cree * @reps_mport_vport_id: vport_id for representor RX filters 205e5731274SEdward Cree * @flush_counters: counters have been stopped, waiting for drain 206e5731274SEdward Cree * @flush_gen: final generation count per type array as reported by 207e5731274SEdward Cree * MC_CMD_MAE_COUNTERS_STREAM_STOP 208e5731274SEdward Cree * @seen_gen: most recent generation count per type as seen by efx_tc_rx() 209e5731274SEdward Cree * @flush_wq: wait queue used by efx_mae_stop_counters() to wait for 210e5731274SEdward Cree * MAE counters RXQ to finish draining 21167ab160eSEdward Cree * @dflt: Match-action rules for default switching; at priority 21267ab160eSEdward Cree * %EFX_TC_PRIO_DFLT. Named by *ingress* port 21367ab160eSEdward Cree * @dflt.pf: rule for traffic ingressing from PF (egresses to wire) 21467ab160eSEdward Cree * @dflt.wire: rule for traffic ingressing from wire (egresses to PF) 215e16ca7fbSEdward Cree * @facts: Fallback action-set-lists for unready rules. Named by *egress* port 216e16ca7fbSEdward Cree * @facts.pf: action-set-list for unready rules on PF netdev, hence applying to 217e16ca7fbSEdward Cree * traffic from wire, and egressing to PF 218e16ca7fbSEdward Cree * @facts.reps: action-set-list for unready rules on representors, hence 219e16ca7fbSEdward Cree * applying to traffic from representees, and egressing to the reps mport 2209dc0cad2SEdward Cree * @up: have TC datastructures been set up? 22167ab160eSEdward Cree */ 22267ab160eSEdward Cree struct efx_tc_state { 2237ce3e235SEdward Cree struct mae_caps *caps; 2249dc0cad2SEdward Cree struct list_head block_list; 225f54a28a2SEdward Cree struct mutex mutex; 22619a0c989SEdward Cree struct rhashtable counter_ht; 22719a0c989SEdward Cree struct rhashtable counter_id_ht; 228b4da4235SEdward Cree struct rhashtable encap_ht; 229746224cdSEdward Cree struct rhashtable encap_match_ht; 230f54a28a2SEdward Cree struct rhashtable match_action_ht; 231c3bb5c6aSEdward Cree struct rhashtable ct_zone_ht; 232*1909387fSEdward Cree struct rhashtable ct_ht; 2337e5e7d80SEdward Cree struct rhashtable neigh_ht; 2343bf969e8SEdward Cree struct efx_tc_table_ct meta_ct; 235e37f3b15SEdward Cree u32 reps_mport_id, reps_mport_vport_id; 236e37f3b15SEdward Cree s32 reps_filter_uc, reps_filter_mc; 237e5731274SEdward Cree bool flush_counters; 238e5731274SEdward Cree u32 flush_gen[EFX_TC_COUNTER_TYPE_MAX]; 239e5731274SEdward Cree u32 seen_gen[EFX_TC_COUNTER_TYPE_MAX]; 240e5731274SEdward Cree wait_queue_head_t flush_wq; 24167ab160eSEdward Cree struct { 24267ab160eSEdward Cree struct efx_tc_flow_rule pf; 24367ab160eSEdward Cree struct efx_tc_flow_rule wire; 24467ab160eSEdward Cree } dflt; 245e16ca7fbSEdward Cree struct { 246e16ca7fbSEdward Cree struct efx_tc_action_set_list pf; 247e16ca7fbSEdward Cree struct efx_tc_action_set_list reps; 248e16ca7fbSEdward Cree } facts; 2499dc0cad2SEdward Cree bool up; 25067ab160eSEdward Cree }; 25167ab160eSEdward Cree 25267ab160eSEdward Cree struct efx_rep; 25367ab160eSEdward Cree 254b4da4235SEdward Cree enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev); 2557e5e7d80SEdward Cree struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, 2567e5e7d80SEdward Cree struct net_device *dev); 2577e5e7d80SEdward Cree s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv); 25867ab160eSEdward Cree int efx_tc_configure_default_rule_rep(struct efx_rep *efv); 25967ab160eSEdward Cree void efx_tc_deconfigure_default_rule(struct efx_nic *efx, 26067ab160eSEdward Cree struct efx_tc_flow_rule *rule); 2619dc0cad2SEdward Cree int efx_tc_flower(struct efx_nic *efx, struct net_device *net_dev, 2629dc0cad2SEdward Cree struct flow_cls_offload *tc, struct efx_rep *efv); 26367ab160eSEdward Cree 264e37f3b15SEdward Cree int efx_tc_insert_rep_filters(struct efx_nic *efx); 265e37f3b15SEdward Cree void efx_tc_remove_rep_filters(struct efx_nic *efx); 266e37f3b15SEdward Cree 26767ab160eSEdward Cree int efx_init_tc(struct efx_nic *efx); 26867ab160eSEdward Cree void efx_fini_tc(struct efx_nic *efx); 26967ab160eSEdward Cree 27067ab160eSEdward Cree int efx_init_struct_tc(struct efx_nic *efx); 27167ab160eSEdward Cree void efx_fini_struct_tc(struct efx_nic *efx); 27267ab160eSEdward Cree 27367ab160eSEdward Cree #endif /* EFX_TC_H */ 274