PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/extras-3.10/pyroute2/netlink/rtnl/tcmsg/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/extras-3.10/pyroute2/netlink/rtnl/tcmsg/common.py |
import logging import os import re import struct from math import log as logfm from socket import inet_aton from pyroute2 import config from pyroute2.common import ( basestring, rate_suffixes, size_suffixes, time_suffixes, ) from pyroute2.netlink import nla, nla_string log = logging.getLogger(__name__) LINKLAYER_UNSPEC = 0 LINKLAYER_ETHERNET = 1 LINKLAYER_ATM = 2 ATM_CELL_SIZE = 53 ATM_CELL_PAYLOAD = 48 TCA_ACT_MAX_PRIO = 32 TIME_UNITS_PER_SEC = 1000000 try: with open('/proc/net/psched', 'r') as psched: [t2us, us2t, clock_res, wee] = [ int(i, 16) for i in psched.read().split() ] clock_factor = float(clock_res) / TIME_UNITS_PER_SEC tick_in_usec = float(t2us) / us2t * clock_factor except IOError as e: if config.uname[0] == 'Linux': log.warning("tcmsg: %s", e) log.warning("the tc subsystem functionality is limited") clock_res = 0 clock_factor = 1 tick_in_usec = 1 wee = 1000 _first_letter = re.compile('[^0-9]+') def get_hz(): if clock_res == 1000000: return wee else: return os.environ.get('HZ', 1000) def get_by_suffix(value, default, func): if not isinstance(value, basestring): return value pos = _first_letter.search(value) if pos is None: suffix = default else: pos = pos.start() value, suffix = value[:pos], value[pos:] value = int(value) return func(value, suffix) def get_size(size): return get_by_suffix(size, 'b', lambda x, y: x * size_suffixes[y]) def get_time(lat): return get_by_suffix( lat, 'ms', lambda x, y: (x * TIME_UNITS_PER_SEC) / time_suffixes[y] ) def get_rate(rate): return get_by_suffix(rate, 'bit', lambda x, y: (x * rate_suffixes[y]) / 8) def time2tick(time): # The code is ported from tc utility return int(time) * tick_in_usec def calc_xmittime(rate, size): # The code is ported from tc utility return int(time2tick(TIME_UNITS_PER_SEC * (float(size) / rate))) def percent2u32(pct): '''xlate a percentage to an uint32 value 0% -> 0 100% -> 2**32 - 1''' return int((2**32 - 1) * pct / 100) def red_eval_ewma(qmin, burst, avpkt): # The code is ported from tc utility wlog = 1 W = 0.5 a = float(burst) + 1 - float(qmin) / avpkt if a < 1: raise ValueError(f'wrong a = {a}') while wlog < 32: wlog += 1 W /= 2 if a <= (1 - pow(1 - W, burst)) / W: return wlog return -1 def red_eval_P(qmin, qmax, probability): # The code is ported from tc utility i = qmax - qmin if i <= 0: raise ValueError(f'qmax - qmin must be > 0 (got {i})') probability /= i for i in range(32): if probability > 1: break probability *= 2 return i def red_eval_idle_damping(Wlog, avpkt, bps): # The code is ported from tc utility xmit_time = calc_xmittime(bps, avpkt) lW = -logfm(1.0 - 1.0 / (1 << Wlog)) / xmit_time maxtime = 31.0 / lW sbuf = [] for clog in range(32): if maxtime / (1 << clog) < 512: break if clog >= 32: return -1, sbuf for i in range(255): sbuf.append((i << clog) * lW) if sbuf[i] > 31: sbuf[i] = 31 sbuf.append(31) return clog, sbuf def get_rate_parameters(kwarg): # rate and burst are required rate = get_rate(kwarg['rate']) burst = kwarg['burst'] # if peak, mtu is required peak = get_rate(kwarg.get('peak', 0)) mtu = kwarg.get('mtu', 0) if peak: assert mtu # limit OR latency is required limit = kwarg.get('limit', None) latency = get_time(kwarg.get('latency', None)) assert limit is not None or latency is not None # calculate limit from latency if limit is None: rate_limit = rate * float(latency) / TIME_UNITS_PER_SEC + burst if peak: peak_limit = peak * float(latency) / TIME_UNITS_PER_SEC + mtu if rate_limit > peak_limit: rate_limit = peak_limit limit = rate_limit return { 'rate': int(rate), 'mtu': mtu, 'buffer': calc_xmittime(rate, burst), 'limit': int(limit), } tc_flow_keys = { 'src': 0x01, 'dst': 0x02, 'proto': 0x04, 'proto-src': 0x08, 'proto-dst': 0x10, 'iif': 0x20, 'priority': 0x40, 'mark': 0x80, 'nfct': 0x0100, 'nfct-src': 0x0200, 'nfct-dst': 0x0400, 'nfct-proto-src': 0x0800, 'nfct-proto-dst': 0x1000, 'rt-classid': 0x2000, 'sk-uid': 0x4000, 'sk-gid': 0x8000, 'vlan-tag': 0x010000, 'rxhash': 0x020000, } def get_tca_keys(kwarg, name): if name not in kwarg: raise ValueError('Missing attribute: {0}'.format(name)) res = 0 keys = kwarg[name] if name == 'hash': keys = keys.split(',') for key, value in tc_flow_keys.items(): if key in keys: res |= value return res tc_flow_modes = {'map': 0, 'hash': 1} def get_tca_mode(kwarg): if 'mode' not in kwarg: raise ValueError('Missing attribute: mode') for key, value in tc_flow_modes.items(): if key == kwarg['mode']: return value raise ValueError('Unknown flow mode {0}'.format(kwarg['mode'])) def get_tca_ops(kwarg, attrs): xor_value = 0 mask_value = 0 addend_value = 0 rshift_value = 0 for elem in kwarg['ops']: op = elem['op'] num = elem['num'] if op == 'and': mask_value = num attrs.append(['TCA_FLOW_XOR', xor_value]) attrs.append(['TCA_FLOW_MASK', mask_value]) elif op == 'or': if mask_value == 0: mask_value = (~num + 1) & 0xFFFFFFFF xor_value = num attrs.append(['TCA_FLOW_XOR', xor_value]) attrs.append(['TCA_FLOW_MASK', mask_value]) elif op == 'xor': if mask_value == 0: mask_value = 0xFFFFFFFF xor_value = num attrs.append(['TCA_FLOW_XOR', xor_value]) attrs.append(['TCA_FLOW_MASK', mask_value]) elif op == 'rshift': rshift_value = num attrs.append(['TCA_FLOW_RSHIFT', rshift_value]) elif op == 'addend': # Check if an IP was specified if isinstance(num, str) and len(num.split('.')) == 4: if num.startswith('-'): inverse = True else: inverse = False ip = num.strip('-') # Convert IP to uint32 ip = inet_aton(ip) ip = struct.unpack('>I', ip)[0] if inverse: ip = (~ip + 1) & 0xFFFFFFFF addend_value = ip else: addend_value = num attrs.append(['TCA_FLOW_ADDEND', addend_value]) tc_actions = { 'unspec': -1, # TC_ACT_UNSPEC 'ok': 0, # TC_ACT_OK 'reclassify': 1, # TC_ACT_RECLASSIFY 'shot': 2, # TC_ACT_SHOT 'drop': 2, # TC_ACT_SHOT 'pipe': 3, # TC_ACT_PIPE 'stolen': 4, # TC_ACT_STOLEN 'queued': 5, # TC_ACT_QUEUED 'repeat': 6, # TC_ACT_REPEAT 'redirect': 7, # TC_ACT_REDIRECT } class nla_plus_rtab(nla): class parms(nla): def adjust_size(self, size, mpu, linklayer): # The current code is ported from tc utility if size < mpu: size = mpu if linklayer == LINKLAYER_ATM: cells = size / ATM_CELL_PAYLOAD if size % ATM_CELL_PAYLOAD > 0: cells += 1 size = cells * ATM_CELL_SIZE return size def calc_rtab(self, kind): # The current code is ported from tc utility rtab = [] mtu = self.get('mtu', 0) or 1600 cell_log = self['%s_cell_log' % (kind)] mpu = self['%s_mpu' % (kind)] rate = self.get(kind, 'rate') # calculate cell_log if cell_log == 0: while (mtu >> cell_log) > 255: cell_log += 1 # fill up the table for i in range(256): size = self.adjust_size( (i + 1) << cell_log, mpu, LINKLAYER_ETHERNET ) rtab.append(calc_xmittime(rate, size)) self['%s_cell_align' % (kind)] = -1 self['%s_cell_log' % (kind)] = cell_log return rtab def encode(self): self.rtab = None self.ptab = None if self.get('rate', False): self.rtab = self.calc_rtab('rate') if self.get('peak', False): self.ptab = self.calc_rtab('peak') if self.get('ceil', False): self.ctab = self.calc_rtab('ceil') nla.encode(self) class rtab(nla_string): own_parent = True def encode(self): parms = ( self.parent.get_encoded('TCA_TBF_PARMS') or self.parent.get_encoded('TCA_HTB_PARMS') or self.parent.get_encoded('TCA_POLICE_TBF') ) if parms is not None: self.value = getattr(parms, self.__class__.__name__) self['value'] = struct.pack( 'I' * 256, *(int(x) for x in self.value) ) nla_string.encode(self) def decode(self): nla_string.decode(self) parms = ( self.parent.get_attr('TCA_TBF_PARMS') or self.parent.get_attr('TCA_HTB_PARMS') or self.parent.get_attr('TCA_POLICE_TBF') ) if parms is not None: rtab = struct.unpack( 'I' * (len(self['value']) / 4), self['value'] ) self.value = rtab setattr(parms, self.__class__.__name__, rtab) class ptab(rtab): pass class ctab(rtab): pass 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.hex): pass