17c1280acc21a349405b53c8e946ca448a1763dbambligh"""Convenience methods for use to manipulate traffic control settings.
27c1280acc21a349405b53c8e946ca448a1763dbambligh
37c1280acc21a349405b53c8e946ca448a1763dbamblighsee http://linux.die.net/man/8/tc for details about traffic controls in linux.
47c1280acc21a349405b53c8e946ca448a1763dbambligh
57c1280acc21a349405b53c8e946ca448a1763dbamblighExample
67c1280acc21a349405b53c8e946ca448a1763dbambligh  import common
77c1280acc21a349405b53c8e946ca448a1763dbambligh  from autotest_lib.client.bin.net.net_tc import *
87c1280acc21a349405b53c8e946ca448a1763dbambligh  from autotest_lib.client.bin.net.net_utils import *
97c1280acc21a349405b53c8e946ca448a1763dbambligh
107c1280acc21a349405b53c8e946ca448a1763dbambligh  class mock_netif(object):
117c1280acc21a349405b53c8e946ca448a1763dbambligh
127c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, name):
137c1280acc21a349405b53c8e946ca448a1763dbambligh        self._name = name
147c1280acc21a349405b53c8e946ca448a1763dbambligh
157c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_name(self):
167c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._name
177c1280acc21a349405b53c8e946ca448a1763dbambligh
187c1280acc21a349405b53c8e946ca448a1763dbambligh
197c1280acc21a349405b53c8e946ca448a1763dbambligh  netem_qdisc = netem()
207c1280acc21a349405b53c8e946ca448a1763dbambligh  netem_qdisc.add_param('loss 100%')
217c1280acc21a349405b53c8e946ca448a1763dbambligh
227c1280acc21a349405b53c8e946ca448a1763dbambligh  ack_filter = u32filter()
237c1280acc21a349405b53c8e946ca448a1763dbambligh  ack_filter.add_rule('match ip protocol 6 0xff')
247c1280acc21a349405b53c8e946ca448a1763dbambligh  ack_filter.add_rule('match u8 0x10 0x10 at nexthdr+13')
257c1280acc21a349405b53c8e946ca448a1763dbambligh  ack_filter.set_dest_qdisc(netem_qdisc)
267c1280acc21a349405b53c8e946ca448a1763dbambligh
277c1280acc21a349405b53c8e946ca448a1763dbambligh  root_qdisc = prio()
287c1280acc21a349405b53c8e946ca448a1763dbambligh  root_qdisc.get_class(2).set_leaf_qdisc(netem_qdisc)
297c1280acc21a349405b53c8e946ca448a1763dbambligh  root_qdisc.add_filter(ack_filter)
307c1280acc21a349405b53c8e946ca448a1763dbambligh
317c1280acc21a349405b53c8e946ca448a1763dbambligh  lo_if = mock_netif('lo')
327c1280acc21a349405b53c8e946ca448a1763dbambligh
337c1280acc21a349405b53c8e946ca448a1763dbambligh  root_qdisc.setup(lo_if)
347c1280acc21a349405b53c8e946ca448a1763dbambligh
357c1280acc21a349405b53c8e946ca448a1763dbambligh  # run test here ...
367c1280acc21a349405b53c8e946ca448a1763dbambligh  root_qdisc.restore(lo_if)
377c1280acc21a349405b53c8e946ca448a1763dbambligh
387c1280acc21a349405b53c8e946ca448a1763dbambligh"""
397c1280acc21a349405b53c8e946ca448a1763dbambligh
407c1280acc21a349405b53c8e946ca448a1763dbamblighimport commands, os, re
417c1280acc21a349405b53c8e946ca448a1763dbamblighimport common
4253da18eddf69243ca175d9a4603cba5b55300726mblighfrom autotest_lib.client.common_lib import error
437c1280acc21a349405b53c8e946ca448a1763dbamblighfrom autotest_lib.client.bin.net import net_utils
447c1280acc21a349405b53c8e946ca448a1763dbambligh
457c1280acc21a349405b53c8e946ca448a1763dbambligh# TODO (chavey) clean up those global here and new_handle()
467c1280acc21a349405b53c8e946ca448a1763dbamblighhandle_counter = 0
477c1280acc21a349405b53c8e946ca448a1763dbamblighINCR = 100
487c1280acc21a349405b53c8e946ca448a1763dbambligh
497c1280acc21a349405b53c8e946ca448a1763dbambligh
507c1280acc21a349405b53c8e946ca448a1763dbamblighdef new_handle():
517c1280acc21a349405b53c8e946ca448a1763dbambligh    global handle_counter
527c1280acc21a349405b53c8e946ca448a1763dbambligh    handle_counter += INCR
537c1280acc21a349405b53c8e946ca448a1763dbambligh    return handle_counter
547c1280acc21a349405b53c8e946ca448a1763dbambligh
557c1280acc21a349405b53c8e946ca448a1763dbambligh
567c1280acc21a349405b53c8e946ca448a1763dbamblighclass tcclass(object):
577c1280acc21a349405b53c8e946ca448a1763dbambligh
587c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle, minor, leaf_qdisc=None):
597c1280acc21a349405b53c8e946ca448a1763dbambligh        self._parent_class = None
607c1280acc21a349405b53c8e946ca448a1763dbambligh        self._children = []
617c1280acc21a349405b53c8e946ca448a1763dbambligh        self._leaf_qdisc = leaf_qdisc
627c1280acc21a349405b53c8e946ca448a1763dbambligh        self._handle = handle
637c1280acc21a349405b53c8e946ca448a1763dbambligh        self._minor = minor
647c1280acc21a349405b53c8e946ca448a1763dbambligh
657c1280acc21a349405b53c8e946ca448a1763dbambligh
667c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_leaf_qdisc(self):
677c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._leaf_qdisc
687c1280acc21a349405b53c8e946ca448a1763dbambligh
697c1280acc21a349405b53c8e946ca448a1763dbambligh
707c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_leaf_qdisc(self, leaf_qdisc):
717c1280acc21a349405b53c8e946ca448a1763dbambligh        leaf_qdisc.set_parent_class(self)
727c1280acc21a349405b53c8e946ca448a1763dbambligh        self._leaf_qdisc = leaf_qdisc
737c1280acc21a349405b53c8e946ca448a1763dbambligh
747c1280acc21a349405b53c8e946ca448a1763dbambligh
757c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_parent_class(self):
767c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._parent_class
777c1280acc21a349405b53c8e946ca448a1763dbambligh
787c1280acc21a349405b53c8e946ca448a1763dbambligh
797c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_parent_class(self, parent_class):
807c1280acc21a349405b53c8e946ca448a1763dbambligh        self._parent_class = parent_class
817c1280acc21a349405b53c8e946ca448a1763dbambligh
827c1280acc21a349405b53c8e946ca448a1763dbambligh
837c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_minor(self):
847c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._minor
857c1280acc21a349405b53c8e946ca448a1763dbambligh
867c1280acc21a349405b53c8e946ca448a1763dbambligh
877c1280acc21a349405b53c8e946ca448a1763dbambligh    def id(self):
887c1280acc21a349405b53c8e946ca448a1763dbambligh        return '%s:%s' % (self._handle, self._minor)
897c1280acc21a349405b53c8e946ca448a1763dbambligh
907c1280acc21a349405b53c8e946ca448a1763dbambligh
917c1280acc21a349405b53c8e946ca448a1763dbambligh    def add_child(self, child_class):
927c1280acc21a349405b53c8e946ca448a1763dbambligh        child_class.set_parent_class(self)
937c1280acc21a349405b53c8e946ca448a1763dbambligh        if child_class not in self._children:
947c1280acc21a349405b53c8e946ca448a1763dbambligh            self._child.append(child_class)
957c1280acc21a349405b53c8e946ca448a1763dbambligh
967c1280acc21a349405b53c8e946ca448a1763dbambligh
977c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
987c1280acc21a349405b53c8e946ca448a1763dbambligh        # setup leaf qdisc
997c1280acc21a349405b53c8e946ca448a1763dbambligh        if self._leaf_qdisc:
1007c1280acc21a349405b53c8e946ca448a1763dbambligh            self._leaf_qdisc.setup(netif)
1017c1280acc21a349405b53c8e946ca448a1763dbambligh
1027c1280acc21a349405b53c8e946ca448a1763dbambligh        # setup child classes
1037c1280acc21a349405b53c8e946ca448a1763dbambligh        for child in self._children:
1047c1280acc21a349405b53c8e946ca448a1763dbambligh            child.setup()
1057c1280acc21a349405b53c8e946ca448a1763dbambligh
1067c1280acc21a349405b53c8e946ca448a1763dbambligh
1077c1280acc21a349405b53c8e946ca448a1763dbambligh    def restore(self, netif):
1087c1280acc21a349405b53c8e946ca448a1763dbambligh        # restore child classes
1097c1280acc21a349405b53c8e946ca448a1763dbambligh        children_copy = list(self._children)
1107c1280acc21a349405b53c8e946ca448a1763dbambligh        children_copy.reverse()
1117c1280acc21a349405b53c8e946ca448a1763dbambligh        for child in children_copy:
1127c1280acc21a349405b53c8e946ca448a1763dbambligh            child.restore()
1137c1280acc21a349405b53c8e946ca448a1763dbambligh
1147c1280acc21a349405b53c8e946ca448a1763dbambligh        # restore leaf qdisc
1157c1280acc21a349405b53c8e946ca448a1763dbambligh        if self._leaf_qdisc:
1167c1280acc21a349405b53c8e946ca448a1763dbambligh            self._leaf_qdisc.restore(netif)
1177c1280acc21a349405b53c8e946ca448a1763dbambligh
1187c1280acc21a349405b53c8e946ca448a1763dbambligh
1197c1280acc21a349405b53c8e946ca448a1763dbamblighclass tcfilter(object):
1207c1280acc21a349405b53c8e946ca448a1763dbambligh
1217c1280acc21a349405b53c8e946ca448a1763dbambligh    _tc_cmd = 'tc filter %(cmd)s dev %(dev)s parent %(parent)s protocol ' \
1227c1280acc21a349405b53c8e946ca448a1763dbambligh               '%(protocol)s prio %(priority)s %(filtertype)s \\\n ' \
1237c1280acc21a349405b53c8e946ca448a1763dbambligh               '%(rules)s \\\n  flowid %(flowid)s'
1247c1280acc21a349405b53c8e946ca448a1763dbambligh
1257c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_device = 'dev'
1267c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_parent = 'parent'
1277c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_type = 'filtertype'
1287c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_protocol = 'protocol'
1297c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_priority = 'priority'
1307c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_flowid = 'flowid'
1317c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_command = 'cmd'
1327c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_rules = 'cmd'
1337c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_qdiscid = 'qdiscid'
1347c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_name = 'name'
1357c1280acc21a349405b53c8e946ca448a1763dbambligh    conf_params = 'params'
1367c1280acc21a349405b53c8e946ca448a1763dbambligh
1377c1280acc21a349405b53c8e946ca448a1763dbambligh
1387c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self):
1397c1280acc21a349405b53c8e946ca448a1763dbambligh        self._parent_qdisc = None
1407c1280acc21a349405b53c8e946ca448a1763dbambligh        self._dest_qdisc = None
1417c1280acc21a349405b53c8e946ca448a1763dbambligh        self._protocol = 'ip'
1427c1280acc21a349405b53c8e946ca448a1763dbambligh        self._priority = 1
1437c1280acc21a349405b53c8e946ca448a1763dbambligh        self._handle = None
1447c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf = None
1457c1280acc21a349405b53c8e946ca448a1763dbambligh
1467c1280acc21a349405b53c8e946ca448a1763dbambligh
1477c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_parent_qdisc(self):
1487c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._parent_qdisc
1497c1280acc21a349405b53c8e946ca448a1763dbambligh
1507c1280acc21a349405b53c8e946ca448a1763dbambligh
1517c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_parent_qdisc(self, parent_qdisc):
1527c1280acc21a349405b53c8e946ca448a1763dbambligh        self._parent_qdisc = parent_qdisc
1537c1280acc21a349405b53c8e946ca448a1763dbambligh
1547c1280acc21a349405b53c8e946ca448a1763dbambligh
1557c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_dest_qdisc(self):
1567c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._dest_qdisc
1577c1280acc21a349405b53c8e946ca448a1763dbambligh
1587c1280acc21a349405b53c8e946ca448a1763dbambligh
1597c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_dest_qdisc(self, dest_qdisc):
1607c1280acc21a349405b53c8e946ca448a1763dbambligh        self._dest_qdisc = dest_qdisc
1617c1280acc21a349405b53c8e946ca448a1763dbambligh
1627c1280acc21a349405b53c8e946ca448a1763dbambligh
1637c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_protocol(self):
1647c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._protocol
1657c1280acc21a349405b53c8e946ca448a1763dbambligh
1667c1280acc21a349405b53c8e946ca448a1763dbambligh
1677c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_protocol(self, protocol):
1687c1280acc21a349405b53c8e946ca448a1763dbambligh        self._protocol = protocol
1697c1280acc21a349405b53c8e946ca448a1763dbambligh
1707c1280acc21a349405b53c8e946ca448a1763dbambligh
1717c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_priority(self):
1727c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._priority
1737c1280acc21a349405b53c8e946ca448a1763dbambligh
1747c1280acc21a349405b53c8e946ca448a1763dbambligh
1757c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_priority(self, priority):
1767c1280acc21a349405b53c8e946ca448a1763dbambligh        self._priority = priority
1777c1280acc21a349405b53c8e946ca448a1763dbambligh
1787c1280acc21a349405b53c8e946ca448a1763dbambligh
1797c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_handle(self):
1807c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._handle
1817c1280acc21a349405b53c8e946ca448a1763dbambligh
1827c1280acc21a349405b53c8e946ca448a1763dbambligh
1837c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_handle(self, handle):
1847c1280acc21a349405b53c8e946ca448a1763dbambligh        self._handle = handle
1857c1280acc21a349405b53c8e946ca448a1763dbambligh
1867c1280acc21a349405b53c8e946ca448a1763dbambligh
1877c1280acc21a349405b53c8e946ca448a1763dbambligh    def _get_tc_conf(self, netif):
1887c1280acc21a349405b53c8e946ca448a1763dbambligh        if self._tc_conf:
1897c1280acc21a349405b53c8e946ca448a1763dbambligh            return self._tc_conf
1907c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf = dict()
1917c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_device] = netif.get_name()
1927c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_parent] = self._parent_qdisc.id()
1937c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_type] = self.filtertype
1947c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_protocol] = self._protocol
1957c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_priotity] = self._priority
1967c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_flowid] = (
1977c1280acc21a349405b53c8e946ca448a1763dbambligh            self._dest_qdisc.get_parent_class().id())
1987c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._tc_conf
1997c1280acc21a349405b53c8e946ca448a1763dbambligh
2007c1280acc21a349405b53c8e946ca448a1763dbambligh
2017c1280acc21a349405b53c8e946ca448a1763dbambligh    def tc_cmd(self, tc_conf):
2027c1280acc21a349405b53c8e946ca448a1763dbambligh        print self._tc_cmd % tc_conf
2037c1280acc21a349405b53c8e946ca448a1763dbambligh
2047c1280acc21a349405b53c8e946ca448a1763dbambligh
2057c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
2067c1280acc21a349405b53c8e946ca448a1763dbambligh        pass
2077c1280acc21a349405b53c8e946ca448a1763dbambligh
2087c1280acc21a349405b53c8e946ca448a1763dbambligh
2097c1280acc21a349405b53c8e946ca448a1763dbambligh    def restore(self, netif):
2107c1280acc21a349405b53c8e946ca448a1763dbambligh        pass
2117c1280acc21a349405b53c8e946ca448a1763dbambligh
2127c1280acc21a349405b53c8e946ca448a1763dbambligh
2137c1280acc21a349405b53c8e946ca448a1763dbamblighclass u32filter(tcfilter):
2147c1280acc21a349405b53c8e946ca448a1763dbambligh
2157c1280acc21a349405b53c8e946ca448a1763dbambligh    filtertype = 'u32'
2167c1280acc21a349405b53c8e946ca448a1763dbambligh
2177c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self):
2187c1280acc21a349405b53c8e946ca448a1763dbambligh        super(u32filter, self).__init__()
2197c1280acc21a349405b53c8e946ca448a1763dbambligh        self._rules = []
2207c1280acc21a349405b53c8e946ca448a1763dbambligh
2217c1280acc21a349405b53c8e946ca448a1763dbambligh
2227c1280acc21a349405b53c8e946ca448a1763dbambligh    def _filter_rules(self):
2237c1280acc21a349405b53c8e946ca448a1763dbambligh        return ' \\\n  '.join(self._rules)
2247c1280acc21a349405b53c8e946ca448a1763dbambligh
2257c1280acc21a349405b53c8e946ca448a1763dbambligh
2267c1280acc21a349405b53c8e946ca448a1763dbambligh    def add_rule(self, rule):
2277c1280acc21a349405b53c8e946ca448a1763dbambligh        self._rules.append(rule)
2287c1280acc21a349405b53c8e946ca448a1763dbambligh
2297c1280acc21a349405b53c8e946ca448a1763dbambligh
2307c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
2317c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf = self._get_tc_conf(netif)
2327c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_cmd] = 'add'
2337c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_rules] = self._filter_rules()
2347c1280acc21a349405b53c8e946ca448a1763dbambligh        self.tc_cmd(tc_conf)
2357c1280acc21a349405b53c8e946ca448a1763dbambligh
2367c1280acc21a349405b53c8e946ca448a1763dbambligh
2377c1280acc21a349405b53c8e946ca448a1763dbambligh    def restore(self, netif):
2387c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf = self._get_tc_conf(netif)
2397c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_cmd] = 'del'
2407c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_rules] = self._filter_rules()
2417c1280acc21a349405b53c8e946ca448a1763dbambligh        self.tc_cmd(tc_conf)
2427c1280acc21a349405b53c8e946ca448a1763dbambligh
2437c1280acc21a349405b53c8e946ca448a1763dbambligh#TODO (ncrao): generate some typical rules: ack, syn, synack,
2447c1280acc21a349405b53c8e946ca448a1763dbambligh#              dport/sport, daddr/sddr, etc.
2457c1280acc21a349405b53c8e946ca448a1763dbamblighclass qdisc(object):
2467c1280acc21a349405b53c8e946ca448a1763dbambligh
2477c1280acc21a349405b53c8e946ca448a1763dbambligh    # tc command
2487c1280acc21a349405b53c8e946ca448a1763dbambligh    _tc_cmd = 'tc qdisc %(cmd)s dev %(dev)s %(parent)s ' \
2497c1280acc21a349405b53c8e946ca448a1763dbambligh              'handle %(qdiscid)s %(name)s %(params)s'
2507c1280acc21a349405b53c8e946ca448a1763dbambligh
2517c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle):
2527c1280acc21a349405b53c8e946ca448a1763dbambligh        self._handle = handle
2537c1280acc21a349405b53c8e946ca448a1763dbambligh        self._parent_class = None
2547c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf = None
2557c1280acc21a349405b53c8e946ca448a1763dbambligh
2567c1280acc21a349405b53c8e946ca448a1763dbambligh
2577c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_handle(self):
2587c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._handle
2597c1280acc21a349405b53c8e946ca448a1763dbambligh
2607c1280acc21a349405b53c8e946ca448a1763dbambligh
2617c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_parent_class(self):
2627c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._parent_class
2637c1280acc21a349405b53c8e946ca448a1763dbambligh
2647c1280acc21a349405b53c8e946ca448a1763dbambligh
2657c1280acc21a349405b53c8e946ca448a1763dbambligh    def set_parent_class(self, parent_class):
2667c1280acc21a349405b53c8e946ca448a1763dbambligh        self._parent_class = parent_class
2677c1280acc21a349405b53c8e946ca448a1763dbambligh
2687c1280acc21a349405b53c8e946ca448a1763dbambligh
2697c1280acc21a349405b53c8e946ca448a1763dbambligh    def _get_tc_conf(self, netif):
2707c1280acc21a349405b53c8e946ca448a1763dbambligh        if self._tc_conf:
2717c1280acc21a349405b53c8e946ca448a1763dbambligh            return self._tc_conf
2727c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf = dict()
2737c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_device] = netif.get_name()
2747c1280acc21a349405b53c8e946ca448a1763dbambligh        if self._parent_class:
2757c1280acc21a349405b53c8e946ca448a1763dbambligh            self._tc_conf[tcfilter.conf_parent] = ('parent %s' %
2767c1280acc21a349405b53c8e946ca448a1763dbambligh                                                   self._parent_class.id())
2777c1280acc21a349405b53c8e946ca448a1763dbambligh        else:
2787c1280acc21a349405b53c8e946ca448a1763dbambligh            self._tc_conf[tcfilter.conf_parent] = 'root'
2797c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_qdiscid] = self.id()
2807c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_name] = self.name
2817c1280acc21a349405b53c8e946ca448a1763dbambligh        self._tc_conf[tcfilter.conf_params] = ''
2827c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._tc_conf
2837c1280acc21a349405b53c8e946ca448a1763dbambligh
2847c1280acc21a349405b53c8e946ca448a1763dbambligh
2857c1280acc21a349405b53c8e946ca448a1763dbambligh    def id(self):
2867c1280acc21a349405b53c8e946ca448a1763dbambligh        return '%s:0' % self._handle
2877c1280acc21a349405b53c8e946ca448a1763dbambligh
2887c1280acc21a349405b53c8e946ca448a1763dbambligh
2897c1280acc21a349405b53c8e946ca448a1763dbambligh    def tc_cmd(self, tc_conf):
2907c1280acc21a349405b53c8e946ca448a1763dbambligh        print self._tc_cmd % tc_conf
2917c1280acc21a349405b53c8e946ca448a1763dbambligh
2927c1280acc21a349405b53c8e946ca448a1763dbambligh
2937c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
2947c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf = self._get_tc_conf(netif)
2957c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_command] = 'add'
2967c1280acc21a349405b53c8e946ca448a1763dbambligh        self.tc_cmd(tc_conf)
2977c1280acc21a349405b53c8e946ca448a1763dbambligh
2987c1280acc21a349405b53c8e946ca448a1763dbambligh
2997c1280acc21a349405b53c8e946ca448a1763dbambligh    def restore(self, netif):
3007c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf = self._get_tc_conf(netif)
3017c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_command] = 'del'
3027c1280acc21a349405b53c8e946ca448a1763dbambligh        self.tc_cmd(tc_conf)
3037c1280acc21a349405b53c8e946ca448a1763dbambligh
3047c1280acc21a349405b53c8e946ca448a1763dbambligh
3057c1280acc21a349405b53c8e946ca448a1763dbamblighclass classful_qdisc(qdisc):
3067c1280acc21a349405b53c8e946ca448a1763dbambligh
3077c1280acc21a349405b53c8e946ca448a1763dbambligh    classful = True
3087c1280acc21a349405b53c8e946ca448a1763dbambligh
3097c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle):
3107c1280acc21a349405b53c8e946ca448a1763dbambligh        super(classful_qdisc, self).__init__(handle)
3117c1280acc21a349405b53c8e946ca448a1763dbambligh        self._classes = []
3127c1280acc21a349405b53c8e946ca448a1763dbambligh        self._filters = []
3137c1280acc21a349405b53c8e946ca448a1763dbambligh
3147c1280acc21a349405b53c8e946ca448a1763dbambligh
3157c1280acc21a349405b53c8e946ca448a1763dbambligh    def add_class(self, child_class):
3167c1280acc21a349405b53c8e946ca448a1763dbambligh        self._classes.append(child_class)
3177c1280acc21a349405b53c8e946ca448a1763dbambligh
3187c1280acc21a349405b53c8e946ca448a1763dbambligh
3197c1280acc21a349405b53c8e946ca448a1763dbambligh    def add_filter(self, filter):
3207c1280acc21a349405b53c8e946ca448a1763dbambligh        filter.set_parent_qdisc(self)
3217c1280acc21a349405b53c8e946ca448a1763dbambligh        self._filters.append(filter)
3227c1280acc21a349405b53c8e946ca448a1763dbambligh
3237c1280acc21a349405b53c8e946ca448a1763dbambligh
3247c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
3257c1280acc21a349405b53c8e946ca448a1763dbambligh        super(classful_qdisc, self).setup(netif)
3267c1280acc21a349405b53c8e946ca448a1763dbambligh
3277c1280acc21a349405b53c8e946ca448a1763dbambligh        # setup child classes
3287c1280acc21a349405b53c8e946ca448a1763dbambligh        for child in self._classes:
3297c1280acc21a349405b53c8e946ca448a1763dbambligh            child.setup(netif)
3307c1280acc21a349405b53c8e946ca448a1763dbambligh
3317c1280acc21a349405b53c8e946ca448a1763dbambligh        # setup filters
3327c1280acc21a349405b53c8e946ca448a1763dbambligh        for filter in self._filters:
3337c1280acc21a349405b53c8e946ca448a1763dbambligh            filter.setup(netif)
3347c1280acc21a349405b53c8e946ca448a1763dbambligh
3357c1280acc21a349405b53c8e946ca448a1763dbambligh
3367c1280acc21a349405b53c8e946ca448a1763dbambligh    def restore(self, netif):
3377c1280acc21a349405b53c8e946ca448a1763dbambligh        # restore filters
3387c1280acc21a349405b53c8e946ca448a1763dbambligh        filters_copy = list(self._filters)
3397c1280acc21a349405b53c8e946ca448a1763dbambligh        filters_copy.reverse()
3407c1280acc21a349405b53c8e946ca448a1763dbambligh        for filter in filters_copy:
3417c1280acc21a349405b53c8e946ca448a1763dbambligh            filter.restore(netif)
3427c1280acc21a349405b53c8e946ca448a1763dbambligh
3437c1280acc21a349405b53c8e946ca448a1763dbambligh        # restore child classes
3447c1280acc21a349405b53c8e946ca448a1763dbambligh        classes_copy = list(self._classes)
3457c1280acc21a349405b53c8e946ca448a1763dbambligh        classes_copy.reverse()
3467c1280acc21a349405b53c8e946ca448a1763dbambligh        for child in classes_copy:
3477c1280acc21a349405b53c8e946ca448a1763dbambligh            child.restore(netif)
3487c1280acc21a349405b53c8e946ca448a1763dbambligh
3497c1280acc21a349405b53c8e946ca448a1763dbambligh        super(classful_qdisc, self).restore(netif)
3507c1280acc21a349405b53c8e946ca448a1763dbambligh
3517c1280acc21a349405b53c8e946ca448a1763dbambligh
3527c1280acc21a349405b53c8e946ca448a1763dbamblighclass prio(classful_qdisc):
3537c1280acc21a349405b53c8e946ca448a1763dbambligh
3547c1280acc21a349405b53c8e946ca448a1763dbambligh    name = 'prio'
3557c1280acc21a349405b53c8e946ca448a1763dbambligh
3567c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle=new_handle(), bands=3):
3577c1280acc21a349405b53c8e946ca448a1763dbambligh        super(prio, self).__init__(handle)
3587c1280acc21a349405b53c8e946ca448a1763dbambligh        self._bands = bands
3597c1280acc21a349405b53c8e946ca448a1763dbambligh        for counter in range(bands):
3607c1280acc21a349405b53c8e946ca448a1763dbambligh            self.add_class(tcclass(handle, counter + 1))
3617c1280acc21a349405b53c8e946ca448a1763dbambligh
3627c1280acc21a349405b53c8e946ca448a1763dbambligh
3637c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
3647c1280acc21a349405b53c8e946ca448a1763dbambligh        super(prio, self).setup(netif)
3657c1280acc21a349405b53c8e946ca448a1763dbambligh
3667c1280acc21a349405b53c8e946ca448a1763dbambligh
3677c1280acc21a349405b53c8e946ca448a1763dbambligh    def get_class(self, band):
3687c1280acc21a349405b53c8e946ca448a1763dbambligh        if band > self._bands:
3697c1280acc21a349405b53c8e946ca448a1763dbambligh            raise error.TestError('error inserting %s at band %s' % \
3707c1280acc21a349405b53c8e946ca448a1763dbambligh                                  (qdisc.name, band))
3717c1280acc21a349405b53c8e946ca448a1763dbambligh        return self._classes[band]
3727c1280acc21a349405b53c8e946ca448a1763dbambligh
3737c1280acc21a349405b53c8e946ca448a1763dbambligh
3747c1280acc21a349405b53c8e946ca448a1763dbamblighclass classless_qdisc(qdisc):
3757c1280acc21a349405b53c8e946ca448a1763dbambligh
3767c1280acc21a349405b53c8e946ca448a1763dbambligh    classful = False
3777c1280acc21a349405b53c8e946ca448a1763dbambligh
3787c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle):
3797c1280acc21a349405b53c8e946ca448a1763dbambligh        super(classless_qdisc, self).__init__(handle)
3807c1280acc21a349405b53c8e946ca448a1763dbambligh
3817c1280acc21a349405b53c8e946ca448a1763dbambligh
3827c1280acc21a349405b53c8e946ca448a1763dbamblighclass pfifo(classless_qdisc):
3837c1280acc21a349405b53c8e946ca448a1763dbambligh
3847c1280acc21a349405b53c8e946ca448a1763dbambligh    name = 'pfifo'
3857c1280acc21a349405b53c8e946ca448a1763dbambligh
3867c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle=new_handle()):
3877c1280acc21a349405b53c8e946ca448a1763dbambligh        super(pfifo, self).__init__(handle)
3887c1280acc21a349405b53c8e946ca448a1763dbambligh
3897c1280acc21a349405b53c8e946ca448a1763dbambligh
3907c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
3917c1280acc21a349405b53c8e946ca448a1763dbambligh        super(pfifo, self).setup(netif)
3927c1280acc21a349405b53c8e946ca448a1763dbambligh
3937c1280acc21a349405b53c8e946ca448a1763dbambligh
3947c1280acc21a349405b53c8e946ca448a1763dbamblighclass netem(classless_qdisc):
3957c1280acc21a349405b53c8e946ca448a1763dbambligh
3967c1280acc21a349405b53c8e946ca448a1763dbambligh    name = 'netem'
3977c1280acc21a349405b53c8e946ca448a1763dbambligh
3987c1280acc21a349405b53c8e946ca448a1763dbambligh    def __init__(self, handle=new_handle()):
3997c1280acc21a349405b53c8e946ca448a1763dbambligh        super(netem, self).__init__(handle)
4007c1280acc21a349405b53c8e946ca448a1763dbambligh        self._params = list()
4017c1280acc21a349405b53c8e946ca448a1763dbambligh
4027c1280acc21a349405b53c8e946ca448a1763dbambligh
4037c1280acc21a349405b53c8e946ca448a1763dbambligh    def add_param(self, param):
4047c1280acc21a349405b53c8e946ca448a1763dbambligh        self._params.append(param)
4057c1280acc21a349405b53c8e946ca448a1763dbambligh
4067c1280acc21a349405b53c8e946ca448a1763dbambligh
4077c1280acc21a349405b53c8e946ca448a1763dbambligh    def setup(self, netif):
4087c1280acc21a349405b53c8e946ca448a1763dbambligh        super(netem, self).setup(netif)
4097c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf = self._get_tc_conf(netif)
4107c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_command] = 'change'
4117c1280acc21a349405b53c8e946ca448a1763dbambligh        tc_conf[tcfilter.conf_params] = ' '.join(self._params)
4127c1280acc21a349405b53c8e946ca448a1763dbambligh        self.tc_cmd(tc_conf)
413