blob: 261583bb54f29e43f0be498284e7c4ce15383a87 [file] [log] [blame]
/*
* 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 */