blob: c7337da3a97c9ab26b10e9f72fedb2dcb3fe70ac [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell Commercial License Option
If you received this File from Marvell and you have entered into a commercial
license agreement (a "Commercial License") with Marvell, the File is licensed
to you under the terms of the applicable Commercial License.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
********************************************************************************
Marvell BSD License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File under the following licensing terms.
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 Marvell 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 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.
*******************************************************************************/
/*******************************************************************************
* mvNfp.h - Header File for Marvell NFP (Routing and NAT)
*
* DESCRIPTION:
* This header file contains macros, typedefs and function declarations
* specific to the Marvell Network Fast Processing (Routing and NAT).
*
* DEPENDENCIES:
* None.
*
*******************************************************************************/
#ifndef __mvNfp_h__
#define __mvNfp_h__
/* includes */
#include "mvTypes.h"
#include "mvCommon.h"
#include "mvStack.h"
#include "mv802_3.h"
#include "eth/mvEth.h"
#include "eth/gbe/mvEthGbe.h"
#include "mvSysHwConfig.h"
/* defines */
#define ETH_FP_IFINDEX_MAX 128
#define ETH_FP_PPPOE_HDR 8 /* PPP header is 6, PPPoE header is 2 */
#define ETH_FP_MTU (1518 + ETH_MV_HEADER_SIZE) /* maximum frame size incluing MH */
#define ETH_FP_PPPOE_MTU (ETH_FP_MTU - ETH_FP_PPPOE_HDR) /* maximum frame size for PPPoE */
/* uncomment to open some debug prints on adding and updating NFP rules */
#define MV_FP_DEBUG
#undef MV_FP_DEBUG
#ifdef MV_FP_DEBUG
# define MV_NFP_DBG(fmt, arg...) printk(KERN_INFO fmt, ##arg)
#else
# define MV_NFP_DBG(fmt, arg...)
#endif
#ifdef MV_FP_STATISTICS
# define MV_NFP_STAT(CODE) CODE;
#else
# define MV_NFP_STAT(CODE)
#endif
/* enumerations */
typedef enum {
MV_FP_ROUTE_CMD, /* perform NFP routing */
MV_FP_DROP_CMD, /* drop packet */
MV_FP_TO_STACK_CMD, /* pass packet to linux stack */
MV_FP_DIP_CMD, /* replace DIP */
MV_FP_SIP_CMD, /* replace SIP */
MV_FP_DPORT_CMD, /* replace DPORT */
MV_FP_SPORT_CMD, /* replace SPORT */
MV_FP_BRIDGE_CMD, /* perform fast path bridging */
MV_FP_PPP_CMD, /* perform fast path pppoe */
} MV_FP_CMD_TYPE;
typedef enum {
MV_NFP_DROP = -3,
MV_NFP_STOLEN = -2,
MV_NFP_NONE = -1,
/* positive values are valid */
} MV_NFP_IF_INDEX;
#define MV_FP_NULL_BINDING 0
#define MV_FP_NULL_BINDING_SET (1 << MV_FP_ROUTE_CMD)
#define MV_FP_DIP_CMD_MAP (1 << MV_FP_DIP_CMD)
#define MV_FP_DPORT_CMD_MAP (1 << MV_FP_DPORT_CMD)
#define MV_FP_DNAT_CMD_MAP (MV_FP_DIP_CMD_MAP | MV_FP_DPORT_CMD_MAP)
#define MV_FP_SIP_CMD_MAP (1 << MV_FP_SIP_CMD)
#define MV_FP_SPORT_CMD_MAP (1 << MV_FP_SPORT_CMD)
#define MV_FP_SNAT_CMD_MAP (MV_FP_SIP_CMD_MAP | MV_FP_SPORT_CMD_MAP)
typedef enum {
MV_FP_STATIC_RULE, /* a static rule created by the user */
MV_FP_DYNAMIC_RULE /* a dynamic rule */
} MV_FP_RULE_TYPE;
/* structure definitions (used by the NFP Manager and the NFP Database)*/
typedef struct {
MV_FP_CMD_TYPE actionType;
MV_U32 old_count;
int new_count;
MV_FP_RULE_TYPE ruleType;
int dnat_aware_refcnt;
int snat_aware_refcnt;
} MV_FP_RULE_MGMT_INFO;
typedef struct {
MV_U32 dstIp;
MV_U32 srcIp;
MV_U32 defGtwIp;
MV_U8 dscp;
MV_U8 txq;
MV_U16 reserved1;
MV_U8 reserved2;
MV_U8 aware_flags;
/* dstMac should be 2 byte aligned */
MV_U8 dstMac[MV_MAC_ADDR_SIZE];
MV_U8 srcMac[MV_MAC_ADDR_SIZE];
MV_U8 inIfIndex; /* Linux interface index */
MV_U8 outIfIndex; /* Linux interface index */
} MV_FP_RULE_ROUTING_INFO;
typedef struct _mv_fp_rule {
struct _mv_fp_rule *next;
MV_FP_RULE_MGMT_INFO mgmtInfo;
MV_FP_RULE_ROUTING_INFO routingInfo;
} MV_FP_RULE;
struct ruleHashBucket {
MV_FP_RULE *ruleChain; /* This is an entry in the rule hash table. */
/* Add additional fields (such as a lock) here if required */
};
#define MV_JHASH_MIX(a, b, c) \
{ \
a -= b; a -= c; a ^= (c>>13); \
b -= c; b -= a; b ^= (a<<8); \
c -= a; c -= b; c ^= (b>>13); \
a -= b; a -= c; a ^= (c>>12); \
b -= c; b -= a; b ^= (a<<16); \
c -= a; c -= b; c ^= (b>>5); \
a -= b; a -= c; a ^= (c>>3); \
b -= c; b -= a; b ^= (a<<10); \
c -= a; c -= b; c ^= (b>>15); \
}
/* The golden ration: an arbitrary value */
#define MV_JHASH_GOLDEN_RATIO 0x9e3779b9
extern MV_U32 fp_ip_jhash_iv;
static INLINE MV_U32 mv_jhash_3words(MV_U32 a, MV_U32 b, MV_U32 c, MV_U32 initval)
{
a += MV_JHASH_GOLDEN_RATIO;
b += MV_JHASH_GOLDEN_RATIO;
c += initval;
MV_JHASH_MIX(a, b, c);
return c;
}
#ifdef CONFIG_MV_ETH_NFP_NAT
typedef struct _mv_fp_nat_rule {
struct _mv_fp_nat_rule *next;
MV_U32 old_count;
MV_U32 new_count;
/* Original packet information */
/* Fields will contain invalid values if they are irrelevant */
MV_U32 srcIp;
MV_U32 dstIp;
MV_U16 srcPort;
MV_U16 dstPort;
MV_U8 proto;
/* NAT information */
MV_U8 flags;
MV_U32 newIp;
MV_U16 newPort;
} MV_FP_NAT_RULE;
struct natRuleHashBucket {
MV_FP_NAT_RULE *natRuleChain; /* This is an entry in the NAT rule hash table. */
/* Add additional fields (such as a lock) here if required */
};
extern struct natRuleHashBucket *natRuleDb;
extern MV_U32 natRuleDbSize;
extern MV_U32 natRuleUpdateCount, natRuleSetCount, natRuleDeleteCount;
extern MV_U32 natHashMaxDepth;
#endif /* CONFIG_MV_ETH_NFP_NAT */
/*
* PPPoE Support
*/
#ifdef CONFIG_MV_ETH_NFP_PPP
typedef struct {
MV_U16 tag;
MV_U8 da[MV_MAC_ADDR_SIZE];
MV_U8 sa[MV_MAC_ADDR_SIZE];
MV_U16 ethertype;
MV_U8 version;
MV_U8 code;
MV_U16 session;
MV_U16 len;
MV_U16 proto;
} __attribute__ ((packed)) MV_PPPoE_HEADER;
typedef struct {
union {
MV_PPPoE_HEADER ppp;
MV_U32 u32[6];
} u;
MV_U32 if_ppp; /* e.g. ppp0 */
MV_U32 if_eth; /* e.g. eth0 */
MV_U32 channel;
} MV_FP_RULE_PPP_INFO;
typedef struct _mv_fp_ppp_rule {
struct _mv_fp_ppp_rule *next;
MV_FP_RULE_MGMT_INFO mgmtInfo;
MV_FP_RULE_PPP_INFO pppInfo;
} MV_FP_PPP_RULE;
extern MV_FP_PPP_RULE pppOpen[];
#endif /* CONFIG_MV_ETH_NFP_PPP */
/*
* 802.1D Support
*/
#ifdef CONFIG_MV_ETH_NFP_FDB
#define MV_FP_FDB_IS_LOCAL 1
typedef struct {
MV_U16 flags;
MV_U8 mac[6];
MV_U32 ifIndex;
MV_U32 bridge;
} MV_FP_RULE_FDB_INFO;
typedef struct _mv_fp_fdb_rule {
struct _mv_fp_fdb_rule *next;
MV_FP_RULE_MGMT_INFO mgmtInfo;
MV_FP_RULE_FDB_INFO fdbInfo;
} MV_FP_FDB_RULE;
struct fdbRuleHashBucket {
MV_FP_FDB_RULE *ruleChain;
};
extern struct fdbRuleHashBucket *fdbRuleDb;
extern MV_U32 fdbRuleDbSize;
extern MV_U32 fdbMember[];
extern MV_U32 fdbRuleUpdateCount, fdbRuleSetCount, fdbRuleDeleteCount;
extern MV_U32 fdbHashMaxDepth;
#endif /* CONFIG_MV_ETH_NFP_FDB */
typedef struct {
MV_U32 parsing;
MV_U32 process;
MV_U32 route_miss;
MV_U32 route_hit;
MV_U32 ip_ttl_expired;
MV_U32 slowpath;
MV_U32 multicast;
MV_U32 ethertype_unknown;
MV_U32 ip_frag;
MV_U32 vlan_tagged;
#ifdef CONFIG_MV_ETH_NFP_NAT
MV_U32 nat_bad_proto;
MV_U32 dnat_aware;
MV_U32 snat_aware;
MV_U32 dnat_found;
MV_U32 snat_found;
MV_U32 dnat_not_found;
MV_U32 snat_not_found;
#endif /* CONFIG_MV_ETH_NFP_NAT */
#ifdef CONFIG_MV_ETH_NFP_FDB
MV_U32 fdb_rx_local;
MV_U32 fdb_rx_unknown;
MV_U32 fdb_tx_found;
MV_U32 fdb_bridged;
#endif /* CONFIG_MV_ETH_NFP_FDB */
#ifdef CONFIG_MV_ETH_NFP_PPP
MV_U32 ppp_rx;
MV_U32 ppp_rx_slow;
MV_U32 ppp_rx_frag;
MV_U32 ppp_tx;
MV_U32 ppp_tx_slow;
MV_U32 ppp_tx_esp;
MV_U32 ppp_err;
#endif /* CONFIG_MV_ETH_NFP_PPP */
#ifdef CONFIG_MV_ETH_NFP_SEC
MV_U32 sec_in;
MV_U32 sec_in_drop;
MV_U32 sec_out;
MV_U32 sec_out_drop;
MV_U32 sec_out_slow;
#endif /* CONFIG_MV_ETH_NFP_SEC */
} MV_FP_STATS;
static INLINE MV_IP_HEADER *mvFpParsing(MV_PKT_INFO *pPktInfo, MV_FP_STATS *pFpStats)
{
MV_U8 *pData;
MV_IP_HEADER *pIpHdr;
MV_U32 tx_status;
pData = (MV_U8 *) pPktInfo->pFrags[0].bufVirtPtr + ETH_MV_HEADER_SIZE;
MV_NFP_STAT(pFpStats->parsing++);
/* Check LLC/SNAP and IP header */
if (((pPktInfo->status & ETH_RX_NOT_LLC_SNAP_FORMAT_MASK) == 0) ||
((pPktInfo->status & ETH_RX_IP_HEADER_OK_MASK) == 0)) {
/* Non IP packet: go to Linux IP stack */
MV_NFP_STAT(pFpStats->ethertype_unknown++);
return NULL;
}
if (pPktInfo->fragIP) {
MV_NFP_STAT(pFpStats->ip_frag++);
return NULL;
}
tx_status = (ETH_TX_GENERATE_IP_CHKSUM_MASK | ETH_TX_IP_NO_FRAG | (5 << ETH_TX_IP_HEADER_LEN_OFFSET));
/* Calculate start of IP header */
if ((pPktInfo->status & ETH_RX_VLAN_TAGGED_FRAME_MASK)) {
MV_NFP_STAT(pFpStats->vlan_tagged++);
pIpHdr = (MV_IP_HEADER *) (pData + sizeof(MV_802_3_HEADER) + MV_VLAN_HLEN);
tx_status |= ETH_TX_VLAN_TAGGED_FRAME_MASK;
} else {
pIpHdr = (MV_IP_HEADER *) (pData + sizeof(MV_802_3_HEADER));
}
if ((pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_TCP_TYPE)
tx_status |= (ETH_TX_L4_TCP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK);
else if ((pPktInfo->status & ETH_RX_L4_TYPE_MASK) == ETH_RX_L4_UDP_TYPE)
tx_status |= (ETH_TX_L4_UDP_TYPE | ETH_TX_GENERATE_L4_CHKSUM_MASK);
pPktInfo->status = tx_status;
return pIpHdr;
}
/* Initialize NFP Rule Database (Routing + ARP information table) */
MV_STATUS mvFpRuleDbInit(MV_U32 dbSize);
/* Clear NFP Rule Database (Routing + ARP information table) */
MV_STATUS mvFpRuleDbClear(void);
/* Free Rule Database memory */
void mvFpRuleDbDestroy(void);
/* Print NFP Rule Database (Routing + ARP information table) */
MV_STATUS mvFpRuleDbPrint(void);
/* Copy all the information from src_rule to new_rule */
/* Warning - doesn't perform any checks on memory, just copies */
/* count is set to zero in new_rule */
/* Note: the next pointer is not updated . */
void mvFpRuleCopy(MV_FP_RULE *newRule, const MV_FP_RULE *srcRule);
/* Get the maximum count value for a rule with srcIp == given ip */
MV_U32 mvFpMaxArpCountGet(MV_U32 ip);
/* Get the count value for a rule that matches the given SIP, DIP */
MV_U32 mvFpRouteCountGet(MV_U32 srcIp, MV_U32 dstIp);
/* Set a Routing Rule: create a new rule or update an existing rule */
/* in the Routing + ARP information table */
MV_STATUS mvFpRuleSet(MV_FP_RULE *rule);
/* Delete a specified rule from the Routing + ARP information table */
MV_STATUS mvFpRuleDelete(MV_FP_RULE *rule);
/* Set a Routing ToS Rule */
MV_STATUS mvFpToSSet(MV_FP_RULE *rule);
/* Print a Rule */
void mvFpRulePrint(const MV_FP_RULE *rule);
/* Enable NFP */
void mvFpEnable(void);
/* Give all packets to Linux IP stack */
void mvFpDisable(void);
MV_STATUS mvFpInit(void);
int mvFpProcess(MV_U32 ifIndex, MV_PKT_INFO *pPkt, MV_IP_HEADER *pIpHdr, MV_FP_STATS *pFpStats);
void mvFpStatsPrint(MV_FP_STATS *pFpStats);
/* NAT SUPPORT Functions */
#ifdef CONFIG_MV_ETH_NFP_NAT
/* Find and return the first matching rule */
static INLINE MV_FP_NAT_RULE *mvFpNatRuleFind(MV_U32 dstIp, MV_U32 srcIp, MV_U8 proto, MV_U16 dport, MV_U16 sport)
{
MV_U32 hash, hash_tr;
MV_FP_NAT_RULE *pNatRule;
int count = 0;
hash = mv_jhash_3words(dstIp, srcIp, (MV_U32) ((dport << 16) | sport),
(MV_U32) ((fp_ip_jhash_iv << 8) | proto));
hash_tr = hash & (natRuleDbSize - 1);
/*
mvOsPrintf("mvFpNatRuleFind: DIP=0x%08x, SIP=0x%08x, proto=%d, DPort=%d, SPort=%d, hash=0x%08x (0x%x)\n",
dstIp, srcIp, proto, dport, sport, hash, hash_tr);
*/
pNatRule = natRuleDb[hash_tr].natRuleChain;
while (pNatRule) {
/* look for a matching rule */
if ((pNatRule->dstIp == dstIp) &&
(pNatRule->srcIp == srcIp) &&
(pNatRule->proto == proto) && (pNatRule->dstPort == dport) && (pNatRule->srcPort == sport)) {
pNatRule->new_count++;
return pNatRule;
}
pNatRule = pNatRule->next;
count++;
}
return NULL;
}
/* Initialize NFP NAT Rule Database (SNAT + DNAT table) */
MV_STATUS mvFpNatDbInit(MV_U32 dbSize);
/* Clear NFP NAT Rule Database (SNAT + DNAT table) */
MV_STATUS mvFpNatDbClear(void);
/* Free NAT Database memory */
void mvFpNatDbDestroy(void);
/* Set a NAT rule: create a new rule or update an existing rule in the SNAT + DNAT table */
MV_STATUS mvFpNatRuleSet(MV_FP_NAT_RULE *natRule);
MV_STATUS mvFpRuleAwareSet(MV_FP_RULE *pSetRule);
/* Delete a specified NAT rule from the SNAT + DNAT table */
MV_STATUS mvFpNatRuleDelete(MV_FP_NAT_RULE *natRule);
/* Get the count value for a NAT rule */
MV_U32 mvFpNatCountGet(MV_U32 srcIp, MV_U32 dstIp, MV_U16 srcPort, MV_U16 dstPort, MV_U8 proto);
/* Print NFP NAT Rule Database (SNAT + DNAT table) */
MV_STATUS mvFpNatDbPrint(void);
/* Print a NAT Rule */
void mvFpNatRulePrint(const MV_FP_NAT_RULE *rule);
/* Extract dstPort and srcPort values from the packet */
MV_U8 mvFpNatPortsGet(MV_IP_HEADER *pIpHdr, MV_U16 *pDstPort, MV_U16 *pSrcPort);
int mvFpNatPktUpdate(MV_IP_HEADER *pIpHdr, MV_FP_NAT_RULE *pDnatRule, MV_FP_NAT_RULE *pSnatRule);
#endif /* CONFIG_MV_ETH_NFP_NAT */
#ifdef CONFIG_MV_ETH_NFP_FDB
/* Init NFP Bridge Rule Database */
MV_STATUS mvFpFdbInit(MV_U32 dbSize);
/* Clear NFP Bridge Rule Database */
MV_STATUS mvFpFdbClear(void);
/* Destroy NFP Bridge Rule Database */
void mvFpFdbDestroy(void);
/* Add NFP Bridge Rule */
MV_STATUS mvFpFdbRuleSet(MV_FP_FDB_RULE *rule);
/* Delete NFP Bridge Rule Database */
MV_STATUS mvFpFdbRuleDel(MV_FP_FDB_RULE *rule);
/* Aging NFP Bridge Rule Database */
MV_U32 mvFpFdbRuleAge(MV_FP_FDB_RULE *rule);
/* Print NFP Bridge Rule Database */
MV_STATUS mvFpFdbPrint(void);
#endif /* CONFIG_MV_ETH_NFP_FDB */
#ifdef CONFIG_MV_ETH_NFP_PPP
/* Init NFP PPPoE Rule Database */
MV_STATUS mvFpPppInit(void);
/* Clear NFP PPPoE Rule Database */
MV_STATUS mvFpPppClear(void);
/* Destroy NFP PPPoE Rule Database */
void mvFpPppDestroy(void);
/* Add NFP PPPoE Rule */
MV_STATUS mvFpPppRuleSet(MV_FP_PPP_RULE *rule);
/* Delete NFP PPPoE Rule Database */
MV_STATUS mvFpPppRuleDel(MV_FP_PPP_RULE *rule);
/* Aging NFP PPPoE Rule Database */
MV_U32 mvFpPppRuleAge(MV_FP_PPP_RULE *rule);
/* Print NFP PPPoE Rule Database */
MV_STATUS mvFpPppPrint(void);
/* Add PPPoE header */
int mvFpPPPoE(MV_U32 ifIndex, MV_PKT_INFO *pPkt, MV_FP_STATS *pFpStats);
/* Get physical interface the PPP runs over */
MV_U32 mvFpPppPhyIf(MV_U32 ifIndex);
#endif /* CONFIG_MV_ETH_NFP_PPP */
#ifdef CONFIG_MV_ETH_NFP_SEC
MV_VOID mvNfpSecDbPrint(MV_VOID);
#endif /* CONFIG_MV_ETH_NFP_SEC */
#endif /* __mvNfp_h__ */