/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ /* Copyright (C) 2021 Corigine, Inc. */ #ifndef __NFP_FLOWER_CONNTRACK_H__ #define __NFP_FLOWER_CONNTRACK_H__ 1 #include <net/netfilter/nf_flow_table.h> #include "main.h" #define NFP_FL_CT_NO_TUN 0xff #define COMPARE_UNMASKED_FIELDS(__match1, __match2, __out) \ do { \ typeof(__match1) _match1 = (__match1); \ typeof(__match2) _match2 = (__match2); \ bool *_out = (__out); \ int i, size = sizeof(*(_match1).key); \ char *k1, *m1, *k2, *m2; \ *_out = false; \ k1 = (char *)_match1.key; \ m1 = (char *)_match1.mask; \ k2 = (char *)_match2.key; \ m2 = (char *)_match2.mask; \ for (i = 0; i < size; i++) \ if ((k1[i] & m1[i] & m2[i]) ^ \ (k2[i] & m1[i] & m2[i])) { \ *_out = true; \ break; \ } \ } while (0) \ extern const struct rhashtable_params nfp_zone_table_params; extern const struct rhashtable_params nfp_ct_map_params; extern const struct rhashtable_params nfp_tc_ct_merge_params; extern const struct rhashtable_params nfp_nft_ct_merge_params; /** * struct nfp_fl_ct_zone_entry - Zone entry containing conntrack flow information * @zone: The zone number, used as lookup key in hashtable * @hash_node: Used by the hashtable * @priv: Pointer to nfp_flower_priv data * @nft: Pointer to nf_flowtable for this zone * * @pre_ct_list: The pre_ct_list of nfp_fl_ct_flow_entry entries * @pre_ct_count: Keep count of the number of pre_ct entries * * @post_ct_list: The post_ct_list of nfp_fl_ct_flow_entry entries * @post_ct_count: Keep count of the number of post_ct entries * * @tc_merge_tb: The table of merged tc flows * @tc_merge_count: Keep count of the number of merged tc entries * * @nft_flows_list: The list of nft relatednfp_fl_ct_flow_entry entries * @nft_flows_count: Keep count of the number of nft_flow entries * * @nft_merge_tb: The table of merged tc+nft flows * @nft_merge_count: Keep count of the number of merged tc+nft entries */ struct nfp_fl_ct_zone_entry { u16 zone; struct rhash_head hash_node; struct nfp_flower_priv *priv; struct nf_flowtable *nft; struct list_head pre_ct_list; unsigned int pre_ct_count; struct list_head post_ct_list; unsigned int post_ct_count; struct rhashtable tc_merge_tb; unsigned int tc_merge_count; struct list_head nft_flows_list; unsigned int nft_flows_count; struct rhashtable nft_merge_tb; unsigned int nft_merge_count; }; enum ct_entry_type { CT_TYPE_PRE_CT, CT_TYPE_NFT, CT_TYPE_POST_CT, _CT_TYPE_MAX, }; #define NFP_MAX_RECIRC_CT_ZONES 4 #define NFP_MAX_ENTRY_RULES (NFP_MAX_RECIRC_CT_ZONES * 2 + 1) enum nfp_nfp_layer_name { FLOW_PAY_META_TCI = 0, FLOW_PAY_INPORT, FLOW_PAY_EXT_META, FLOW_PAY_MAC_MPLS, FLOW_PAY_L4, FLOW_PAY_IPV4, FLOW_PAY_IPV6, FLOW_PAY_CT, FLOW_PAY_GRE, FLOW_PAY_QINQ, FLOW_PAY_UDP_TUN, FLOW_PAY_GENEVE_OPT, _FLOW_PAY_LAYERS_MAX }; /* NFP flow entry flags. */ #define NFP_FL_ACTION_DO_NAT BIT(0) #define NFP_FL_ACTION_DO_MANGLE BIT(1) /** * struct nfp_fl_ct_flow_entry - Flow entry containing conntrack flow information * @cookie: Flow cookie, same as original TC flow, used as key * @list_node: Used by the list * @chain_index: Chain index of the original flow * @goto_chain_index: goto chain index of the flow * @netdev: netdev structure. * @zt: Reference to the zone table this belongs to * @children: List of tc_merge flows this flow forms part of * @rule: Reference to the original TC flow rule * @stats: Used to cache stats for updating * @prev_m_entries: Array of all previous nft_tc_merge entries * @num_prev_m_entries: The number of all previous nft_tc_merge entries * @tun_offset: Used to indicate tunnel action offset in action list * @flags: Used to indicate flow flag like NAT which used by merge. * @type: Type of ct-entry from enum ct_entry_type */ struct nfp_fl_ct_flow_entry { unsigned long cookie; struct list_head list_node; u32 chain_index; u32 goto_chain_index; struct net_device *netdev; struct nfp_fl_ct_zone_entry *zt; struct list_head children; struct flow_rule *rule; struct flow_stats stats; struct nfp_fl_nft_tc_merge *prev_m_entries[NFP_MAX_RECIRC_CT_ZONES - 1]; u8 num_prev_m_entries; u8 tun_offset; // Set to NFP_FL_CT_NO_TUN if no tun u8 flags; u8 type; }; /** * struct nfp_fl_ct_tc_merge - Merge of two flows from tc * @cookie: Flow cookie, combination of pre and post ct cookies * @hash_node: Used by the hashtable * @pre_ct_list: This entry is part of a pre_ct_list * @post_ct_list: This entry is part of a post_ct_list * @zt: Reference to the zone table this belongs to * @pre_ct_parent: The pre_ct_parent * @post_ct_parent: The post_ct_parent * @children: List of nft merged entries */ struct nfp_fl_ct_tc_merge { unsigned long cookie[2]; struct rhash_head hash_node; struct list_head pre_ct_list; struct list_head post_ct_list; struct nfp_fl_ct_zone_entry *zt; struct nfp_fl_ct_flow_entry *pre_ct_parent; struct nfp_fl_ct_flow_entry *post_ct_parent; struct list_head children; }; /** * struct nfp_fl_nft_tc_merge - Merge of tc_merge flows with nft flow * @netdev: Ingress netdev name * @cookie: Flow cookie, combination of tc_merge and nft cookies * @hash_node: Used by the hashtable * @zt: Reference to the zone table this belongs to * @nft_flow_list: This entry is part of a nft_flows_list * @tc_merge_list: This entry is part of a ct_merge_list * @tc_m_parent: The tc_merge parent * @nft_parent: The nft_entry parent * @tc_flower_cookie: The cookie of the flow offloaded to the nfp * @flow_pay: Reference to the offloaded flow struct * @next_pre_ct_entry: Reference to the next ct zone pre ct entry */ struct nfp_fl_nft_tc_merge { struct net_device *netdev; unsigned long cookie[3]; struct rhash_head hash_node; struct nfp_fl_ct_zone_entry *zt; struct list_head nft_flow_list; struct list_head tc_merge_list; struct nfp_fl_ct_tc_merge *tc_m_parent; struct nfp_fl_ct_flow_entry *nft_parent; unsigned long tc_flower_cookie; struct nfp_fl_payload *flow_pay; struct nfp_fl_ct_flow_entry *next_pre_ct_entry; }; /** * struct nfp_fl_ct_map_entry - Map between flow cookie and specific ct_flow * @cookie: Flow cookie, same as original TC flow, used as key * @hash_node: Used by the hashtable * @ct_entry: Pointer to corresponding ct_entry */ struct nfp_fl_ct_map_entry { unsigned long cookie; struct rhash_head hash_node; struct nfp_fl_ct_flow_entry *ct_entry; }; bool is_pre_ct_flow(struct flow_cls_offload *flow); bool is_post_ct_flow(struct flow_cls_offload *flow); /** * nfp_fl_ct_handle_pre_ct() - Handles -trk conntrack rules * @priv: Pointer to app priv * @netdev: netdev structure. * @flow: TC flower classifier offload structure. * @extack: Extack pointer for errors * @m_entry:previous nfp_fl_nft_tc_merge entry * * Adds a new entry to the relevant zone table and tries to * merge with other +trk+est entries and offload if possible. * * Return: negative value on error, 0 if configured successfully. */ int nfp_fl_ct_handle_pre_ct(struct nfp_flower_priv *priv, struct net_device *netdev, struct flow_cls_offload *flow, struct netlink_ext_ack *extack, struct nfp_fl_nft_tc_merge *m_entry); /** * nfp_fl_ct_handle_post_ct() - Handles +trk+est conntrack rules * @priv: Pointer to app priv * @netdev: netdev structure. * @flow: TC flower classifier offload structure. * @extack: Extack pointer for errors * * Adds a new entry to the relevant zone table and tries to * merge with other -trk entries and offload if possible. * * Return: negative value on error, 0 if configured successfully. */ int nfp_fl_ct_handle_post_ct(struct nfp_flower_priv *priv, struct net_device *netdev, struct flow_cls_offload *flow, struct netlink_ext_ack *extack); /** * nfp_fl_create_new_pre_ct() - create next ct_zone -trk conntrack rules * @m_entry:previous nfp_fl_nft_tc_merge entry * * Create a new pre_ct entry from previous nfp_fl_nft_tc_merge entry * to the next relevant zone table. Try to merge with other +trk+est * entries and offload if possible. The created new pre_ct entry is * linked to the previous nfp_fl_nft_tc_merge entry. * * Return: negative value on error, 0 if configured successfully. */ int nfp_fl_create_new_pre_ct(struct nfp_fl_nft_tc_merge *m_entry); /** * nfp_fl_ct_clean_flow_entry() - Free a nfp_fl_ct_flow_entry * @entry: Flow entry to cleanup */ void nfp_fl_ct_clean_flow_entry(struct nfp_fl_ct_flow_entry *entry); /** * nfp_fl_ct_del_flow() - Handle flow_del callbacks for conntrack * @ct_map_ent: ct map entry for the flow that needs deleting */ int nfp_fl_ct_del_flow(struct nfp_fl_ct_map_entry *ct_map_ent); /** * nfp_fl_ct_handle_nft_flow() - Handle flower flow callbacks for nft table * @type: Type provided by callback * @type_data: Callback data * @cb_priv: Pointer to data provided when registering the callback, in this * case it's the zone table. */ int nfp_fl_ct_handle_nft_flow(enum tc_setup_type type, void *type_data, void *cb_priv); /** * nfp_fl_ct_stats() - Handle flower stats callbacks for ct flows * @flow: TC flower classifier offload structure. * @ct_map_ent: ct map entry for the flow that needs deleting */ int nfp_fl_ct_stats(struct flow_cls_offload *flow, struct nfp_fl_ct_map_entry *ct_map_ent); #endif