Exemplo n.º 1
0
 def flow_removed_hybrid(self, label, expire, overflow, curtime):
     instractions = []
     for entry in expire:
         if entry.timeout_type == setting.TIMEOUT_IDLE and entry.priority < 32:
             # print('*remove dependency')
             rule = (entry.priority, entry.match_field)
             deprules = self.ruleset.depset[rule]
             for r in deprules:
                 if r[0] == 32:
                     entry = element.Entry(setting.FIELD_DSTIP, 32, r[1], None)
                 else:
                     entry = element.Entry(setting.FIELD_DSTPREFIX, r[0], r[1], None)
                 instractions.append((setting.INST_DELETE, label, entry))
     return instractions
Exemplo n.º 2
0
    def packet_in_hybrid(self, label, pkt, curtime):
        rule = self.ruleset.rules[pkt.dstip]
        deprules = self.ruleset.depset[rule]

        timeout = setting.DEFAULT_TIMEOUT
        if self.predictor.name == setting.PREDICTOR_SIMPLE:
            self.predictor.update((setting.INFO_PACKET_IN, label, curtime, rule))
            timeout = self.predictor.predict(rule, curtime, label)
        if (self.predictor.name == setting.PREDICTOR_Q or 
            self.predictor.name == setting.PREDICTOR_DQN):
            timeout = self.predictor.predict(rule, curtime, label)

        instractions = []
        dst = pkt.dst
        path = self.shortest_pathes[label][dst][0]
        if rule[0] == 32:
            field = setting.FIELD_DSTIP
            priority = 32
        else:
            field = setting.FIELD_DSTPREFIX[rule[0]]
            priority = rule[0]
        match_field = rule[1]
        for cnt in range(len(path)-1):
            action = [(setting.ACT_FWD, path[cnt+1])]
            entry = element.Entry(field, priority, match_field, action, 
                                  flag=setting.FLAG_REMOVE_NOTIFY, ts=curtime, 
                                  timeout=timeout, timeout_type=setting.TIMEOUT_IDLE)
            instractions.append((setting.INST_ADD, path[cnt], entry))
            self.record_install(rule)

        for r in deprules:
            if r[0] == 32:
                field = setting.FIELD_DSTIP
                priority = 32
            else:
                field = setting.FIELD_DSTPREFIX[r[0]]
                priority = r[0]
            match_field = r[1]
            for cnt in range(len(path)-1):
                action = [(setting.ACT_FWD, path[cnt+1])]
                entry = element.Entry(field, priority, match_field, action, 
                                      flag=None, ts=curtime, 
                                      timeout=setting.INF, 
                                      timeout_type=setting.TIMEOUT_HARD)
                instractions.append((setting.INST_ADD, path[cnt], entry))
                self.record_install(r)
            
        return instractions
Exemplo n.º 3
0
    def packet_in_idle(self, label, pkt, curtime):
        instractions = []
        dst = pkt.dst
        path = self.shortest_pathes[label][dst][0]
        field = setting.FIELD_DSTIP
        priority = 32
        match_field = pkt.dstip

        timeout = setting.DEFAULT_TIMEOUT
        if self.predictor.name == setting.PREDICTOR_SIMPLE:
            rule = (32, match_field)
            self.predictor.update((setting.INFO_PACKET_IN, label, curtime, rule))
            timeout = self.predictor.predict(rule, curtime, label)
        if (self.predictor.name == setting.PREDICTOR_Q or 
            self.predictor.name == setting.PREDICTOR_DQN):
            rule = (32, match_field)
            timeout = self.predictor.predict(rule, curtime, label)

        for cnt in range(len(path)-1):
            action = [(setting.ACT_FWD, path[cnt+1])]
            entry = element.Entry(field, priority, match_field, action, 
                                  flag=setting.FLAG_REMOVE_NOTIFY, 
                                  ts=curtime, timeout=timeout, 
                                  timeout_type=setting.TIMEOUT_IDLE)
            instractions.append((setting.INST_ADD, path[cnt], entry))
            self.record_install((32, match_field))
        return instractions
Exemplo n.º 4
0
    def get_match_entry(self, pkt):
        match_entry = element.Entry(None, -1, None, None)

        def comp_entry(new_entry, old_entry):
            if new_entry.priority > old_entry.priority:
                return new_entry
            elif new_entry.priority == old_entry.priority:  # TODO: ECMP
                return old_entry
            else:
                return old_entry

        # fast match (exact matching)
        pkt_attr = {setting.FIELD_TP: pkt.tp, setting.FIELD_DSTIP: pkt.dstip}

        for field in pkt_attr:
            if field in self.flow_table:
                attr = pkt_attr[field]
                if attr in self.flow_table[field]:
                    entry = self.flow_table[field][attr]
                    match_entry = comp_entry(entry, match_entry)

        # slow match (wildcard matching for dstip)
        if match_entry.priority == -1:
            for prefix in setting.FIELD_DSTPREFIX:
                field = setting.FIELD_DSTPREFIX[prefix]
                if field in self.flow_table:
                    attr = element.int2ip(
                        element.get_ip_range(pkt.dstip, prefix)[0])
                    if attr in self.flow_table[field]:
                        entry = self.flow_table[field][attr]
                        match_entry = comp_entry(entry, match_entry)

        return match_entry
Exemplo n.º 5
0
    def get_match_entry(self, pkt):
        match_entry = element.Entry(None, -1, None, None)

        def comp_entry(new_entry, old_entry):
            if new_entry.priority > old_entry.priority:
                return new_entry
            elif new_entry.priority == old_entry.priority:  # TODO: ECMP
                return old_entry
            else:
                return old_entry

        # fast match (exact matching)
        # sequential matching against label(50) -> tuple(40) -> dstip(32) -> others
        if setting.FIELD_LABEL_SRC_DST in self.fast_table:
            if (pkt.label, pkt.src, pkt.dst) in self.fast_table[setting.FIELD_LABEL_SRC_DST]:
                entry = self.fast_table[setting.FIELD_LABEL_SRC_DST][(pkt.label, pkt.src, pkt.dst)]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        if setting.FIELD_LABEL_RLABEL_DST in self.fast_table:
            if (pkt.label, pkt.rlabel, pkt.dst) in self.fast_table[setting.FIELD_LABEL_RLABEL_DST]:
                entry = self.fast_table[setting.FIELD_LABEL_RLABEL_DST][(pkt.label, pkt.rlabel, pkt.dst)]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        if setting.FIELD_LABEL in self.fast_table:
            if pkt.label in self.fast_table[setting.FIELD_LABEL]:
                entry = self.fast_table[setting.FIELD_LABEL][pkt.label]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        if setting.FIELD_LABEL_RLABEL in self.fast_table:
            if (pkt.label, pkt.rlabel) in self.fast_table[setting.FIELD_LABEL_RLABEL]:
                entry = self.fast_table[setting.FIELD_LABEL_RLABEL][(pkt.label, pkt.rlabel)]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        if setting.FIELD_TP in self.fast_table:
            if pkt.tp in self.fast_table[setting.FIELD_TP]:
                entry = self.fast_table[setting.FIELD_TP][pkt.tp]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        if setting.FIELD_DSTIP in self.fast_table:
            if pkt.dstip in self.fast_table[setting.FIELD_DSTIP]:
                entry = self.fast_table[setting.FIELD_DSTIP][pkt.dstip]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        if setting.FIELD_DST in self.fast_table:
            if pkt.dst in self.fast_table[setting.FIELD_DST]:
                entry = self.fast_table[setting.FIELD_DST][pkt.dst]
                if entry is not None:
                    match_entry = comp_entry(entry, match_entry)

        # TODO: slow match (wildcard matching)

        return match_entry
Exemplo n.º 6
0
 def packet_in_default(self, label, pkt):
     dst = pkt.dst
     path = self.shortest_pathes[label][dst][0]
     field = setting.FIELD_TP
     priority = 40
     match_field = pkt.tp
     action = [(setting.ACT_FWD, path[1])]
     entry = element.Entry(field, priority, match_field, action)
     inst = [(setting.INST_ADD, label, entry)
             ]  # instructions = [(action, object, content), ...]
     return inst
Exemplo n.º 7
0
 def packet_in_default(self, label, pkt, curtime):  
     dst = pkt.dst
     path = self.shortest_pathes[label][dst][0]
     field = setting.FIELD_TP
     priority = 40
     match_field = pkt.tp
     action = [(setting.ACT_FWD, path[1])]
     entry = element.Entry(field, priority, match_field, action, 
                           flag=setting.FLAG_REMOVE_NOTIFY, 
                           ts=curtime, timeout=setting.DEFAULT_TIMEOUT, 
                           timeout_type=setting.TIMEOUT_IDLE)  # 1s idle timeout
     inst = [(setting.INST_ADD, label, entry)]  # instructions = [(action, object, content), ...]
     return inst
Exemplo n.º 8
0
 def packet_in_spath(self, label, pkt):
     dst = pkt.dst
     path = self.shortest_pathes[label][dst][0]
     instractions = []
     field = setting.FIELD_TP
     priority = 40
     match_field = pkt.tp
     for cnt in range(len(path) - 1):
         action = [(setting.ACT_FWD, path[cnt + 1])]
         entry = element.Entry(field, priority, match_field, action)
         inst = (setting.INST_ADD, path[cnt], entry)
         instractions.append(inst)
     return instractions
Exemplo n.º 9
0
 def packet_in_spath(self, label, pkt, curtime):  
     dst = pkt.dst
     path = self.shortest_pathes[label][dst][0]
     instractions = []
     field = setting.FIELD_TP
     priority = 40
     match_field = pkt.tp
     for cnt in range(len(path)-1):
         action = [(setting.ACT_FWD, path[cnt+1])]
         entry = element.Entry(field, priority, match_field, action, 
                               flag=setting.FLAG_REMOVE_NOTIFY, 
                               ts=curtime, timeout=setting.DEFAULT_TIMEOUT, 
                               timeout_type=setting.TIMEOUT_IDLE)  # 1s idle timeout
         inst = (setting.INST_ADD, path[cnt], entry)
         instractions.append(inst)
     return instractions
Exemplo n.º 10
0
def fabric_simu(net, log_prefix, check_interval=5000):
    # print('***simulation begins***')

    n = net
    c = n.controller

    instractions = []
    for src in range(n.switch_num):
        for dst in range(n.switch_num):
            if src == dst: continue
            #  select a path
            path = c.shortest_pathes[src][dst][0]

            #  install tagging entries at the first switch
            field = setting.FIELD_DST
            priority = 1
            match_field = dst
            action = [(setting.ACT_TAG, dst), (setting.ACT_FWD, setting.LOCAL)]
            entry = element.Entry(field, priority, match_field, action)
            inst = (setting.INST_FIX, src, entry)
            instractions.append(inst)

            # install forwarding entries
            field = setting.FIELD_LABEL
            priority = 50
            match_field = dst
            for cnt in range(1, len(path) - 1):
                action = [(setting.ACT_FWD, path[cnt + 1])]
                entry = element.Entry(field, priority, match_field, action)
                inst = (setting.INST_FIX, path[cnt], entry)
                instractions.append(inst)
    n.process_ctrl_messages(instractions)

    flownum = n.traffic.flownum
    d = data.Data()
    delay = 0
    overflow_num = 0
    pktnum = 0

    for pkt in n.traffic.pkts:
        # print('processing packet');pkt.print_pkt()
        sw = n.switches[pkt.src]
        # print('arriving switch %d' % sw.label)
        hop = 0
        of = 0
        while True:
            if pkt.dst == sw.label:
                pkt.path.append(sw.label)
                break
            [pkt, next_hop] = sw.recv_pkt(pkt)
            # print('\tforwarding to %s' % str(next_hop))
            if next_hop == setting.CTRL:
                raise AssertionError(
                    'Error. Packets in Fabric do not go pass controller. Exit.'
                )
            elif next_hop == setting.LOCAL:
                src = pkt.src
                dst = pkt.dst
                path = c.shortest_pathes[src][dst][0]

                # install tagging rule matching exact dst IP
                field = setting.FIELD_TP
                priority = 40
                match_field = pkt.tp
                action = [(setting.ACT_TAG, dst), (setting.ACT_FWD, path[1])]
                entry = element.Entry(field, priority, match_field, action)
                instractions = [(setting.INST_ADD, src, entry)]
                of = n.process_ctrl_messages(instractions)

                # forward
                next_hop = path[1]
                sw = n.switches[next_hop]
                # print('arriving switch %d' % sw.label)
            else:
                sw = n.switches[next_hop]
                # print('arriving switch %d' % sw.label)
            hop += 1
            assert hop < 10 * len(n.topo)
        # print('pkt path = {}'.format(pkt.path))

        fnum = flownum[pktnum]
        pktnum += 1
        overflow_num += of
        pkttime = c.get_delay(pkt.path, pkt.size)
        delay += pkttime

        flowsize = n.traffic.flowsize[pkt.tp]
        d.record_fct(pkt.tp, pkttime, flowsize)

        if fnum % check_interval == 0:
            if fnum not in d.delay['flownum']:
                instractions = [(setting.INST_QUERY, setting.INST_OBJ_ALL,
                                 None)]
                totentry = n.process_ctrl_messages(instractions)
                maxentry = 0
                for label in range(n.switch_num):
                    instractions = [(setting.INST_QUERY,
                                     setting.INST_OBJ_TABLE, label)]
                    maxentry = max(maxentry,
                                   n.process_ctrl_messages(instractions))

                d.record(fnum, delay, totentry, maxentry, overflow_num)
                d.print_checkpoint(fnum, log_prefix + '_checkpoint.txt')

    d.print_data(log_prefix)

    return
Exemplo n.º 11
0
        if next_hop == setting.CTRL:
            pkt.path.append(setting.CTRL)
        
        return [pkt, next_hop]

    def print_table(self, filename=None):
        for entry in self.flow_table:
            entry.print_entry(filename)
        return 0


if __name__ == '__main__':
    label = 1
    sw = Switch(label)
    entry = element.Entry(setting.FIELD_DSTIP, 32, '1.2.3.4', 
                          [(setting.ACT_FWD, 2)])
    sw.add_entry(entry)
    pkt = traffic.Packet(('0.0.3.0', '1.2.3.4'))
    [pkt, next_hop] = sw.recv_pkt(pkt)
    assert next_hop == 2

    entry = element.Entry(setting.FIELD_DSTIP, 40, '1.2.3.4', 
                          [(setting.ACT_TAG, 10), (setting.ACT_FWD, 10)])
    sw.add_entry(entry)
    entry = element.Entry(setting.FIELD_DSTIP, 10, '1.2.3.4', 
                          [(setting.ACT_TAG, 10), (setting.ACT_FWD, 10)])
    sw.add_entry(entry)
    [pkt, next_hop] = sw.recv_pkt(pkt)
    assert next_hop == 10
    assert pkt.label == 10
    assert sw.get_size() == 1
Exemplo n.º 12
0
def difane_simu(net, log_prefix, check_interval=5000):
    # print('***simulation begins***')

    n = net
    c = n.controller

    instractions = []
    for region_label in c.regions:
        for dst in c.regions[region_label]:
            # install relay rule to forward packets from auth. switch to egress
            path = c.shortest_pathes[region_label][dst][0]
            field = setting.FIELD_LABEL
            priority = 50
            match_field = dst
            for cnt in range(1, len(path) - 1):
                action = [(setting.ACT_FWD, path[cnt + 1])]
                entry = element.Entry(field, priority, match_field, action)
                inst = (setting.INST_FIX, path[cnt], entry)
                instractions.append(inst)

            for src in range(n.switch_num):
                if src == dst: continue
                # install auth. rule to trigger local action
                field = setting.FIELD_LABEL_SRC_DST
                priority = 50
                match_field = (region_label, src, dst)
                action = [(setting.ACT_TAG, dst),
                          (setting.ACT_FWD, setting.LOCAL)]
                entry = element.Entry(field, priority, match_field, action)
                inst = (setting.INST_FIX, region_label, entry)
                instractions.append(inst)

                path = c.shortest_pathes[src][region_label][0]
                if len(path) > 1:  # src != region_label
                    # install part. rule to forward unknown packets to
                    # corresponding auth. swich
                    field = setting.FIELD_DST
                    priority = 1
                    match_field = dst
                    action = [(setting.ACT_TAG, region_label),
                              (setting.ACT_FWD, path[1])]
                    entry = element.Entry(field, priority, match_field, action)
                    inst = (setting.INST_FIX, src, entry)
                    instractions.append(inst)

                    # install relay rule to forward packets to auth. switch
                    field = setting.FIELD_LABEL
                    priority = 50
                    match_field = region_label
                    action = [(setting.ACT_FWD, path[1])]
                    entry = element.Entry(field, priority, match_field, action)
                    inst = (setting.INST_FIX, src, entry)
                    instractions.append(inst)
                else:
                    # src == region_label: forward to local
                    field = setting.FIELD_DST
                    priority = 1
                    match_field = dst
                    action = [(setting.ACT_FWD, setting.LOCAL)]
                    entry = element.Entry(field, priority, match_field, action)
                    inst = (setting.INST_FIX, src, entry)
                    instractions.append(inst)

    n.process_ctrl_messages(instractions)

    flownum = n.traffic.flownum
    d = data.Data()
    delay = 0
    overflow_num = 0
    pktnum = 0

    for pkt in n.traffic.pkts:
        # print('processing packet');pkt.print_pkt()
        sw = n.switches[pkt.src]
        # print('arriving switch %d' % sw.label)
        hop = 0
        of = 0
        while True:
            if pkt.dst == sw.label:  # abandon using receving entry
                pkt.path.append(sw.label)
                break
            [pkt, next_hop] = sw.recv_pkt(pkt)
            # print('\tforwarding to %s' % str(next_hop))
            if next_hop == setting.CTRL:
                raise AssertionError(
                    'Error. Packets in DIFANE do not go pass controller. Exit.'
                )
            elif next_hop == setting.LOCAL:
                # perform local actions
                # install forwarding entries on shortest path
                instractions = []
                src = pkt.src
                dst = pkt.dst
                fast_path = c.shortest_pathes[src][dst][0]
                field = setting.FIELD_TP
                priority = 40
                match_field = pkt.tp
                for cnt in range(len(fast_path) - 1):
                    action = [(setting.ACT_FWD, fast_path[cnt + 1])]
                    entry = element.Entry(field, priority, match_field, action)
                    inst = (setting.INST_ADD, fast_path[cnt], entry)
                    instractions.append(inst)
                of = n.process_ctrl_messages(instractions)

                # forward
                slow_path = c.shortest_pathes[sw.label][dst][0]
                next_hop = slow_path[1]
                sw = n.switches[next_hop]
                # print('arriving switch %d' % sw.label)
            else:
                sw = n.switches[next_hop]
                # print('arriving switch %d' % sw.label)
            hop += 1
            assert hop < 10 * len(n.topo)
        # print('pkt path = {}'.format(pkt.path))

        fnum = flownum[pktnum]
        pktnum += 1
        overflow_num += of
        pkttime = c.get_delay(pkt.path, pkt.size)
        delay += pkttime

        flowsize = n.traffic.flowsize[pkt.tp]
        d.record_fct(pkt.tp, pkttime, flowsize)

        if fnum % check_interval == 0:
            if fnum not in d.delay['flownum']:
                instractions = [(setting.INST_QUERY, setting.INST_OBJ_ALL,
                                 None)]
                totentry = n.process_ctrl_messages(instractions)
                maxentry = 0
                for label in range(n.switch_num):
                    instractions = [(setting.INST_QUERY,
                                     setting.INST_OBJ_TABLE, label)]
                    maxentry = max(maxentry,
                                   n.process_ctrl_messages(instractions))

                d.record(fnum, delay, totentry, maxentry, overflow_num)
                d.print_checkpoint(fnum, log_prefix + '_checkpoint.txt')

    d.print_data(log_prefix)

    return
Exemplo n.º 13
0
    assert p.round(p.t_max[label]) == 6e6
    rule = (32, '1.2.3.4')
    p.update((setting.INFO_PACKET_IN, label, 12e6, rule))
    assert p.predict(rule, 12, label) == 6e6
    p.update((setting.INFO_FLOW_REMOVED, label, 11e6, rule))
    assert p.predict(rule, 12, label) == 3e6

    import element
    p = QPredictor()
    p.init(1)
    rule = (32, '1.2.3.4')
    timeout = p.predict(rule, 0, label)
    e = element.Entry(setting.FIELD_DSTIP,
                      32,
                      '1.2.3.4',
                      None,
                      flag=None,
                      ts=0,
                      timeout=timeout,
                      timeout_type=None)
    e.counter = 10  # 10 hits between 0~timeout then expire
    p.update((setting.INFO_FLOW_REMOVED, label, timeout, e))
    p.train()
    assert p.Q[(0,
                0)][(timeout / 1e6) - 1] == 1.0 * e.counter / (timeout / 1e6)

    p = DQNPredictor()
    p.init(1)
    rule = (32, '1.2.3.4')
    timeout = p.predict(rule, 0, label)
    e = element.Entry(setting.FIELD_DSTIP,
                      32,
Exemplo n.º 14
0
            else:
                raise NameError('Error. No such act type. Exit.')

        pkt.path.append(self.label)

        if next_hop == setting.CTRL:
            pkt.path.append(setting.CTRL)

        return [pkt, next_hop]


if __name__ == '__main__':
    label = 0
    sw = Switch(label)
    # basic tests
    entry = element.Entry(setting.FIELD_DSTIP, 32, '1.2.3.4',
                          [(setting.ACT_FWD, 1)])
    sw.add_entry(entry)
    assert sw.table_size == 1
    pkt = traffic.Packet(('0.0.0.0', '1.2.3.4'))
    [pkt, next_hop] = sw.recv_pkt(pkt)
    assert next_hop == 1
    entry = element.Entry(setting.FIELD_DSTPREFIX[24], 24, '1.2.3.0',
                          [(setting.ACT_FWD, 2)])
    sw.add_entry(entry)
    pkt = traffic.Packet(('0.0.0.0', '1.2.3.5'))
    [pkt, next_hop] = sw.recv_pkt(pkt)
    assert next_hop == 2

    setting.FLOW_TABLE_SIZE[setting.TYPE_HARDWARE] = 1
    [_, overflow] = sw.update()
    assert len(overflow) == 1
Exemplo n.º 15
0
def sdls_ctrl_simu(net,
                   log_prefix,
                   check_interval=5000,
                   upd_delay=0,
                   policy=0,
                   k=1.0,
                   ctrl_delay=setting.CONTROLLER_DELAY / 2):
    # print('***simulation begins***')

    n = net
    c = n.controller

    instractions = []
    for region_label in c.regions:
        # intra-region routing rules
        for src in c.regions[region_label]:
            for dst in c.regions[region_label]:
                if src == dst: continue
                # tag and forward by IP for src
                path = c.region_pathes[src][dst][0]
                field = setting.FIELD_DST
                priority = 1
                match_field = dst
                action = [(setting.ACT_TAG, dst),
                          (setting.ACT_FWD, setting.LOCAL)]
                entry = element.Entry(field, priority, match_field, action)
                inst = (setting.INST_FIX, src, entry)
                instractions.append(inst)
                # forward by label
                field = setting.FIELD_LABEL
                priority = 50
                match_field = dst
                for cnt in range(1, len(path) - 1):
                    action = [(setting.ACT_FWD, path[cnt + 1])]
                    entry = element.Entry(field, priority, match_field, action)
                    inst = (setting.INST_FIX, path[cnt], entry)
                    instractions.append(inst)

        # change default action
        for src in c.regions[region_label]:
            sw = n.switches[src]
            if src == region_label: continue
            else:
                path = c.region_pathes[src][region_label][0]
                action = [(setting.ACT_TAG, region_label),
                          (setting.ACT_RTAG, src), (setting.ACT_FWD, path[1])]
            sw.set_default_action(action)

        # software switch as a sender
        for dst in range(n.switch_num):
            if dst in c.regions[region_label]: continue
            fast_path = c.shortest_pathes[region_label][dst][0]
            (_, seg) = c.segments[region_label][dst][0][0]
            end_point = seg[-1]
            end_cnt = fast_path.index(end_point)
            next_begin_point = fast_path[end_cnt + 1]
            field = setting.FIELD_DST
            priority = 1
            match_field = dst
            action = [(setting.ACT_TAG, end_point),
                      (setting.ACT_RTAG, next_begin_point),
                      (setting.ACT_FWD, setting.LOCAL)]
            entry = element.Entry(field, priority, match_field, action)
            inst = (setting.INST_FIX, region_label, entry)
            instractions.append(inst)

        # inter-region routing rules
        for src in range(n.switch_num):
            for dst in range(n.switch_num):
                if c.label2region[src] == c.label2region[dst]: continue
                if dst in c.regions[region_label]: continue
                fast_path = c.shortest_pathes[src][dst][0]
                segments = c.segments[src][dst][0]

                # find the segment
                for (belong_region, seg) in segments:
                    if belong_region == region_label:
                        begin_point = seg[0]
                        end_point = seg[-1]
                        end_cnt = fast_path.index(end_point)
                        next_begin_point = fast_path[end_cnt + 1]
                        slow_path = c.region_pathes[region_label][end_point][0]
                        # install tagging rule
                        field = setting.FIELD_LABEL_RLABEL_DST
                        priority = 60
                        match_field = (region_label, begin_point, dst)
                        action = [(setting.ACT_TAG, end_point),
                                  (setting.ACT_RTAG, next_begin_point),
                                  (setting.ACT_FWD, setting.LOCAL)]
                        entry = element.Entry(field, priority, match_field,
                                              action)
                        inst = (setting.INST_FIX, region_label, entry)
                        instractions.append(inst)
                        # install rule to forward packets to another region
                        field = setting.FIELD_LABEL_RLABEL
                        priority = 50
                        match_field = (end_point, next_begin_point)
                        action = [(setting.ACT_TAG, None),
                                  (setting.ACT_RTAG, None),
                                  (setting.ACT_FWD, next_begin_point)]
                        entry = element.Entry(field, priority, match_field,
                                              action)
                        inst = (setting.INST_FIX, end_point, entry)
                        instractions.append(inst)
    n.process_ctrl_messages(instractions)

    flownum = n.traffic.flownum
    d = data.Data()
    delay = 0
    overflow_num = 0
    pktnum = 0

    inst_queue = []
    inst_point = 0

    for pkt in n.traffic.pkts:
        # print('processing packet');pkt.print_pkt()
        sw = n.switches[pkt.src]
        # print('arriving switch %d' % sw.label)
        hop = 0
        of = 0
        while True:
            if pkt.dst == sw.label:  # abandon using receving entry
                pkt.path.append(sw.label)
                break
            [pkt, next_hop] = sw.recv_pkt(pkt)
            # print('\tforwarding to %s' % str(next_hop))
            if next_hop == setting.CTRL:
                raise AssertionError(
                    'Error. Packets in SDLS do not go pass controller. Exit.')
            elif next_hop == setting.LOCAL:
                dst = pkt.dst
                # intra-region routing local action
                if c.label2region[sw.label] == c.label2region[dst]:
                    intra_path = c.region_pathes[sw.label][dst][0]

                    filed = setting.FIELD_TP
                    priority = 40
                    match_field = pkt.tp
                    action = [(setting.ACT_TAG, dst),
                              (setting.ACT_FWD, intra_path[1])]
                    entry = element.Entry(filed, priority, match_field, action)
                    instractions = [(setting.INST_ADD, sw.label, entry)]
                    of = n.process_ctrl_messages(instractions)

                    # forward
                    next_hop = intra_path[1]
                    sw = n.switches[next_hop]
                    # print('arriving switch %d' % sw.label)
                # inter-region routing local action
                else:
                    src = pkt.src
                    fast_path = c.shortest_pathes[src][dst][0]
                    segment = c.segments[src][dst][0]
                    instractions = []
                    for (belong_region,
                         seg) in segment[:-1]:  # no need for last segment
                        begin_point = seg[0]
                        end_point = seg[-1]
                        end_cnt = fast_path.index(end_point)
                        next_begin_point = fast_path[end_cnt + 1]

                        if pkt.label == end_point:
                            now_end_point = end_point
                            now_next_begin_point = next_begin_point

                        field = setting.FIELD_TP
                        priority = 40
                        match_field = pkt.tp
                        if begin_point != end_point:
                            # install forwarding entries on segment of the shortest path
                            action = [(setting.ACT_TAG, end_point),
                                      (setting.ACT_RTAG, next_begin_point),
                                      (setting.ACT_FWD, seg[1])]
                        else:
                            action = [(setting.ACT_FWD, next_begin_point)]
                        entry = element.Entry(field, priority, match_field,
                                              action)
                        inst = (setting.INST_ADD, begin_point, entry)
                        instractions.append(inst)

                    inst_queue.append((instractions, delay, pkt.tp))

                    # forward
                    if sw.label != now_end_point:
                        slow_path = c.region_pathes[sw.label][now_end_point][0]
                        next_hop = slow_path[1]
                    else:
                        next_hop = now_next_begin_point

                    sw = n.switches[next_hop]
                    # print('arriving switch %d' % sw.label)
            else:
                sw = n.switches[next_hop]
                # print('arriving switch %d' % sw.label)
            hop += 1
            assert hop < 10 * len(n.topo)
        # print('pkt path = {}'.format(pkt.path))

        if (inst_point < len(inst_queue) and
                inst_queue[inst_point][1] + ctrl_delay + upd_delay <= delay):
            new_inst_point = inst_point + 1
            while (new_inst_point < len(inst_queue)
                   and inst_queue[new_inst_point][1] + ctrl_delay < delay):
                new_inst_point += 1

            # controller update flow table in batch
            available_update = inst_queue[inst_point:new_inst_point]
            inst_point = new_inst_point
            if policy == 0:  # update all
                to_update = available_update
            elif policy == 1:  # update randomly
                from random import sample
                to_update = sample(available_update,
                                   int(k * len(available_update)))
            elif policy == 2:  # select elephant flow
                flow_cnt = {}
                for (_, _, tp) in available_update:
                    if tp in flow_cnt:
                        flow_cnt[tp] += 1
                    else:
                        flow_cnt[tp] = 1
                select_tp = sorted(flow_cnt,
                                   key=lambda e: flow_cnt[e],
                                   reverse=True)[:int(k * len(flow_cnt))]
                to_update = []
                for update in available_update:
                    if update[2] in select_tp:
                        to_update.append(update)
            else:
                raise NameError('Error. No such policy. Exit.')
                exit(1)

            for (instractions, _, _) in to_update:
                of += n.process_ctrl_messages(instractions)

        fnum = flownum[pktnum]
        pktnum += 1
        overflow_num += of
        pkttime = c.get_delay(pkt.path, pkt.size)
        delay += pkttime

        flowsize = n.traffic.flowsize[pkt.tp]
        d.record_fct(pkt.tp, pkttime, flowsize)

        if fnum % check_interval == 0:
            if fnum not in d.delay['flownum']:
                instractions = [(setting.INST_QUERY, setting.INST_OBJ_ALL,
                                 None)]
                totentry = n.process_ctrl_messages(instractions)
                maxentry = 0
                for label in range(n.switch_num):
                    instractions = [(setting.INST_QUERY,
                                     setting.INST_OBJ_TABLE, label)]
                    maxentry = max(maxentry,
                                   n.process_ctrl_messages(instractions))

                d.record(fnum, delay, totentry, maxentry, overflow_num)
                d.print_checkpoint(fnum, log_prefix + '_checkpoint.txt')

    d.print_data(log_prefix)

    return