2013-01-04 06:05:31 +04:00
/* Copyright (C) 2009-2013 B.A.T.M.A.N. contributors:
2010-12-13 14:19:28 +03:00
*
* Marek Lindner
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation .
*
* 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 "main.h"
# include "gateway_common.h"
# include "gateway_client.h"
/* calculates the gateway class from kbit */
2012-05-12 20:33:56 +04:00
static void batadv_kbit_to_gw_bandwidth ( int down , int up , long * gw_srv_class )
2010-12-13 14:19:28 +03:00
{
int mdown = 0 , tdown , tup , difference ;
uint8_t sbit , part ;
* gw_srv_class = 0 ;
difference = 0x0FFFFFFF ;
/* test all downspeeds */
for ( sbit = 0 ; sbit < 2 ; sbit + + ) {
for ( part = 0 ; part < 16 ; part + + ) {
tdown = 32 * ( sbit + 2 ) * ( 1 < < part ) ;
if ( abs ( tdown - down ) < difference ) {
* gw_srv_class = ( sbit < < 7 ) + ( part < < 3 ) ;
difference = abs ( tdown - down ) ;
mdown = tdown ;
}
}
}
/* test all upspeeds */
difference = 0x0FFFFFFF ;
for ( part = 0 ; part < 8 ; part + + ) {
tup = ( ( part + 1 ) * ( mdown ) ) / 8 ;
if ( abs ( tup - up ) < difference ) {
* gw_srv_class = ( * gw_srv_class & 0xF8 ) | part ;
difference = abs ( tup - up ) ;
}
}
}
/* returns the up and downspeeds in kbit, calculated from the class */
2012-05-12 04:09:30 +04:00
void batadv_gw_bandwidth_to_kbit ( uint8_t gw_srv_class , int * down , int * up )
2010-12-13 14:19:28 +03:00
{
2011-06-15 11:41:37 +04:00
int sbit = ( gw_srv_class & 0x80 ) > > 7 ;
int dpart = ( gw_srv_class & 0x78 ) > > 3 ;
int upart = ( gw_srv_class & 0x07 ) ;
2010-12-13 14:19:28 +03:00
if ( ! gw_srv_class ) {
* down = 0 ;
* up = 0 ;
return ;
}
* down = 32 * ( sbit + 2 ) * ( 1 < < dpart ) ;
* up = ( ( upart + 1 ) * ( * down ) ) / 8 ;
}
2012-05-12 20:33:56 +04:00
static bool batadv_parse_gw_bandwidth ( struct net_device * net_dev , char * buff ,
int * up , int * down )
2010-12-13 14:19:28 +03:00
{
int ret , multi = 1 ;
char * slash_ptr , * tmp_ptr ;
2011-05-15 01:14:51 +04:00
long ldown , lup ;
2010-12-13 14:19:28 +03:00
slash_ptr = strchr ( buff , ' / ' ) ;
if ( slash_ptr )
* slash_ptr = 0 ;
if ( strlen ( buff ) > 4 ) {
tmp_ptr = buff + strlen ( buff ) - 4 ;
if ( strnicmp ( tmp_ptr , " mbit " , 4 ) = = 0 )
multi = 1024 ;
if ( ( strnicmp ( tmp_ptr , " kbit " , 4 ) = = 0 ) | |
2012-02-28 13:55:36 +04:00
( multi > 1 ) )
2010-12-13 14:19:28 +03:00
* tmp_ptr = ' \0 ' ;
}
2011-09-30 15:32:01 +04:00
ret = kstrtol ( buff , 10 , & ldown ) ;
2010-12-13 14:19:28 +03:00
if ( ret ) {
2012-05-16 22:23:22 +04:00
batadv_err ( net_dev ,
" Download speed of gateway mode invalid: %s \n " ,
buff ) ;
2010-12-13 14:19:28 +03:00
return false ;
}
2011-05-15 01:14:51 +04:00
* down = ldown * multi ;
2010-12-13 14:19:28 +03:00
/* we also got some upload info */
if ( slash_ptr ) {
multi = 1 ;
if ( strlen ( slash_ptr + 1 ) > 4 ) {
tmp_ptr = slash_ptr + 1 - 4 + strlen ( slash_ptr + 1 ) ;
if ( strnicmp ( tmp_ptr , " mbit " , 4 ) = = 0 )
multi = 1024 ;
if ( ( strnicmp ( tmp_ptr , " kbit " , 4 ) = = 0 ) | |
2012-02-28 13:55:36 +04:00
( multi > 1 ) )
2010-12-13 14:19:28 +03:00
* tmp_ptr = ' \0 ' ;
}
2011-09-30 15:32:01 +04:00
ret = kstrtol ( slash_ptr + 1 , 10 , & lup ) ;
2010-12-13 14:19:28 +03:00
if ( ret ) {
2012-05-16 22:23:22 +04:00
batadv_err ( net_dev ,
" Upload speed of gateway mode invalid: %s \n " ,
slash_ptr + 1 ) ;
2010-12-13 14:19:28 +03:00
return false ;
}
2011-05-15 01:14:51 +04:00
* up = lup * multi ;
2010-12-13 14:19:28 +03:00
}
return true ;
}
2012-05-12 04:09:30 +04:00
ssize_t batadv_gw_bandwidth_set ( struct net_device * net_dev , char * buff ,
size_t count )
2010-12-13 14:19:28 +03:00
{
2012-06-06 00:31:31 +04:00
struct batadv_priv * bat_priv = netdev_priv ( net_dev ) ;
2011-05-15 01:14:51 +04:00
long gw_bandwidth_tmp = 0 ;
int up = 0 , down = 0 ;
2010-12-13 14:19:28 +03:00
bool ret ;
2012-05-12 20:33:56 +04:00
ret = batadv_parse_gw_bandwidth ( net_dev , buff , & up , & down ) ;
2010-12-13 14:19:28 +03:00
if ( ! ret )
goto end ;
if ( ( ! down ) | | ( down < 256 ) )
down = 2000 ;
if ( ! up )
up = down / 5 ;
2012-05-12 20:33:56 +04:00
batadv_kbit_to_gw_bandwidth ( down , up , & gw_bandwidth_tmp ) ;
2010-12-13 14:19:28 +03:00
2012-05-12 04:09:43 +04:00
/* the gw bandwidth we guessed above might not match the given
2010-12-13 14:19:28 +03:00
* speeds , hence we need to calculate it back to show the number
* that is going to be propagated
2012-05-12 04:09:43 +04:00
*/
2012-05-12 04:09:30 +04:00
batadv_gw_bandwidth_to_kbit ( ( uint8_t ) gw_bandwidth_tmp , & down , & up ) ;
2010-12-13 14:19:28 +03:00
2012-05-11 12:10:50 +04:00
if ( atomic_read ( & bat_priv - > gw_bandwidth ) = = gw_bandwidth_tmp )
return count ;
2012-05-12 04:09:29 +04:00
batadv_gw_deselect ( bat_priv ) ;
2012-05-16 22:23:22 +04:00
batadv_info ( net_dev ,
" Changing gateway bandwidth from: '%i' to: '%ld' (propagating: %d%s/%d%s) \n " ,
atomic_read ( & bat_priv - > gw_bandwidth ) , gw_bandwidth_tmp ,
( down > 2048 ? down / 1024 : down ) ,
( down > 2048 ? " MBit " : " KBit " ) ,
( up > 2048 ? up / 1024 : up ) ,
( up > 2048 ? " MBit " : " KBit " ) ) ;
2010-12-13 14:19:28 +03:00
atomic_set ( & bat_priv - > gw_bandwidth , gw_bandwidth_tmp ) ;
end :
return count ;
}