def linkconfig(self, netif, bw = None, delay = None,
                   loss = None, duplicate = None, jitter = None, netif2 = None,
                   devname = None):
        
        sys.stderr.write("enter linkconfig() ...\n")
        traceback.print_stack()
        
        if devname is None:
            devname = netif.localname
        tc = [TC_BIN, "qdisc", "replace", "dev", devname]
        parent = ["root"]
        changed = False
        if netif.setparam('bw', bw):
            # from tc-tbf(8): minimum value for burst is rate / kernel_hz
            if bw is not None:
                burst = max(2 * netif.mtu, bw / 1000)
                limit = 0xffff # max IP payload
                tbf = ["tbf", "rate", str(bw),
                       "burst", str(burst), "limit", str(limit)]
            if bw > 0:
                if self.up:
                    if (self.verbose):
                        self.info("linkconfig: %s" % \
                                  ([tc + parent + ["handle", "1:"] + tbf],))
                    check_call(tc + parent + ["handle", "1:"] + tbf)
                netif.setparam('has_tbf', True)
                changed = True
            elif netif.getparam('has_tbf') and bw <= 0:
                tcd = [] + tc
                tcd[2] = "delete"
                if self.up:
                    check_call(tcd + parent)
                netif.setparam('has_tbf', False)
                # removing the parent removes the child
                netif.setparam('has_netem', False)
                changed = True
        if netif.getparam('has_tbf'):
            parent = ["parent", "1:1"]
        netem = ["netem"]
        changed = max(changed, netif.setparam('delay', delay))
        if loss is not None:
            loss = float(loss)
        changed = max(changed, netif.setparam('loss', loss))
        if duplicate is not None:
            duplicate = float(duplicate)
        changed = max(changed, netif.setparam('duplicate', duplicate))
        changed = max(changed, netif.setparam('jitter', jitter))
        if not changed:
            return
        # jitter and delay use the same delay statement
        if delay is not None:
            netem += ["delay", "%sus" % delay]
        if jitter is not None:
            if delay is None:
                netem += ["delay", "0us", "%sus" % jitter, "25%"]
            else:
                netem += ["%sus" % jitter, "25%"]
        
        if loss is not None:
            netem += ["loss", "%s%%" % min(loss, 100)]
        if duplicate is not None:
            netem += ["duplicate", "%s%%" % min(duplicate, 100)]
        if delay <= 0 and jitter <= 0 and loss <= 0 and duplicate <= 0:
            # possibly remove netem if it exists and parent queue wasn't removed
            if not netif.getparam('has_netem'):
                return
            tc[2] = "delete"
            if self.up:
                if self.verbose:
                    self.info("linkconfig: %s" % \
                              ([tc + parent + ["handle", "10:"]],))
                check_call(tc + parent + ["handle", "10:"])
            netif.setparam('has_netem', False)
        elif len(netem) > 1:
            if self.up:
                if self.verbose:
                    self.info("linkconfig: %s" % \
                              ([tc + parent + ["handle", "10:"] + netem],))
                check_call(tc + parent + ["handle", "10:"] + netem)
            netif.setparam('has_netem', True)
Configure link parameters by applying tc queuing disciplines on the
dataset/ETHPy150Open coreemu/core/daemon/core/netns/vnet.py/LxBrNet.linkconfig