/*
 * Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
 * above copyright notice and this permission notice appear in all copies.
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

/**
 * @defgroup fal_flow
 * @{
 */
#ifndef _FAL_FLOW_H_
#define _FAL_FLOW_H_

#ifdef __cplusplus
extern "C" {
#endif                          /* __cplusplus */

#include "sw.h"
#include "fal/fal_type.h"
#include "fal/fal_ip.h"

typedef enum {
	FAL_FLOW_L3_UNICAST = 0,
	FAL_FLOW_L2_UNICAST,
	FAL_FLOW_MCAST,
} fal_flow_pkt_type_t;

typedef enum {
	FAL_FLOW_LAN_TO_LAN_DIR = 0,
	FAL_FLOW_LAN_TO_WAN_DIR,
	FAL_FLOW_WAN_TO_LAN_DIR,
	FAL_FLOW_WAN_TO_WAN_DIR,
	FAL_FLOW_UNKOWN_DIR_DIR,
} fal_flow_direction_t;

typedef enum {
	FAL_FLOW_FORWARD = 0,
	FAL_FLOW_SNAT,
	FAL_FLOW_DNAT,
	FAL_FLOW_ROUTE,
	FAL_FLOW_BRIDGE,
	FAL_FLOW_DROP,
	FAL_FLOW_RDT_TO_CPU,
} fal_flow_fwd_type_t;

/* FLOW entry type field */
#define FAL_FLOW_IP4_5TUPLE_ADDR        0x1
#define FAL_FLOW_IP6_5TUPLE_ADDR        0x2
#define FAL_FLOW_IP4_3TUPLE_ADDR        0x4
#define FAL_FLOW_IP6_3TUPLE_ADDR        0x8

#define FAL_FLOW_OP_MODE_KEY         0x0
#define FAL_FLOW_OP_MODE_INDEX     0x1
#define FAL_FLOW_OP_MODE_FLUSH     0x2

#define FAL_FLOW_PROTOCOL_OTHER    0
#define FAL_FLOW_PROTOCOL_TCP	        1
#define FAL_FLOW_PROTOCOL_UDP	  2
#define FAL_FLOW_PROTOCOL_UDPLITE  3

#define FAL_FLOW_PKT_CNT_MASK	0xFFFFFFFFULL
#define FAL_FLOW_BYTE_CNT_MASK	0xFFFFFFFFFFULL

#define FAL_FLOW_QOS_TYPE_TREE_ID	0
#define FAL_FLOW_QOS_TYPE_COOKIE	1
typedef struct {
	a_uint32_t tree_id; /*for qos for flow cookie */
	a_uint32_t flow_cookie_ext; /* flow_cookie_ext, added for ipq54xx */
	a_bool_t wifi_qos_en; /* enable wifi qos or not, added for ipq95xx */
	a_uint32_t wifi_qos; /* wifi qos value, added for ipq95xx */
	a_uint8_t qos_type; /* wifi qos value, added for ipq53xx */
} fal_flow_qos_t;

typedef struct {
	fal_fwd_cmd_t miss_action; /* flow mismatch action*/
	a_bool_t frag_bypass_en; /*0 for disable and 1 for enable*/
	a_bool_t tcp_spec_bypass_en; /*0 for disable and 1 for enable*/
	a_bool_t all_bypass_en; /*0 for disable and 1 for enable*/
	a_uint8_t key_sel; /*0 for source ip address and 1 for destination ip address*/
} fal_flow_mgmt_t;

typedef struct {
	a_uint32_t entry_id; /*entry index*/ 
	a_uint8_t entry_type; /*1:ipv4 5 tuple, 2:ipv6 5 tuple, 4:ipv4 3 tuple, 8:ipv6 3 tuple*/
	a_uint8_t host_addr_type; /*0:souce ip index, 1:destination ip index*/
	a_uint16_t host_addr_index; /*host table entry index*/
	a_uint8_t protocol; /*1:tcp, 2:udp, 3:udp-lite, 0:other*/
	a_uint8_t age; /*aging value*/
	a_bool_t src_intf_valid; /*source interface check valid*/
	a_uint8_t src_intf_index; /*souce l3 interface*/
	fal_flow_fwd_type_t fwd_type; /*forward type*/
	a_uint16_t snat_nexthop; /*nexthop index for snat*/
	a_uint16_t snat_srcport; /*new source l4 port*/
	a_uint16_t dnat_nexthop; /*nexthop index for dnat*/
	a_uint16_t dnat_dstport; /*new destination l4 port*/
	a_uint16_t route_nexthop; /*nexthop index for route*/
	a_bool_t port_valid; /*route port valid*/
	fal_port_t route_port; /*port for route*/
	fal_port_t bridge_port; /*port for l2 bridge*/
	a_bool_t deacclr_en; /*0 for disable and 1 for enable*/
	a_bool_t copy_tocpu_en; /*0 for disable and 1 for enable*/
	a_uint8_t syn_toggle; /*update by host*/
	a_uint8_t pri_profile; /*flow qos index*/
	a_uint8_t sevice_code; /*service code for bypass*/
	a_uint8_t ip_type; /*0 for ipv4 and 1 for ipv6*/
	union {
		fal_ip4_addr_t ipv4;
		fal_ip6_addr_t ipv6;
	} flow_ip;
	a_uint16_t src_port; /*l4 source port*/
	a_uint16_t dst_port; /*l4 destination port*/
	a_uint32_t pkt_counter; /*flow packet counter*/
	a_uint64_t byte_counter; /*flow byte counter*/
	a_bool_t pmtu_check_l3; /* compare pmtu with paket length of L3 or L2, added for ipq95xx */
	a_uint32_t pmtu; /*path mtu length, added for ipq95xx */
	a_uint32_t vpn_id; /*vpn id, added for ipq95xx */
	a_bool_t vlan_fmt_valid; /*egress with vlan format of bridge, added for ipq95xx */
	a_bool_t svlan_fmt; /*egress with svlan tag of bridge, added for ipq95xx */
	a_bool_t cvlan_fmt; /*egress with cvlan tag of bridge, added for ipq95xx */
	fal_flow_qos_t flow_qos; /* egress with wifi qos, wifi tree id or flow cookie */
	a_bool_t bridge_nexthop_valid; /*bridge nexthop valid, added for ipq53xx */
	a_uint16_t bridge_nexthop; /*nexthop index for bridge, added for ipq53xx */
	a_bool_t invalid; /* added for host data path */
	a_bool_t policer_valid; /* flow based policer valid or not, added for ipq53xx */
	a_uint32_t policer_index; /* flow based policer index, added for ipq53xx */
} fal_flow_entry_t;

typedef struct {
	fal_fwd_cmd_t src_if_check_action; /*source inferface check fail action*/
	a_bool_t src_if_check_deacclr_en; /*0 for disable and 1 for enable*/
	a_bool_t service_loop_en; /*0 for disable and 1 for enable*/
	fal_fwd_cmd_t service_loop_action; /*0 for disable and 1 for enable*/
	a_bool_t service_loop_deacclr_en; /*0 for disable and 1 for enable*/ 
	fal_fwd_cmd_t flow_deacclr_action; /*flow de acceleration action*/
	fal_fwd_cmd_t sync_mismatch_action; /*sync toggle mismatch action*/
	a_bool_t sync_mismatch_deacclr_en; /*0 for disable and 1 for enable*/
	a_uint8_t hash_mode_0; /*0 crc10, 1 xor, 2 crc16*/
	a_uint8_t hash_mode_1; /*0 crc10, 1 xor, 2 crc16*/
	a_bool_t flow_mismatch_copy_escape_en; /*0 for disable and 1 for enable*/
	fal_fwd_cmd_t ptmu_fail_action; /* mtu check fail action
					 * added for ipq95xx */
	a_bool_t ptmu_fail_deacclr_en; /* mtu check fail deaccelerate or not
					     * added for ipq95xx */
	fal_fwd_cmd_t ptmu_fail_df_action; /* mtu check fail and
					    * fragmentaion not allowed action
					    * added for ipq95xx */
	a_bool_t ptmu_fail_df_deacclr_en; /* mtu check fail and
					     * dont fragment not allowed deaccelerate or not
					     * added for ipq95xx */
	a_bool_t l2_vpn_en; /* enable vsi as flow key or not
			     * added for ipq95xx */
	a_bool_t l3_vpn_en; /* enable vrf(vpn_id configured by ip globalctrl) as flow key or not
			     * added for ipq95xx */
	a_uint8_t flow_cookie_pri; /* flow cookie priority compared with IPO, added for ipq53xx */
} fal_flow_global_cfg_t;

typedef struct {
	fal_flow_entry_t flow_entry;
	fal_host_entry_t host_entry;
} fal_flow_host_entry_t;

typedef struct {
	a_uint16_t age_time; /* age value*/
	a_uint16_t unit; /*0:second 1:cycle 2:million cycle*/
} fal_flow_age_timer_t;

typedef struct {
/*input of fal_flow_npt66_iid_cal to calculate*/
	fal_ip6_addr_t 	sip; 		//source ip, used when is_dnat is false
	fal_ip6_addr_t 	dip;	 	//destination ip, used when is_dnat is true
	fal_ip6_addr_t 	tip; 		//translated ip
	a_uint32_t 		prefix_len;	//ipv6 prefix length
	a_uint32_t 		tip_prefix_len;	//ipv6 tip prefix length
	a_bool_t 		is_dnat;	//is dnat or not
} fal_flow_npt66_iid_calc_t;

typedef struct {
/*result of fal_flow_npt66_iid_cal*/
	a_uint32_t iid_offset;
	a_uint32_t iid;
	a_bool_t   is_dnat;
} fal_flow_npt66_iid_t;


sw_error_t
fal_flow_counter_get(a_uint32_t dev_id, a_uint32_t flow_index, fal_entry_counter_t *flow_counter);

sw_error_t
fal_flow_counter_cleanup(a_uint32_t dev_id, a_uint32_t flow_index);

sw_error_t
fal_flow_entry_en_set(a_uint32_t dev_id, a_uint32_t flow_index, a_bool_t enable);

sw_error_t
fal_flow_entry_en_get(a_uint32_t dev_id, a_uint32_t flow_index, a_bool_t *enable);

sw_error_t
fal_flow_qos_set(a_uint32_t dev_id, a_uint32_t flow_index, fal_flow_qos_t *flow_qos);

sw_error_t
fal_flow_qos_get(a_uint32_t dev_id, a_uint32_t flow_index, fal_flow_qos_t *flow_qos);

sw_error_t
fal_flow_status_set(a_uint32_t dev_id, a_bool_t enable);

sw_error_t
fal_flow_status_get(a_uint32_t dev_id, a_bool_t *enable);

#if !defined(IN_FLOW_MINI)
sw_error_t
fal_flow_age_timer_set(a_uint32_t dev_id, fal_flow_age_timer_t *age_timer);

sw_error_t
fal_flow_age_timer_get(a_uint32_t dev_id, fal_flow_age_timer_t *age_timer);
#endif

sw_error_t
fal_flow_mgmt_set(
		a_uint32_t dev_id,
		fal_flow_pkt_type_t type,
		fal_flow_direction_t dir,
		fal_flow_mgmt_t *mgmt);

sw_error_t
fal_flow_mgmt_get(
		a_uint32_t dev_id,
		fal_flow_pkt_type_t type,
		fal_flow_direction_t dir,
		fal_flow_mgmt_t *mgmt);

sw_error_t
fal_flow_entry_add(
		a_uint32_t dev_id,
		a_uint32_t add_mode, /*index or hash*/
		fal_flow_entry_t *flow_entry);

sw_error_t
fal_flow_entry_del(
		a_uint32_t dev_id,
		a_uint32_t del_mode,
		fal_flow_entry_t *flow_entry);

sw_error_t
fal_flow_entry_get(
		a_uint32_t dev_id,
		a_uint32_t get_mode,
		fal_flow_entry_t *flow_entry);

sw_error_t
fal_flow_entry_next(
		a_uint32_t dev_id,
		a_uint32_t next_mode,
		fal_flow_entry_t *flow_entry);

sw_error_t
fal_flow_host_add(
		a_uint32_t dev_id,
		a_uint32_t add_mode,
		fal_flow_host_entry_t *flow_host_entry);

sw_error_t
fal_flow_host_del(
		a_uint32_t dev_id,
		a_uint32_t del_mode,
		fal_flow_host_entry_t *flow_host_entry);

sw_error_t
fal_flow_host_get(
		a_uint32_t dev_id,
		a_uint32_t get_mode,
		fal_flow_host_entry_t *flow_host_entry);

sw_error_t
fal_flow_global_cfg_get(
		a_uint32_t dev_id,
		fal_flow_global_cfg_t *cfg);

sw_error_t
fal_flow_global_cfg_set(
		a_uint32_t dev_id,
		fal_flow_global_cfg_t *cfg);

sw_error_t
fal_flow_npt66_prefix_add(a_uint32_t dev_id, a_uint32_t l3_if_index, fal_ip6_addr_t *ip6, a_uint32_t prefix_len);
sw_error_t
fal_flow_npt66_prefix_get(a_uint32_t dev_id, a_uint32_t l3_if_index, fal_ip6_addr_t *ip6, a_uint32_t *prefix_len);
sw_error_t
fal_flow_npt66_prefix_del(a_uint32_t dev_id, a_uint32_t l3_if_index);
sw_error_t
fal_flow_npt66_iid_cal(a_uint32_t dev_id, fal_flow_npt66_iid_calc_t *iid_cal, fal_flow_npt66_iid_t *iid_result);
sw_error_t
fal_flow_npt66_iid_add(a_uint32_t dev_id, a_uint32_t flow_index, fal_flow_npt66_iid_t *iid_entry);
sw_error_t
fal_flow_npt66_iid_get(a_uint32_t dev_id, a_uint32_t flow_index, fal_flow_npt66_iid_t *iid_entry);
sw_error_t
fal_flow_npt66_iid_del(a_uint32_t dev_id, a_uint32_t flow_index);
sw_error_t
fal_flow_npt66_status_get(a_uint32_t dev_id, a_bool_t *enable);
sw_error_t
fal_flow_npt66_status_set(a_uint32_t dev_id, a_bool_t enable);


#ifdef __cplusplus
}
#endif                          /* __cplusplus */
#endif                          /* _FAL_FLOW_H_ */

/**
 * @}
 */

