Mini Shell
'''
cake
++++
Usage:
# Imports
from pyroute2 import IPRoute
# Add cake with 2048kbit of bandwidth capacity
with IPRoute() as ipr:
# Get interface index
index = ipr.link_lookup(ifname='lo')
ipr.tc('add', kind='cake', index=index, bandwidth='2048kbit')
# Same with 15mbit of bandwidth capacity
with IPRoute() as ipr:
# Get interface index
index = ipr.link_lookup(ifname='lo')
ipr.tc('add', kind='cake', index=index, bandwidth='15mbit')
# If you don't know the bandwidth capacity, use autorate
with IPRoute() as ipr:
# Get interface index
index = ipr.link_lookup(ifname='lo')
ipr.tc('add', kind='cake', index=index, bandwidth='unlimited',
autorate=True)
# If you want to tune ATM properties use:
# atm_mode=False # For no ATM tuning
# atm_mode=True # For ADSL tuning
# atm_mode='ptm' # For VDSL2 tuning
with IPRoute() as ipr:
# Get interface index
index = ipr.link_lookup(ifname='lo')
ipr.tc('add', kind='cake', index=index, bandwidth='unlimited',
autorate=True, atm_mode=True)
# Complex example which has no-sense
with IPRoute() as ipr:
# Get interface index
index = ipr.link_lookup(ifname='lo')
ipr.tc('add', kind='cake', index=index, bandwidth='unlimited',
autorate=True, nat=True, rtt='interplanetary', target=10000,
flow_mode='dsthost', diffserv_mode='precedence', fwmark=0x1337)
NOTES:
Here is the list of all supported options with their values:
- ack_filter: False, True or 'aggressive' (False by default)
- atm_mode: False, True or 'ptm' (False by default)
- autorate: False or True (False by default)
- bandwidth: any integer, 'N[kbit|mbit|gbit]' or 'unlimited'
- diffserv_mode: 'diffserv3', 'diffserv4', 'diffserv8',
'besteffort', 'precedence' ('diffserv3' by default)
- ingress: False or True (False by default)
- overhead: any integer between -64 and 256 inclusive (0 by default)
- flow_mode: 'flowblind', 'srchost', 'dsthost', 'hosts', 'flows',
'dual-srchost', 'dual-dsthost', 'triple-isolate'
('triple-isolate' by default)
- fwmark: any integer (0 by default)
- memlimit: any integer (by default, calculated based on the bandwidth
and RTT settings)
- mpu: any integer between 0 and 256 inclusive (0 by default)
- nat: False or True (False by default)
- raw: False or True (True by default)
- rtt: any integer or 'datacentre', 'lan', 'metro', 'regional',
'internet', 'oceanic', 'satellite', 'interplanetary'
('internet' by default)
- split_gso: False or True (True by default)
- target: any integer (5000 by default)
- wash: False or True (False by default)
'''
from pyroute2.netlink import nla
from pyroute2.netlink.rtnl import TC_H_ROOT
# Defines from pkt_sched.h
CAKE_FLOW_NONE = 0
CAKE_FLOW_SRC_IP = 1
CAKE_FLOW_DST_IP = 2
CAKE_FLOW_HOSTS = 3
CAKE_FLOW_FLOWS = 4
CAKE_FLOW_DUAL_SRC = 5
CAKE_FLOW_DUAL_DST = 6
CAKE_FLOW_TRIPLE = 7
CAKE_DIFFSERV_DIFFSERV3 = 0
CAKE_DIFFSERV_DIFFSERV4 = 1
CAKE_DIFFSERV_DIFFSERV8 = 2
CAKE_DIFFSERV_BESTEFFORT = 3
CAKE_DIFFSERV_PRECEDENCE = 4
CAKE_ACK_NONE = 0
CAKE_ACK_FILTER = 1
CAKE_ACK_AGGRESSIVE = 2
CAKE_ATM_NONE = 0
CAKE_ATM_ATM = 1
CAKE_ATM_PTM = 2
TCA_CAKE_MAX_TINS = 8
def fix_msg(msg, kwarg):
if 'parent' not in kwarg:
msg['parent'] = TC_H_ROOT
def convert_bandwidth(value):
types = [('kbit', 1000), ('mbit', 1000000), ('gbit', 1000000000)]
if 'unlimited' == value:
return 0
try:
# Value is passed as an int
x = int(value)
return x >> 3
except ValueError:
value = value.lower()
for t, mul in types:
if len(value.split(t)) == 2:
x = int(value.split(t)[0]) * mul
return x >> 3
raise ValueError(
'Invalid bandwidth value. Specify either an integer, '
'"unlimited" or a value with "kbit", "mbit" or '
'"gbit" appended'
)
def convert_rtt(value):
types = {
'datacentre': 100,
'lan': 1000,
'metro': 10000,
'regional': 30000,
'internet': 100000,
'oceanic': 300000,
'satellite': 1000000,
'interplanetary': 3600000000,
}
try:
# Value is passed as an int
x = int(value)
return x
except ValueError:
rtt = types.get(value.lower())
if rtt is not None:
return rtt
raise ValueError(
'Invalid rtt value. Specify either an integer (us), '
'or datacentre, lan, metro, regional, internet, '
'oceanic or interplanetary.'
)
def convert_atm(value):
if isinstance(value, bool):
if not value:
return CAKE_ATM_NONE
else:
return CAKE_ATM_ATM
else:
if value == 'ptm':
return CAKE_ATM_PTM
raise ValueError('Invalid ATM value!')
def convert_flowmode(value):
modes = {
'flowblind': CAKE_FLOW_NONE,
'srchost': CAKE_FLOW_SRC_IP,
'dsthost': CAKE_FLOW_DST_IP,
'hosts': CAKE_FLOW_HOSTS,
'flows': CAKE_FLOW_FLOWS,
'dual-srchost': CAKE_FLOW_DUAL_SRC,
'dual-dsthost': CAKE_FLOW_DUAL_DST,
'triple-isolate': CAKE_FLOW_TRIPLE,
}
res = modes.get(value.lower())
if res:
return res
raise ValueError(
'Invalid flow mode specified! See tc-cake man '
'page for valid values.'
)
def convert_diffserv(value):
modes = {
'diffserv3': CAKE_DIFFSERV_DIFFSERV3,
'diffserv4': CAKE_DIFFSERV_DIFFSERV4,
'diffserv8': CAKE_DIFFSERV_DIFFSERV8,
'besteffort': CAKE_DIFFSERV_BESTEFFORT,
'precedence': CAKE_DIFFSERV_PRECEDENCE,
}
res = modes.get(value.lower())
if res is not None:
return res
raise ValueError(
'Invalid diffserv mode specified! See tc-cake man '
'page for valid values.'
)
def convert_ackfilter(value):
if isinstance(value, bool):
if not value:
return CAKE_ACK_NONE
else:
return CAKE_ACK_FILTER
else:
if value == 'aggressive':
return CAKE_ACK_AGGRESSIVE
raise ValueError('Invalid ACK filter!')
def check_range(name, value, start, end):
if not isinstance(value, int):
raise ValueError('{} value must be an integer'.format(name))
if not start <= value <= end:
raise ValueError(
'{0} value must be between {1} and {2} '
'inclusive.'.format(name, start, end)
)
def get_parameters(kwarg):
ret = {'attrs': []}
attrs_map = (
('ack_filter', 'TCA_CAKE_ACK_FILTER'),
('atm_mode', 'TCA_CAKE_ATM'),
('autorate', 'TCA_CAKE_AUTORATE'),
('bandwidth', 'TCA_CAKE_BASE_RATE64'),
('diffserv_mode', 'TCA_CAKE_DIFFSERV_MODE'),
('ingress', 'TCA_CAKE_INGRESS'),
('overhead', 'TCA_CAKE_OVERHEAD'),
('flow_mode', 'TCA_CAKE_FLOW_MODE'),
('fwmark', 'TCA_CAKE_FWMARK'),
('memlimit', 'TCA_CAKE_MEMORY'),
('mpu', 'TCA_CAKE_MPU'),
('nat', 'TCA_CAKE_NAT'),
('raw', 'TCA_CAKE_RAW'),
('rtt', 'TCA_CAKE_RTT'),
('split_gso', 'TCA_CAKE_SPLIT_GSO'),
('target', 'TCA_CAKE_TARGET'),
('wash', 'TCA_CAKE_WASH'),
)
for k, v in attrs_map:
r = kwarg.get(k, None)
if r is not None:
if k == 'bandwidth':
r = convert_bandwidth(r)
elif k == 'rtt':
r = convert_rtt(r)
elif k == 'atm_mode':
r = convert_atm(r)
elif k == 'flow_mode':
r = convert_flowmode(r)
elif k == 'diffserv_mode':
r = convert_diffserv(r)
elif k == 'ack_filter':
r = convert_ackfilter(r)
elif k == 'mpu':
check_range(k, r, 0, 256)
elif k == 'overhead':
check_range(k, r, -64, 256)
ret['attrs'].append([v, r])
return ret
class options(nla):
nla_map = (
('TCA_CAKE_UNSPEC', 'none'),
('TCA_CAKE_PAD', 'uint64'),
('TCA_CAKE_BASE_RATE64', 'uint64'),
('TCA_CAKE_DIFFSERV_MODE', 'uint32'),
('TCA_CAKE_ATM', 'uint32'),
('TCA_CAKE_FLOW_MODE', 'uint32'),
('TCA_CAKE_OVERHEAD', 'int32'),
('TCA_CAKE_RTT', 'uint32'),
('TCA_CAKE_TARGET', 'uint32'),
('TCA_CAKE_AUTORATE', 'uint32'),
('TCA_CAKE_MEMORY', 'uint32'),
('TCA_CAKE_NAT', 'uint32'),
('TCA_CAKE_RAW', 'uint32'),
('TCA_CAKE_WASH', 'uint32'),
('TCA_CAKE_MPU', 'uint32'),
('TCA_CAKE_INGRESS', 'uint32'),
('TCA_CAKE_ACK_FILTER', 'uint32'),
('TCA_CAKE_SPLIT_GSO', 'uint32'),
('TCA_CAKE_FWMARK', 'uint32'),
)
def encode(self):
# Set default Auto-Rate value
if not self.get_attr('TCA_CAKE_AUTORATE'):
self['attrs'].append(['TCA_CAKE_AUTORATE', 0])
nla.encode(self)
class stats2(nla):
nla_map = (
('TCA_STATS_UNSPEC', 'none'),
('TCA_STATS_BASIC', 'basic'),
('TCA_STATS_RATE_EST', 'rate_est'),
('TCA_STATS_QUEUE', 'queue'),
('TCA_STATS_APP', 'stats_app'),
)
class basic(nla):
fields = (('bytes', 'Q'), ('packets', 'I'))
class rate_est(nla):
fields = (('bps', 'I'), ('pps', 'I'))
class queue(nla):
fields = (
('qlen', 'I'),
('backlog', 'I'),
('drops', 'I'),
('requeues', 'I'),
('overlimits', 'I'),
)
class stats_app(nla):
nla_map = (
('__TCA_CAKE_STATS_INVALID', 'none'),
('TCA_CAKE_STATS_PAD', 'hex'),
('TCA_CAKE_STATS_CAPACITY_ESTIMATE64', 'uint64'),
('TCA_CAKE_STATS_MEMORY_LIMIT', 'uint32'),
('TCA_CAKE_STATS_MEMORY_USED', 'uint32'),
('TCA_CAKE_STATS_AVG_NETOFF', 'uint32'),
('TCA_CAKE_STATS_MAX_NETLEN', 'uint32'),
('TCA_CAKE_STATS_MAX_ADJLEN', 'uint32'),
('TCA_CAKE_STATS_MIN_NETLEN', 'uint32'),
('TCA_CAKE_STATS_MIN_ADJLEN', 'uint32'),
('TCA_CAKE_STATS_TIN_STATS', 'tca_parse_tins'),
('TCA_CAKE_STATS_DEFICIT', 'uint32'),
('TCA_CAKE_STATS_COBALT_COUNT', 'uint32'),
('TCA_CAKE_STATS_DROPPING', 'uint32'),
('TCA_CAKE_STATS_DROP_NEXT_US', 'uint32'),
('TCA_CAKE_STATS_P_DROP', 'uint32'),
('TCA_CAKE_STATS_BLUE_TIMER_US', 'uint32'),
)
class tca_parse_tins(nla):
nla_map = tuple(
[
('TCA_CAKE_TIN_STATS_%i' % x, 'tca_parse_tin_stats')
for x in range(TCA_CAKE_MAX_TINS)
]
)
class tca_parse_tin_stats(nla):
nla_map = (
('__TCA_CAKE_TIN_STATS_INVALID', 'none'),
('TCA_CAKE_TIN_STATS_PAD', 'hex'),
('TCA_CAKE_TIN_STATS_SENT_PACKETS', 'uint32'),
('TCA_CAKE_TIN_STATS_SENT_BYTES64', 'uint64'),
('TCA_CAKE_TIN_STATS_DROPPED_PACKETS', 'uint32'),
('TCA_CAKE_TIN_STATS_DROPPED_BYTES64', 'uint64'),
('TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS', 'uint32'),
('TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64', 'uint64'),
('TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS', 'uint32'),
('TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64', 'uint64'),
('TCA_CAKE_TIN_STATS_BACKLOG_PACKETS', 'uint32'),
('TCA_CAKE_TIN_STATS_BACKLOG_BYTES', 'uint32'),
('TCA_CAKE_TIN_STATS_THRESHOLD_RATE64', 'uint64'),
('TCA_CAKE_TIN_STATS_TARGET_US', 'uint32'),
('TCA_CAKE_TIN_STATS_INTERVAL_US', 'uint32'),
('TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS', 'uint32'),
('TCA_CAKE_TIN_STATS_WAY_MISSES', 'uint32'),
('TCA_CAKE_TIN_STATS_WAY_COLLISIONS', 'uint32'),
('TCA_CAKE_TIN_STATS_PEAK_DELAY_US', 'uint32'),
('TCA_CAKE_TIN_STATS_AVG_DELAY_US', 'uint32'),
('TCA_CAKE_TIN_STATS_BASE_DELAY_US', 'uint32'),
('TCA_CAKE_TIN_STATS_SPARSE_FLOWS', 'uint32'),
('TCA_CAKE_TIN_STATS_BULK_FLOWS', 'uint32'),
('TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS', 'uint32'),
('TCA_CAKE_TIN_STATS_MAX_SKBLEN', 'uint32'),
('TCA_CAKE_TIN_STATS_FLOW_QUANTUM', 'uint32'),
)
Zerion Mini Shell 1.0