blob: 58920dbbe8751284e8998b4ec55f15145299d037 [file] [log] [blame]
/*
* Copyright (c) 2009 Mindspeed Technologies, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#include "modules.h"
#include "fpp.h"
#include "fe.h"
#include "alt_conf.h"
#include "module_mc4.h"
#include "module_mc6.h"
#include "module_hidrv.h"
#if defined(COMCERTO_2000)
extern int pe_send_cmd(u16 cmd_type, u16 action, U32 param1, U32 param2);
#endif
#if !defined(COMCERTO_2000)
void update_mc_ttl_check(void)
{
}
#else
void update_mc_ttl_check(void)
{
int id;
for (id=CLASS0_ID; id <= CLASS_MAX_ID; id++) {
pe_dmem_write(id, gMC4Ctx.ttl_check_rule, virt_to_class_dmem(&gMC4Ctx.ttl_check_rule), 4);
pe_dmem_write(id, gMC6Ctx.hoplimit_check_rule, virt_to_class_dmem(&gMC6Ctx.hoplimit_check_rule), 4);
}
}
#endif
int ALTCONF_HandleCONF_SET (U16 *p, U16 Length)
{
AltConfCommandSet cmd[ALTCONF_OPTION_MAX];
int rc = NO_ERR;
int i = 0;
U16 cmd_len = 0;
// Check length
if (Length > (sizeof(cmd)*ALTCONF_OPTION_MAX))
return ERR_WRONG_COMMAND_SIZE;
// Ensure alignment
SFL_memcpy((U8*)&cmd, (U8*)p, sizeof(cmd));
while(cmd_len < Length)
{
switch(cmd[i].option_id)
{
case ALTCONF_OPTION_MCTTL:
// Check configuration value range
if(cmd[i].num_params != ALTCONF_MCTTL_NUM_PARAMS)
return ERR_ALTCONF_WRONG_NUM_PARAMS;
if(cmd[i].params[0] > ALTCONF_MCTTL_MODE_MAX)
return ERR_ALTCONF_MODE_NOT_SUPPORTED;
// update processed command length
cmd_len += (ALTCONF_MCTTL_NUM_PARAMS*sizeof(U32) + 2*sizeof(U16));
// Update MC4 MC6 context with TTL check rule
gMC4Ctx.ttl_check_rule = (U8)cmd[i].params[0];
gMC6Ctx.hoplimit_check_rule = (U8)cmd[i].params[0];
update_mc_ttl_check();
break;
#if !defined(COMCERTO_100)
/* This alternate configuration is not supported for C100 */
case ALTCONF_OPTION_IPSECRL:
// Check number of parameters. Can be 3 or 2.
if(cmd[i].num_params != ALTCONF_IPSECRL_NUM_PARAMS)
return ERR_ALTCONF_WRONG_NUM_PARAMS;
if(cmd[i].params[0] == ALTCONF_IPSECRL_ON)
{
AltConfIpsec_RateLimitEntry.enable = TRUE;
AltConfIpsec_RateLimitEntry.aggregate_bandwidth = cmd[i].params[1];
/* Tokens stored in bits per 1ms clock period = (rate * bps_PER_Kbps)/MILLISEC_PER_SEC
* bps_PER_Kbps = 1000 & MILLISEC_PER_SEC = 1000
* Hence tokens per 1ms clock period = rate */
AltConfIpsec_RateLimitEntry.tokens_per_clock_period = (cmd[i].params[1]);
AltConfIpsec_RateLimitEntry.bucket_size = cmd[i].params[2];
/* If bucket size is less than 4*tokens_per_clock_period, change bucket_size */
if(cmd[i].params[2] < AltConfIpsec_RateLimitEntry.tokens_per_clock_period * 4)
{
AltConfIpsec_RateLimitEntry.bucket_size = AltConfIpsec_RateLimitEntry.tokens_per_clock_period * 4;
}
if(AltConfIpsec_RateLimitEntry.bucket_size < ALTCONF_RX_MTU)
AltConfIpsec_RateLimitEntry.bucket_size = ALTCONF_RX_MTU;
#ifdef COMCERTO_1000
//Initially No Tokens are available. They will be accrued as clock ticks i.e every 1ms.
AltConfIpsec_RateLimitEntry.inbound_tokens_available = 0;
AltConfIpsec_RateLimitEntry.outbound_tokens_available = 0;
/* register IPSEC module to the timer service for updating tokens every 1ms */
timer_add(&ipsec_ratelimiter_timer, 1);
#endif
#if defined(COMCERTO_2000)
pe_send_cmd(CMD_ALTCONF_SET, ALTCONF_OPTION_IPSECRL, AltConfIpsec_RateLimitEntry.aggregate_bandwidth, AltConfIpsec_RateLimitEntry.bucket_size);
#endif
}
else if(cmd[i].params[0] == ALTCONF_IPSECRL_OFF)
{
AltConfIpsec_RateLimitEntry.enable = FALSE;
#ifdef COMCERTO_1000
timer_del(&ipsec_ratelimiter_timer);
#endif /* #ifdef COMCERTO_1000 */
#if defined(COMCERTO_2000)
pe_send_cmd(CMD_ALTCONF_RESET, ALTCONF_OPTION_IPSECRL, 0, 0);
#endif
}
else
return ERR_ALTCONF_MODE_NOT_SUPPORTED;
// update processed command length
cmd_len += (ALTCONF_IPSECRL_NUM_PARAMS*sizeof(U32) + 2*sizeof(U16));
break;
#endif /* #if !defined(COMCERTO_100) */
default:
return ERR_ALTCONF_OPTION_NOT_SUPPORTED;
}
}
return rc;
}
int ALTCONF_HandleCONF_RESET_ALL (U16 *p, U16 Length)
{
int rc = NO_ERR;
// Update MC4 MC6 context with TTL check rule
gMC4Ctx.ttl_check_rule = ALTCONF_MCTTL_MODE_DEFAULT;
gMC6Ctx.hoplimit_check_rule = ALTCONF_MCTTL_MODE_DEFAULT;
update_mc_ttl_check();
#if !defined(COMCERTO_100)
AltConfIpsec_RateLimitEntry.enable = FALSE;
#ifdef COMCERTO_1000
timer_del(&ipsec_ratelimiter_timer);
#endif /* #ifdef COMCERTO_1000 */
#if defined(COMCERTO_2000)
pe_send_cmd(CMD_ALTCONF_RESET, ALTCONF_OPTION_IPSECRL, 0, 0);
#endif /* #if defined(COMCERTO_2000) */
#endif /* #if !defined(COMCERTO_100) */
return rc;
}
#ifdef COMCERTO_1000
/*****************************************************************************
*Function Name : AltConfIpsec_RateLimit_token_generator
*Description: This is 1ms timer function which replenishes the tokens. For every 1 ms, it
* increments tokens_available variable by the value of pre-computed
* tokens_per_clock_period. If tokens_available value is greater than bucket_size,
* the value of tokens_available is set to bucket_size.
******************************************************************************/
void AltConfIpsec_RateLimit_token_generator(void)
{
// Updating the tokens_available value of Rate Limiting node
// Incrementing by the value of tokens_per_clock_period
AltConfIpsec_RateLimitEntry.inbound_tokens_available += AltConfIpsec_RateLimitEntry.tokens_per_clock_period;
AltConfIpsec_RateLimitEntry.outbound_tokens_available += AltConfIpsec_RateLimitEntry.tokens_per_clock_period;
// Make sure that tokens_available are not greater than the bucket size
if(AltConfIpsec_RateLimitEntry.inbound_tokens_available > AltConfIpsec_RateLimitEntry.bucket_size)
AltConfIpsec_RateLimitEntry.inbound_tokens_available = AltConfIpsec_RateLimitEntry.bucket_size;
if(AltConfIpsec_RateLimitEntry.outbound_tokens_available > AltConfIpsec_RateLimitEntry.bucket_size)
AltConfIpsec_RateLimitEntry.outbound_tokens_available = AltConfIpsec_RateLimitEntry.bucket_size;
}
/*****************************************************************************
*Function Name : AltConfIpsec_Rate_Limiter
*Description : This is the IPSEC Rate limiting function. A check is made if the packet
* can be allowed for inbound or outbound for the configured bandwidth.
* If yes, check is made if the size of the packet is
* less than the tokens_available. If it is not, FALSE is returned. If it is less,
* tokens_available is decremented by the size of the packet. TRUE is returned.
* mode: inbound/outbound
******************************************************************************/
U8 AltConfIpsec_Rate_Limiter(int mode, U32 sizeofpacket)
{
/* This function is called only when rate limiting is enabled.
* Caller will check if IPSEC Rate Limiting is enabled or not */
// Check that sizeofpacket is less than or equal to tokens_available. Also taking into account Ethernet FCS size
if(mode == ALTCONF_IPSEC_INBOUND)
{
if(AltConfIpsec_RateLimitEntry.inbound_tokens_available > 0)
{
AltConfIpsec_RateLimitEntry.inbound_tokens_available -= (sizeofpacket*ALTCONF_BITS_PER_BYTE);
return TRUE;
}
else
{
return FALSE;
}
}
else if(mode == ALTCONF_IPSEC_OUTBOUND)
{
if(AltConfIpsec_RateLimitEntry.outbound_tokens_available > 0)
{
AltConfIpsec_RateLimitEntry.outbound_tokens_available -= (sizeofpacket*ALTCONF_BITS_PER_BYTE);
return TRUE;
}
else
{
return FALSE;
}
}
return TRUE;
}
#endif /* #ifdef COMCERTO_1000 */