/* * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef IPA_NAT_DRVI_H #define IPA_NAT_DRVI_H #include "ipa_table.h" #include "ipa_mem_descriptor.h" #include "ipa_nat_utils.h" #undef MAKE_TBL_HDL #define MAKE_TBL_HDL(hdl, mt) \ ((mt) << 31 | (hdl)) #undef BREAK_TBL_HDL #define BREAK_TBL_HDL(hdl_in, mt, hdl_out) \ do { \ mt = (hdl_in) >> 31 & 0x0000000001; \ hdl_out = (hdl_in) & 0x00000000FF; \ } while ( 0 ) #undef VALID_TBL_HDL #define VALID_TBL_HDL(h) \ (((h) & 0x00000000FF) == IPA_NAT_MAX_IP4_TBLS) /*======= IMPLEMENTATION related data structures and functions ======= */ #define IPA_NAT_MAX_IP4_TBLS 1 #define IPA_NAT_RULE_FLAG_FIELD_OFFSET 18 #define IPA_NAT_RULE_NEXT_FIELD_OFFSET 8 #define IPA_NAT_RULE_PROTO_FIELD_OFFSET 22 #define IPA_NAT_INDEX_RULE_NEXT_FIELD_OFFSET 2 #define IPA_NAT_INDEX_RULE_NAT_INDEX_FIELD_OFFSET 0 #define IPA_NAT_FLAG_ENABLE_BIT 1 #define IPA_NAT_INVALID_PROTO_FIELD_VALUE 0xFF00 /* * IPA_NAT_INVALID_PROTO_FIELD_VALUE above is what's passed to the IPA * in a DMA command. It is written into the NAT's rule, by the * IPA. After being written, It minifests in the rule in the form * below, hence it will be used when perusing the "struct * ipa_nat_rule". */ #define IPA_NAT_INVALID_PROTO_FIELD_VALUE_IN_RULE 0xFF typedef enum { IPA_NAT_TABLE_FLAGS, IPA_NAT_TABLE_NEXT_INDEX, IPA_NAT_TABLE_PROTOCOL, IPA_NAT_INDEX_TABLE_ENTRY, IPA_NAT_INDEX_TABLE_NEXT_INDEX, IPA_NAT_TABLE_DMA_CMD_MAX } ipa_nat_table_dma_cmd_type; /* * ------------------------ NAT Table Entry ----------------------------------------- * * ------------------------------------------------------------------------------------ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | * ------------------------------------------------------------------------------------ * | Target IP(4B) | Private IP(4B) | * ------------------------------------------------------------------------------------ * |Target Port(2B) | Private Port(2B) | Public Port(2B) | Next Index(2B) | * ------------------------------------------------------------------------------------ * | Proto | TimeStamp(3B) | Flags(2B) | IP check sum Diff(2B)| * | (1B) | |EN|Redirect|Resv | | * ------------------------------------------------------------------------------------ * | TCP/UDP checksum |PDN info|Reserved | SW Specific Parameters(4B) | * | diff (2B) | (1B) | (1B) | | * ------------------------------------------------------------------------------------ * * Dont change below structure definition. * * It should be same as above(little endian order) * * ------------------------------------------------------------------------------- */ struct ipa_nat_rule { uint64_t private_ip:32; uint64_t target_ip:32; uint64_t next_index:16; uint64_t public_port:16; uint64_t private_port:16; uint64_t target_port:16; uint64_t ip_chksum:16; /*-------------------------------------------------- IPA NAT Flag is interpreted as follows --------------------------------------------------- | EN |FIN/RST| S | IPv4 uC activation index | | [15] | [14] | [13] | [12:0] | --------------------------------------------------- --------------------------------------------------*/ uint64_t uc_activation_index:13; uint64_t s:1; uint64_t redirect:1; uint64_t enable:1; uint64_t time_stamp:24; uint64_t protocol:8; /*-------------------------------------------------- 32 bit sw_spec_params is interpreted as follows ------------------------------------ | 16 bits | 16 bits | ------------------------------------ | index table | prev index | | entry | | ------------------------------------ --------------------------------------------------*/ uint64_t prev_index:16; uint64_t indx_tbl_entry:16; uint64_t rsvd2:8; /*----------------------------------------- 8 bit PDN info is interpreted as following ----------------------------------------------------- | 4 bits | 1 bit | 3 bits | ----------------------------------------------------- | PDN index | uC processing | src dst Rsrv3 | | [7:4] | [3] | [2] [1] [0] | ----------------------------------------------------- -------------------------------------------*/ uint64_t rsvd3:1; uint64_t dst_only:1; uint64_t src_only:1; uint64_t ucp:1; uint64_t pdn_index:4; uint64_t tcp_udp_chksum:16; }; static inline char* prep_nat_rule_4print( struct ipa_nat_rule* rule_ptr, char* buf_ptr, uint32_t buf_sz ) { if ( rule_ptr && buf_ptr && buf_sz ) { snprintf( buf_ptr, buf_sz, "NAT RULE: " "protocol(0x%02X) " "public_port(0x%04X) " "target_ip(0x%08X) " "target_port(0x%04X) " "private_ip(0x%08X) " "private_port(0x%04X) " "pdn_index(0x%02X) " "ip_chksum(0x%04X) " "tcp_udp_chksum(0x%04X) " "redirect(0x%02X) " "enable(0x%02X) " "time_stamp(0x%08X) " "indx_tbl_entry(0x%04X) " "prev_index(0x%04X) " "next_index(0x%04X)", rule_ptr->protocol, rule_ptr->public_port, rule_ptr->target_ip, rule_ptr->target_port, rule_ptr->private_ip, rule_ptr->private_port, rule_ptr->pdn_index, rule_ptr->ip_chksum, rule_ptr->tcp_udp_chksum, rule_ptr->redirect, rule_ptr->enable, rule_ptr->time_stamp, rule_ptr->indx_tbl_entry, rule_ptr->prev_index, rule_ptr->next_index); } return buf_ptr; } static inline const char *ipa3_nat_mem_in_as_str( enum ipa3_nat_mem_in nmi) { switch (nmi) { case IPA_NAT_MEM_IN_DDR: return "IPA_NAT_MEM_IN_DDR"; case IPA_NAT_MEM_IN_SRAM: return "IPA_NAT_MEM_IN_SRAM"; default: break; } return "???"; } static inline char *ipa_ioc_v4_nat_init_as_str( struct ipa_ioc_v4_nat_init *ptr, char *buf, uint32_t buf_sz) { if (ptr && buf && buf_sz) { snprintf( buf, buf_sz, "V4 NAT INIT: tbl_index(0x%02X) ipv4_rules_offset(0x%08X) expn_rules_offset(0x%08X) index_offset(0x%08X) index_expn_offset(0x%08X) table_entries(0x%04X) expn_table_entries(0x%04X) ip_addr(0x%08X)", ptr->tbl_index, ptr->ipv4_rules_offset, ptr->expn_rules_offset, ptr->index_offset, ptr->index_expn_offset, ptr->table_entries, ptr->expn_table_entries, ptr->ip_addr); } return buf; } /* IPA NAT Flag is interpreted as follows --------------------------------------------------- | EN |FIN/RST| S | IPv4 uC activation index | | [15] | [14] | [13] | [12:0] | --------------------------------------------------- */ typedef struct { uint32_t uc_activation_index:13; uint32_t s:1; uint32_t redirect:1; uint32_t enable:1; } ipa_nat_flags; struct ipa_nat_indx_tbl_rule { uint16_t tbl_entry; uint16_t next_index; }; struct ipa_nat_indx_tbl_meta_info { uint16_t prev_index; }; struct ipa_nat_ip4_table_cache { uint32_t public_addr; ipa_mem_descriptor mem_desc; ipa_table table; ipa_table index_table; struct ipa_nat_indx_tbl_meta_info *index_expn_table_meta; ipa_table_dma_cmd_helper table_dma_cmd_helpers[IPA_NAT_TABLE_DMA_CMD_MAX]; }; struct ipa_nat_cache { ipa_descriptor* ipa_desc; struct ipa_nat_ip4_table_cache ip4_tbl[IPA_NAT_MAX_IP4_TBLS]; uint8_t table_cnt; enum ipa3_nat_mem_in nmi; }; int ipa_nati_add_ipv4_tbl( uint32_t public_ip_addr, const char *mem_type_ptr, uint16_t number_of_entries, uint32_t *table_hanle); int ipa_nati_del_ipv4_table(uint32_t tbl_hdl); int ipa_nati_query_timestamp(uint32_t tbl_hdl, uint32_t rule_hdl, uint32_t *time_stamp); int ipa_nati_modify_pdn(struct ipa_ioc_nat_pdn_entry *entry); int ipa_nati_get_pdn_index(uint32_t public_ip, uint8_t *pdn_index); int ipa_nati_alloc_pdn(ipa_nat_pdn_entry *pdn_info, uint8_t *pdn_index); int ipa_nati_get_pdn_cnt(void); int ipa_nati_dealloc_pdn(uint8_t pdn_index); int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl, const ipa_nat_ipv4_rule *clnt_rule, uint32_t *rule_hdl); int ipa_nati_del_ipv4_rule(uint32_t tbl_hdl, uint32_t rule_hdl); int ipa_nati_get_sram_size( uint32_t* size_ptr); int ipa_nati_clear_ipv4_tbl( uint32_t tbl_hdl ); int ipa_nati_copy_ipv4_tbl( uint32_t src_tbl_hdl, uint32_t dst_tbl_hdl, ipa_table_walk_cb copy_cb ); typedef enum { USE_NAT_TABLE = 0, USE_INDEX_TABLE = 1, USE_MAX } WhichTbl2Use; #define VALID_WHICHTBL2USE(w) \ ( (w) >= USE_NAT_TABLE && (w) < USE_MAX ) int ipa_nati_walk_ipv4_tbl( uint32_t tbl_hdl, WhichTbl2Use which, ipa_table_walk_cb walk_cb, void* arb_data_ptr ); /* * The following used for retrieving table stats. */ typedef struct { enum ipa3_nat_mem_in nmi; uint32_t tot_ents; uint32_t tot_base_ents; uint32_t tot_base_ents_filled; uint32_t tot_expn_ents; uint32_t tot_expn_ents_filled; uint32_t tot_chains; uint32_t min_chain_len; uint32_t max_chain_len; float avg_chain_len; } ipa_nati_tbl_stats; int ipa_nati_ipv4_tbl_stats( uint32_t tbl_hdl, ipa_nati_tbl_stats* nat_stats_ptr, ipa_nati_tbl_stats* idx_stats_ptr ); int ipa_nati_vote_clock( enum ipa_app_clock_vote_type vote_type ); int ipa_NATI_add_ipv4_tbl( enum ipa3_nat_mem_in nmi, uint32_t public_ip_addr, uint16_t number_of_entries, uint32_t* tbl_hdl); int ipa_NATI_del_ipv4_table( uint32_t tbl_hdl); int ipa_NATI_clear_ipv4_tbl( uint32_t tbl_hdl ); int ipa_NATI_walk_ipv4_tbl( uint32_t tbl_hdl, WhichTbl2Use which, ipa_table_walk_cb walk_cb, void* arb_data_ptr ); int ipa_NATI_ipv4_tbl_stats( uint32_t tbl_hdl, ipa_nati_tbl_stats* nat_stats_ptr, ipa_nati_tbl_stats* idx_stats_ptr ); int ipa_NATI_query_timestamp( uint32_t tbl_hdl, uint32_t rule_hdl, uint32_t* time_stamp); int ipa_NATI_add_ipv4_rule( uint32_t tbl_hdl, const ipa_nat_ipv4_rule* clnt_rule, uint32_t* rule_hdl); int ipa_NATI_del_ipv4_rule( uint32_t tbl_hdl, uint32_t rule_hdl); int ipa_NATI_post_ipv4_init_cmd( uint32_t tbl_hdl ); #endif /* #ifndef IPA_NAT_DRVI_H */