/* Broadcom NetXtreme-C/E network driver. * * Copyright (c) 2017 Broadcom Limited * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. */ #ifndef BNXT_TC_H #define BNXT_TC_H #ifdef CONFIG_BNXT_FLOWER_OFFLOAD #include <net/ip_tunnels.h> /* Structs used for storing the filter/actions of the TC cmd. */ struct bnxt_tc_l2_key { u8 dmac[ETH_ALEN]; u8 smac[ETH_ALEN]; __be16 inner_vlan_tpid; __be16 inner_vlan_tci; __be16 ether_type; u8 num_vlans; u8 dir; #define BNXT_DIR_RX 1 #define BNXT_DIR_TX 0 }; struct bnxt_tc_l3_key { union { struct { struct in_addr daddr; struct in_addr saddr; } ipv4; struct { struct in6_addr daddr; struct in6_addr saddr; } ipv6; }; }; struct bnxt_tc_l4_key { u8 ip_proto; union { struct { __be16 sport; __be16 dport; } ports; struct { u8 type; u8 code; } icmp; }; }; struct bnxt_tc_tunnel_key { struct bnxt_tc_l2_key l2; struct bnxt_tc_l3_key l3; struct bnxt_tc_l4_key l4; __be32 id; }; #define bnxt_eth_addr_key_mask_invalid(eth_addr, eth_addr_mask) \ ((is_wildcard(&(eth_addr)[0], ETH_ALEN) && \ is_wildcard(&(eth_addr)[ETH_ALEN / 2], ETH_ALEN)) || \ (is_wildcard(&(eth_addr_mask)[0], ETH_ALEN) && \ is_wildcard(&(eth_addr_mask)[ETH_ALEN / 2], ETH_ALEN))) struct bnxt_tc_actions { u32 flags; #define BNXT_TC_ACTION_FLAG_FWD BIT(0) #define BNXT_TC_ACTION_FLAG_FWD_VXLAN BIT(1) #define BNXT_TC_ACTION_FLAG_PUSH_VLAN BIT(3) #define BNXT_TC_ACTION_FLAG_POP_VLAN BIT(4) #define BNXT_TC_ACTION_FLAG_DROP BIT(5) #define BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP BIT(6) #define BNXT_TC_ACTION_FLAG_TUNNEL_DECAP BIT(7) #define BNXT_TC_ACTION_FLAG_L2_REWRITE BIT(8) #define BNXT_TC_ACTION_FLAG_NAT_XLATE BIT(9) u16 dst_fid; struct net_device *dst_dev; __be16 push_vlan_tpid; __be16 push_vlan_tci; /* tunnel encap */ struct ip_tunnel_key tun_encap_key; #define PEDIT_OFFSET_SMAC_LAST_4_BYTES 0x8 __be16 l2_rewrite_dmac[3]; __be16 l2_rewrite_smac[3]; struct { bool src_xlate; /* true => translate src, * false => translate dst * Mutually exclusive, i.e cannot set both */ bool l3_is_ipv4; /* false means L3 is ipv6 */ struct bnxt_tc_l3_key l3; struct bnxt_tc_l4_key l4; } nat; }; struct bnxt_tc_flow { u32 flags; #define BNXT_TC_FLOW_FLAGS_ETH_ADDRS BIT(1) #define BNXT_TC_FLOW_FLAGS_IPV4_ADDRS BIT(2) #define BNXT_TC_FLOW_FLAGS_IPV6_ADDRS BIT(3) #define BNXT_TC_FLOW_FLAGS_PORTS BIT(4) #define BNXT_TC_FLOW_FLAGS_ICMP BIT(5) #define BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS BIT(6) #define BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS BIT(7) #define BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS BIT(8) #define BNXT_TC_FLOW_FLAGS_TUNL_PORTS BIT(9) #define BNXT_TC_FLOW_FLAGS_TUNL_ID BIT(10) #define BNXT_TC_FLOW_FLAGS_TUNNEL (BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS | \ BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS | \ BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS |\ BNXT_TC_FLOW_FLAGS_TUNL_PORTS |\ BNXT_TC_FLOW_FLAGS_TUNL_ID) /* flow applicable to pkts ingressing on this fid */ u16 src_fid; struct bnxt_tc_l2_key l2_key; struct bnxt_tc_l2_key l2_mask; struct bnxt_tc_l3_key l3_key; struct bnxt_tc_l3_key l3_mask; struct bnxt_tc_l4_key l4_key; struct bnxt_tc_l4_key l4_mask; struct ip_tunnel_key tun_key; struct ip_tunnel_key tun_mask; struct bnxt_tc_actions actions; /* updated stats accounting for hw-counter wrap-around */ struct bnxt_tc_flow_stats stats; /* previous snap-shot of stats */ struct bnxt_tc_flow_stats prev_stats; unsigned long lastused; /* jiffies */ /* for calculating delta from prev_stats and * updating prev_stats atomically. */ spinlock_t stats_lock; }; /* Tunnel encap/decap hash table * This table is used to maintain a list of flows that use * the same tunnel encap/decap params (ip_daddrs, vni, udp_dport) * and the FW returned handle. * A separate table is maintained for encap and decap */ struct bnxt_tc_tunnel_node { struct ip_tunnel_key key; struct rhash_head node; /* tunnel l2 info */ struct bnxt_tc_l2_key l2_info; #define INVALID_TUNNEL_HANDLE cpu_to_le32(0xffffffff) /* tunnel handle returned by FW */ __le32 tunnel_handle; u32 refcount; struct rcu_head rcu; }; /* L2 hash table * The same data-struct is used for L2-flow table and L2-tunnel table. * The L2 part of a flow or tunnel is stored in a hash table. * A flow that shares the same L2 key/mask with an * already existing flow/tunnel must refer to it's flow handle or * decap_filter_id respectively. */ struct bnxt_tc_l2_node { /* hash key: first 16b of key */ #define BNXT_TC_L2_KEY_LEN 16 struct bnxt_tc_l2_key key; struct rhash_head node; /* a linked list of flows that share the same l2 key */ struct list_head common_l2_flows; /* number of flows/tunnels sharing the l2 key */ u16 refcount; struct rcu_head rcu; }; struct bnxt_tc_flow_node { /* hash key: provided by TC */ unsigned long cookie; struct rhash_head node; struct bnxt_tc_flow flow; __le64 ext_flow_handle; __le16 flow_handle; __le32 flow_id; /* L2 node in l2 hashtable that shares flow's l2 key */ struct bnxt_tc_l2_node *l2_node; /* for the shared_flows list maintained in l2_node */ struct list_head l2_list_node; /* tunnel encap related */ struct bnxt_tc_tunnel_node *encap_node; /* tunnel decap related */ struct bnxt_tc_tunnel_node *decap_node; /* L2 node in tunnel-l2 hashtable that shares flow's tunnel l2 key */ struct bnxt_tc_l2_node *decap_l2_node; /* for the shared_flows list maintained in tunnel decap l2_node */ struct list_head decap_l2_list_node; struct rcu_head rcu; }; int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid, struct flow_cls_offload *cls_flower); int bnxt_init_tc(struct bnxt *bp); void bnxt_shutdown_tc(struct bnxt *bp); void bnxt_tc_flow_stats_work(struct bnxt *bp); static inline bool bnxt_tc_flower_enabled(struct bnxt *bp) { return bp->tc_info && bp->tc_info->enabled; } #else /* CONFIG_BNXT_FLOWER_OFFLOAD */ static inline int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid, struct flow_cls_offload *cls_flower) { return -EOPNOTSUPP; } static inline int bnxt_init_tc(struct bnxt *bp) { return 0; } static inline void bnxt_shutdown_tc(struct bnxt *bp) { } static inline void bnxt_tc_flow_stats_work(struct bnxt *bp) { } static inline bool bnxt_tc_flower_enabled(struct bnxt *bp) { return false; } #endif /* CONFIG_BNXT_FLOWER_OFFLOAD */ #endif /* BNXT_TC_H */