162306a36Sopenharmony_ci/* Broadcom NetXtreme-C/E network driver.
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Copyright (c) 2017 Broadcom Limited
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This program is free software; you can redistribute it and/or modify
662306a36Sopenharmony_ci * it under the terms of the GNU General Public License as published by
762306a36Sopenharmony_ci * the Free Software Foundation.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#ifndef BNXT_TC_H
1162306a36Sopenharmony_ci#define BNXT_TC_H
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#ifdef CONFIG_BNXT_FLOWER_OFFLOAD
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <net/ip_tunnels.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/* Structs used for storing the filter/actions of the TC cmd.
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_cistruct bnxt_tc_l2_key {
2062306a36Sopenharmony_ci	u8		dmac[ETH_ALEN];
2162306a36Sopenharmony_ci	u8		smac[ETH_ALEN];
2262306a36Sopenharmony_ci	__be16		inner_vlan_tpid;
2362306a36Sopenharmony_ci	__be16		inner_vlan_tci;
2462306a36Sopenharmony_ci	__be16		ether_type;
2562306a36Sopenharmony_ci	u8		num_vlans;
2662306a36Sopenharmony_ci	u8		dir;
2762306a36Sopenharmony_ci#define BNXT_DIR_RX	1
2862306a36Sopenharmony_ci#define BNXT_DIR_TX	0
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistruct bnxt_tc_l3_key {
3262306a36Sopenharmony_ci	union {
3362306a36Sopenharmony_ci		struct {
3462306a36Sopenharmony_ci			struct in_addr daddr;
3562306a36Sopenharmony_ci			struct in_addr saddr;
3662306a36Sopenharmony_ci		} ipv4;
3762306a36Sopenharmony_ci		struct {
3862306a36Sopenharmony_ci			struct in6_addr daddr;
3962306a36Sopenharmony_ci			struct in6_addr saddr;
4062306a36Sopenharmony_ci		} ipv6;
4162306a36Sopenharmony_ci	};
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cistruct bnxt_tc_l4_key {
4562306a36Sopenharmony_ci	u8  ip_proto;
4662306a36Sopenharmony_ci	union {
4762306a36Sopenharmony_ci		struct {
4862306a36Sopenharmony_ci			__be16 sport;
4962306a36Sopenharmony_ci			__be16 dport;
5062306a36Sopenharmony_ci		} ports;
5162306a36Sopenharmony_ci		struct {
5262306a36Sopenharmony_ci			u8 type;
5362306a36Sopenharmony_ci			u8 code;
5462306a36Sopenharmony_ci		} icmp;
5562306a36Sopenharmony_ci	};
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistruct bnxt_tc_tunnel_key {
5962306a36Sopenharmony_ci	struct bnxt_tc_l2_key	l2;
6062306a36Sopenharmony_ci	struct bnxt_tc_l3_key	l3;
6162306a36Sopenharmony_ci	struct bnxt_tc_l4_key	l4;
6262306a36Sopenharmony_ci	__be32			id;
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#define bnxt_eth_addr_key_mask_invalid(eth_addr, eth_addr_mask)		\
6662306a36Sopenharmony_ci	((is_wildcard(&(eth_addr)[0], ETH_ALEN) &&			\
6762306a36Sopenharmony_ci	 is_wildcard(&(eth_addr)[ETH_ALEN / 2], ETH_ALEN)) ||		\
6862306a36Sopenharmony_ci	(is_wildcard(&(eth_addr_mask)[0], ETH_ALEN) &&			\
6962306a36Sopenharmony_ci	 is_wildcard(&(eth_addr_mask)[ETH_ALEN / 2], ETH_ALEN)))
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistruct bnxt_tc_actions {
7262306a36Sopenharmony_ci	u32				flags;
7362306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_FWD			BIT(0)
7462306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_FWD_VXLAN		BIT(1)
7562306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_PUSH_VLAN		BIT(3)
7662306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_POP_VLAN		BIT(4)
7762306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_DROP		BIT(5)
7862306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_TUNNEL_ENCAP	BIT(6)
7962306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_TUNNEL_DECAP	BIT(7)
8062306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_L2_REWRITE		BIT(8)
8162306a36Sopenharmony_ci#define BNXT_TC_ACTION_FLAG_NAT_XLATE		BIT(9)
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	u16				dst_fid;
8462306a36Sopenharmony_ci	struct net_device		*dst_dev;
8562306a36Sopenharmony_ci	__be16				push_vlan_tpid;
8662306a36Sopenharmony_ci	__be16				push_vlan_tci;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	/* tunnel encap */
8962306a36Sopenharmony_ci	struct ip_tunnel_key		tun_encap_key;
9062306a36Sopenharmony_ci#define	PEDIT_OFFSET_SMAC_LAST_4_BYTES		0x8
9162306a36Sopenharmony_ci	__be16				l2_rewrite_dmac[3];
9262306a36Sopenharmony_ci	__be16				l2_rewrite_smac[3];
9362306a36Sopenharmony_ci	struct {
9462306a36Sopenharmony_ci		bool src_xlate;  /* true => translate src,
9562306a36Sopenharmony_ci				  * false => translate dst
9662306a36Sopenharmony_ci				  * Mutually exclusive, i.e cannot set both
9762306a36Sopenharmony_ci				  */
9862306a36Sopenharmony_ci		bool l3_is_ipv4; /* false means L3 is ipv6 */
9962306a36Sopenharmony_ci		struct bnxt_tc_l3_key l3;
10062306a36Sopenharmony_ci		struct bnxt_tc_l4_key l4;
10162306a36Sopenharmony_ci	} nat;
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistruct bnxt_tc_flow {
10562306a36Sopenharmony_ci	u32				flags;
10662306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_ETH_ADDRS		BIT(1)
10762306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_IPV4_ADDRS		BIT(2)
10862306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_IPV6_ADDRS		BIT(3)
10962306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_PORTS		BIT(4)
11062306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_ICMP			BIT(5)
11162306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS	BIT(6)
11262306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS	BIT(7)
11362306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS	BIT(8)
11462306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_TUNL_PORTS		BIT(9)
11562306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_TUNL_ID		BIT(10)
11662306a36Sopenharmony_ci#define BNXT_TC_FLOW_FLAGS_TUNNEL	(BNXT_TC_FLOW_FLAGS_TUNL_ETH_ADDRS | \
11762306a36Sopenharmony_ci					 BNXT_TC_FLOW_FLAGS_TUNL_IPV4_ADDRS | \
11862306a36Sopenharmony_ci					 BNXT_TC_FLOW_FLAGS_TUNL_IPV6_ADDRS |\
11962306a36Sopenharmony_ci					 BNXT_TC_FLOW_FLAGS_TUNL_PORTS |\
12062306a36Sopenharmony_ci					 BNXT_TC_FLOW_FLAGS_TUNL_ID)
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	/* flow applicable to pkts ingressing on this fid */
12362306a36Sopenharmony_ci	u16				src_fid;
12462306a36Sopenharmony_ci	struct bnxt_tc_l2_key		l2_key;
12562306a36Sopenharmony_ci	struct bnxt_tc_l2_key		l2_mask;
12662306a36Sopenharmony_ci	struct bnxt_tc_l3_key		l3_key;
12762306a36Sopenharmony_ci	struct bnxt_tc_l3_key		l3_mask;
12862306a36Sopenharmony_ci	struct bnxt_tc_l4_key		l4_key;
12962306a36Sopenharmony_ci	struct bnxt_tc_l4_key		l4_mask;
13062306a36Sopenharmony_ci	struct ip_tunnel_key		tun_key;
13162306a36Sopenharmony_ci	struct ip_tunnel_key		tun_mask;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	struct bnxt_tc_actions		actions;
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	/* updated stats accounting for hw-counter wrap-around */
13662306a36Sopenharmony_ci	struct bnxt_tc_flow_stats	stats;
13762306a36Sopenharmony_ci	/* previous snap-shot of stats */
13862306a36Sopenharmony_ci	struct bnxt_tc_flow_stats	prev_stats;
13962306a36Sopenharmony_ci	unsigned long			lastused; /* jiffies */
14062306a36Sopenharmony_ci	/* for calculating delta from prev_stats and
14162306a36Sopenharmony_ci	 * updating prev_stats atomically.
14262306a36Sopenharmony_ci	 */
14362306a36Sopenharmony_ci	spinlock_t			stats_lock;
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/* Tunnel encap/decap hash table
14762306a36Sopenharmony_ci * This table is used to maintain a list of flows that use
14862306a36Sopenharmony_ci * the same tunnel encap/decap params (ip_daddrs, vni, udp_dport)
14962306a36Sopenharmony_ci * and the FW returned handle.
15062306a36Sopenharmony_ci * A separate table is maintained for encap and decap
15162306a36Sopenharmony_ci */
15262306a36Sopenharmony_cistruct bnxt_tc_tunnel_node {
15362306a36Sopenharmony_ci	struct ip_tunnel_key		key;
15462306a36Sopenharmony_ci	struct rhash_head		node;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	/* tunnel l2 info */
15762306a36Sopenharmony_ci	struct bnxt_tc_l2_key		l2_info;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci#define	INVALID_TUNNEL_HANDLE		cpu_to_le32(0xffffffff)
16062306a36Sopenharmony_ci	/* tunnel handle returned by FW */
16162306a36Sopenharmony_ci	__le32				tunnel_handle;
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci	u32				refcount;
16462306a36Sopenharmony_ci	struct rcu_head			rcu;
16562306a36Sopenharmony_ci};
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* L2 hash table
16862306a36Sopenharmony_ci * The same data-struct is used for L2-flow table and L2-tunnel table.
16962306a36Sopenharmony_ci * The L2 part of a flow or tunnel is stored in a hash table.
17062306a36Sopenharmony_ci * A flow that shares the same L2 key/mask with an
17162306a36Sopenharmony_ci * already existing flow/tunnel must refer to it's flow handle or
17262306a36Sopenharmony_ci * decap_filter_id respectively.
17362306a36Sopenharmony_ci */
17462306a36Sopenharmony_cistruct bnxt_tc_l2_node {
17562306a36Sopenharmony_ci	/* hash key: first 16b of key */
17662306a36Sopenharmony_ci#define BNXT_TC_L2_KEY_LEN			16
17762306a36Sopenharmony_ci	struct bnxt_tc_l2_key	key;
17862306a36Sopenharmony_ci	struct rhash_head	node;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/* a linked list of flows that share the same l2 key */
18162306a36Sopenharmony_ci	struct list_head	common_l2_flows;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	/* number of flows/tunnels sharing the l2 key */
18462306a36Sopenharmony_ci	u16			refcount;
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci	struct rcu_head		rcu;
18762306a36Sopenharmony_ci};
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistruct bnxt_tc_flow_node {
19062306a36Sopenharmony_ci	/* hash key: provided by TC */
19162306a36Sopenharmony_ci	unsigned long			cookie;
19262306a36Sopenharmony_ci	struct rhash_head		node;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	struct bnxt_tc_flow		flow;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	__le64				ext_flow_handle;
19762306a36Sopenharmony_ci	__le16				flow_handle;
19862306a36Sopenharmony_ci	__le32				flow_id;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/* L2 node in l2 hashtable that shares flow's l2 key */
20162306a36Sopenharmony_ci	struct bnxt_tc_l2_node		*l2_node;
20262306a36Sopenharmony_ci	/* for the shared_flows list maintained in l2_node */
20362306a36Sopenharmony_ci	struct list_head		l2_list_node;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	/* tunnel encap related */
20662306a36Sopenharmony_ci	struct bnxt_tc_tunnel_node	*encap_node;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	/* tunnel decap related */
20962306a36Sopenharmony_ci	struct bnxt_tc_tunnel_node	*decap_node;
21062306a36Sopenharmony_ci	/* L2 node in tunnel-l2 hashtable that shares flow's tunnel l2 key */
21162306a36Sopenharmony_ci	struct bnxt_tc_l2_node		*decap_l2_node;
21262306a36Sopenharmony_ci	/* for the shared_flows list maintained in tunnel decap l2_node */
21362306a36Sopenharmony_ci	struct list_head		decap_l2_list_node;
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci	struct rcu_head			rcu;
21662306a36Sopenharmony_ci};
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ciint bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
21962306a36Sopenharmony_ci			 struct flow_cls_offload *cls_flower);
22062306a36Sopenharmony_ciint bnxt_init_tc(struct bnxt *bp);
22162306a36Sopenharmony_civoid bnxt_shutdown_tc(struct bnxt *bp);
22262306a36Sopenharmony_civoid bnxt_tc_flow_stats_work(struct bnxt *bp);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	return bp->tc_info && bp->tc_info->enabled;
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci#else /* CONFIG_BNXT_FLOWER_OFFLOAD */
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic inline int bnxt_tc_setup_flower(struct bnxt *bp, u16 src_fid,
23262306a36Sopenharmony_ci				       struct flow_cls_offload *cls_flower)
23362306a36Sopenharmony_ci{
23462306a36Sopenharmony_ci	return -EOPNOTSUPP;
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic inline int bnxt_init_tc(struct bnxt *bp)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	return 0;
24062306a36Sopenharmony_ci}
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic inline void bnxt_shutdown_tc(struct bnxt *bp)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic inline void bnxt_tc_flow_stats_work(struct bnxt *bp)
24762306a36Sopenharmony_ci{
24862306a36Sopenharmony_ci}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic inline bool bnxt_tc_flower_enabled(struct bnxt *bp)
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	return false;
25362306a36Sopenharmony_ci}
25462306a36Sopenharmony_ci#endif /* CONFIG_BNXT_FLOWER_OFFLOAD */
25562306a36Sopenharmony_ci#endif /* BNXT_TC_H */
256