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 #ifdef CONFIG_IPV6 22746224cdSEdward Cree static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) 23746224cdSEdward Cree { 24746224cdSEdward Cree return !memchr_inv(addr, 0xff, sizeof(*addr)); 25746224cdSEdward Cree } 26746224cdSEdward Cree #endif 27746224cdSEdward Cree 28b4da4235SEdward Cree struct efx_tc_encap_action; /* see tc_encap_actions.h */ 29b4da4235SEdward Cree 3067ab160eSEdward Cree struct efx_tc_action_set { 3105ccd8d8SEdward Cree u16 vlan_push:2; 3205ccd8d8SEdward Cree u16 vlan_pop:2; 3317654d84SEdward Cree u16 decap:1; 3467ab160eSEdward Cree u16 deliver:1; 3505ccd8d8SEdward Cree __be16 vlan_tci[2]; /* TCIs for vlan_push */ 3605ccd8d8SEdward Cree __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ 372e0f1eb0SEdward Cree struct efx_tc_counter_index *count; 38b4da4235SEdward Cree struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ 397e5e7d80SEdward Cree struct list_head encap_user; /* entry on encap_md->users list */ 407e5e7d80SEdward Cree struct efx_tc_action_set_list *user; /* Only populated if encap_md */ 41*9a14f2e3SEdward Cree struct list_head count_user; /* entry on counter->users list, if encap */ 4267ab160eSEdward Cree u32 dest_mport; 4367ab160eSEdward Cree u32 fw_id; /* index of this entry in firmware actions table */ 4467ab160eSEdward Cree struct list_head list; 4567ab160eSEdward Cree }; 4667ab160eSEdward Cree 4767ab160eSEdward Cree struct efx_tc_match_fields { 4867ab160eSEdward Cree /* L1 */ 4967ab160eSEdward Cree u32 ingress_port; 50d902e1a7SEdward Cree u8 recirc_id; 516d1c604dSEdward Cree /* L2 (inner when encap) */ 526d1c604dSEdward Cree __be16 eth_proto; 536d1c604dSEdward Cree __be16 vlan_tci[2], vlan_proto[2]; 546d1c604dSEdward Cree u8 eth_saddr[ETH_ALEN], eth_daddr[ETH_ALEN]; 55c178dff3SEdward Cree /* L3 (when IP) */ 56c178dff3SEdward Cree u8 ip_proto, ip_tos, ip_ttl; 57c178dff3SEdward Cree __be32 src_ip, dst_ip; 58c178dff3SEdward Cree #ifdef CONFIG_IPV6 59c178dff3SEdward Cree struct in6_addr src_ip6, dst_ip6; 60c178dff3SEdward Cree #endif 615ca7ef29SEdward Cree bool ip_frag, ip_firstfrag; 625d1d24daSEdward Cree /* L4 */ 635d1d24daSEdward Cree __be16 l4_sport, l4_dport; /* Ports (UDP, TCP) */ 645d1d24daSEdward Cree __be16 tcp_flags; 65b9d5c9b7SEdward Cree /* Encap. The following are *outer* fields. Note that there are no 66b9d5c9b7SEdward Cree * outer eth (L2) fields; this is because TC doesn't have them. 67b9d5c9b7SEdward Cree */ 68b9d5c9b7SEdward Cree __be32 enc_src_ip, enc_dst_ip; 69b9d5c9b7SEdward Cree struct in6_addr enc_src_ip6, enc_dst_ip6; 70b9d5c9b7SEdward Cree u8 enc_ip_tos, enc_ip_ttl; 71b9d5c9b7SEdward Cree __be16 enc_sport, enc_dport; 72b9d5c9b7SEdward Cree __be32 enc_keyid; /* e.g. VNI, VSID */ 73b9d5c9b7SEdward Cree }; 74b9d5c9b7SEdward Cree 75b9d5c9b7SEdward Cree static inline bool efx_tc_match_is_encap(const struct efx_tc_match_fields *mask) 76b9d5c9b7SEdward Cree { 77b9d5c9b7SEdward Cree return mask->enc_src_ip || mask->enc_dst_ip || 78b9d5c9b7SEdward Cree !ipv6_addr_any(&mask->enc_src_ip6) || 79b9d5c9b7SEdward Cree !ipv6_addr_any(&mask->enc_dst_ip6) || mask->enc_ip_tos || 80b9d5c9b7SEdward Cree mask->enc_ip_ttl || mask->enc_sport || mask->enc_dport; 81b9d5c9b7SEdward Cree } 82b9d5c9b7SEdward Cree 833c9561c0SEdward Cree /** 843c9561c0SEdward Cree * enum efx_tc_em_pseudo_type - &struct efx_tc_encap_match pseudo type 853c9561c0SEdward Cree * 863c9561c0SEdward Cree * These are used to classify "pseudo" encap matches, which don't refer 873c9561c0SEdward Cree * to an entry in hardware but rather indicate that a section of the 883c9561c0SEdward Cree * match space is in use by another Outer Rule. 893c9561c0SEdward Cree * 903c9561c0SEdward Cree * @EFX_TC_EM_DIRECT: real HW entry in Outer Rule table; not a pseudo. 913c9561c0SEdward Cree * Hardware index in &struct efx_tc_encap_match.fw_id is valid. 923c9561c0SEdward Cree * @EFX_TC_EM_PSEUDO_MASK: registered by an encap match which includes a 93b6583d5eSEdward Cree * match on an optional field (currently ip_tos and/or udp_sport), 94b6583d5eSEdward Cree * to prevent an overlapping encap match _without_ optional fields. 953c9561c0SEdward Cree * The pseudo encap match may be referenced again by an encap match 96b6583d5eSEdward Cree * with different values for these fields, but all masks must match the 97b6583d5eSEdward Cree * first (stored in our child_* fields). 983c9561c0SEdward Cree */ 993c9561c0SEdward Cree enum efx_tc_em_pseudo_type { 1003c9561c0SEdward Cree EFX_TC_EM_DIRECT, 1013c9561c0SEdward Cree EFX_TC_EM_PSEUDO_MASK, 1023c9561c0SEdward Cree }; 1033c9561c0SEdward Cree 104b9d5c9b7SEdward Cree struct efx_tc_encap_match { 105b9d5c9b7SEdward Cree __be32 src_ip, dst_ip; 106b9d5c9b7SEdward Cree struct in6_addr src_ip6, dst_ip6; 107b9d5c9b7SEdward Cree __be16 udp_dport; 108b6583d5eSEdward Cree __be16 udp_sport, udp_sport_mask; 10956beb35dSEdward Cree u8 ip_tos, ip_tos_mask; 110746224cdSEdward Cree struct rhash_head linkage; 1112245eb00SEdward Cree enum efx_encap_type tun_type; 1123c9561c0SEdward Cree u8 child_ip_tos_mask; 113b6583d5eSEdward Cree __be16 child_udp_sport_mask; 114746224cdSEdward Cree refcount_t ref; 1153c9561c0SEdward Cree enum efx_tc_em_pseudo_type type; 116b9d5c9b7SEdward Cree u32 fw_id; /* index of this entry in firmware encap match table */ 1173c9561c0SEdward Cree struct efx_tc_encap_match *pseudo; /* Referenced pseudo EM if needed */ 11867ab160eSEdward Cree }; 11967ab160eSEdward Cree 12067ab160eSEdward Cree struct efx_tc_match { 12167ab160eSEdward Cree struct efx_tc_match_fields value; 12267ab160eSEdward Cree struct efx_tc_match_fields mask; 123b9d5c9b7SEdward Cree struct efx_tc_encap_match *encap; 12467ab160eSEdward Cree }; 12567ab160eSEdward Cree 12667ab160eSEdward Cree struct efx_tc_action_set_list { 12767ab160eSEdward Cree struct list_head list; 12867ab160eSEdward Cree u32 fw_id; 12967ab160eSEdward Cree }; 13067ab160eSEdward Cree 13167ab160eSEdward Cree struct efx_tc_flow_rule { 132f54a28a2SEdward Cree unsigned long cookie; 133f54a28a2SEdward Cree struct rhash_head linkage; 13467ab160eSEdward Cree struct efx_tc_match match; 13567ab160eSEdward Cree struct efx_tc_action_set_list acts; 136b4da4235SEdward Cree struct efx_tc_action_set_list *fallback; /* what to use when unready? */ 13767ab160eSEdward Cree u32 fw_id; 13867ab160eSEdward Cree }; 13967ab160eSEdward Cree 14067ab160eSEdward Cree enum efx_tc_rule_prios { 141d902e1a7SEdward Cree EFX_TC_PRIO_TC, /* Rule inserted by TC */ 14267ab160eSEdward Cree EFX_TC_PRIO_DFLT, /* Default switch rule; one of efx_tc_default_rules */ 14367ab160eSEdward Cree EFX_TC_PRIO__NUM 14467ab160eSEdward Cree }; 14567ab160eSEdward Cree 14667ab160eSEdward Cree /** 14767ab160eSEdward Cree * struct efx_tc_state - control plane data for TC offload 14867ab160eSEdward Cree * 1497ce3e235SEdward Cree * @caps: MAE capabilities reported by MCDI 1509dc0cad2SEdward Cree * @block_list: List of &struct efx_tc_block_binding 151f54a28a2SEdward Cree * @mutex: Used to serialise operations on TC hashtables 15219a0c989SEdward Cree * @counter_ht: Hashtable of TC counters (FW IDs and counter values) 15319a0c989SEdward Cree * @counter_id_ht: Hashtable mapping TC counter cookies to counters 154b4da4235SEdward Cree * @encap_ht: Hashtable of TC encap actions 155746224cdSEdward Cree * @encap_match_ht: Hashtable of TC encap matches 156f54a28a2SEdward Cree * @match_action_ht: Hashtable of TC match-action rules 1577e5e7d80SEdward Cree * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) 158e37f3b15SEdward Cree * @reps_mport_id: MAE port allocated for representor RX 159e37f3b15SEdward Cree * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) 160e37f3b15SEdward Cree * @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) 161e37f3b15SEdward Cree * @reps_mport_vport_id: vport_id for representor RX filters 162e5731274SEdward Cree * @flush_counters: counters have been stopped, waiting for drain 163e5731274SEdward Cree * @flush_gen: final generation count per type array as reported by 164e5731274SEdward Cree * MC_CMD_MAE_COUNTERS_STREAM_STOP 165e5731274SEdward Cree * @seen_gen: most recent generation count per type as seen by efx_tc_rx() 166e5731274SEdward Cree * @flush_wq: wait queue used by efx_mae_stop_counters() to wait for 167e5731274SEdward Cree * MAE counters RXQ to finish draining 16867ab160eSEdward Cree * @dflt: Match-action rules for default switching; at priority 16967ab160eSEdward Cree * %EFX_TC_PRIO_DFLT. Named by *ingress* port 17067ab160eSEdward Cree * @dflt.pf: rule for traffic ingressing from PF (egresses to wire) 17167ab160eSEdward Cree * @dflt.wire: rule for traffic ingressing from wire (egresses to PF) 172e16ca7fbSEdward Cree * @facts: Fallback action-set-lists for unready rules. Named by *egress* port 173e16ca7fbSEdward Cree * @facts.pf: action-set-list for unready rules on PF netdev, hence applying to 174e16ca7fbSEdward Cree * traffic from wire, and egressing to PF 175e16ca7fbSEdward Cree * @facts.reps: action-set-list for unready rules on representors, hence 176e16ca7fbSEdward Cree * applying to traffic from representees, and egressing to the reps mport 1779dc0cad2SEdward Cree * @up: have TC datastructures been set up? 17867ab160eSEdward Cree */ 17967ab160eSEdward Cree struct efx_tc_state { 1807ce3e235SEdward Cree struct mae_caps *caps; 1819dc0cad2SEdward Cree struct list_head block_list; 182f54a28a2SEdward Cree struct mutex mutex; 18319a0c989SEdward Cree struct rhashtable counter_ht; 18419a0c989SEdward Cree struct rhashtable counter_id_ht; 185b4da4235SEdward Cree struct rhashtable encap_ht; 186746224cdSEdward Cree struct rhashtable encap_match_ht; 187f54a28a2SEdward Cree struct rhashtable match_action_ht; 1887e5e7d80SEdward Cree struct rhashtable neigh_ht; 189e37f3b15SEdward Cree u32 reps_mport_id, reps_mport_vport_id; 190e37f3b15SEdward Cree s32 reps_filter_uc, reps_filter_mc; 191e5731274SEdward Cree bool flush_counters; 192e5731274SEdward Cree u32 flush_gen[EFX_TC_COUNTER_TYPE_MAX]; 193e5731274SEdward Cree u32 seen_gen[EFX_TC_COUNTER_TYPE_MAX]; 194e5731274SEdward Cree wait_queue_head_t flush_wq; 19567ab160eSEdward Cree struct { 19667ab160eSEdward Cree struct efx_tc_flow_rule pf; 19767ab160eSEdward Cree struct efx_tc_flow_rule wire; 19867ab160eSEdward Cree } dflt; 199e16ca7fbSEdward Cree struct { 200e16ca7fbSEdward Cree struct efx_tc_action_set_list pf; 201e16ca7fbSEdward Cree struct efx_tc_action_set_list reps; 202e16ca7fbSEdward Cree } facts; 2039dc0cad2SEdward Cree bool up; 20467ab160eSEdward Cree }; 20567ab160eSEdward Cree 20667ab160eSEdward Cree struct efx_rep; 20767ab160eSEdward Cree 208b4da4235SEdward Cree enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev); 2097e5e7d80SEdward Cree struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, 2107e5e7d80SEdward Cree struct net_device *dev); 2117e5e7d80SEdward Cree s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv); 21267ab160eSEdward Cree int efx_tc_configure_default_rule_rep(struct efx_rep *efv); 21367ab160eSEdward Cree void efx_tc_deconfigure_default_rule(struct efx_nic *efx, 21467ab160eSEdward Cree struct efx_tc_flow_rule *rule); 2159dc0cad2SEdward Cree int efx_tc_flower(struct efx_nic *efx, struct net_device *net_dev, 2169dc0cad2SEdward Cree struct flow_cls_offload *tc, struct efx_rep *efv); 21767ab160eSEdward Cree 218e37f3b15SEdward Cree int efx_tc_insert_rep_filters(struct efx_nic *efx); 219e37f3b15SEdward Cree void efx_tc_remove_rep_filters(struct efx_nic *efx); 220e37f3b15SEdward Cree 22167ab160eSEdward Cree int efx_init_tc(struct efx_nic *efx); 22267ab160eSEdward Cree void efx_fini_tc(struct efx_nic *efx); 22367ab160eSEdward Cree 22467ab160eSEdward Cree int efx_init_struct_tc(struct efx_nic *efx); 22567ab160eSEdward Cree void efx_fini_struct_tc(struct efx_nic *efx); 22667ab160eSEdward Cree 22767ab160eSEdward Cree #endif /* EFX_TC_H */ 228