예제 #1
0
파일: RR.py 프로젝트: THU-DBLAB/IRBRL
    def one_row_observation(self):
        #NEED_Norm=True#需要正規劃?
        while True:
            jitter_ms=[]
            loss_percent=[]
            bandwidth_bytes_per_s=[]
            latency_ms=[]
            for edge in list(GLOBAL_VALUE.G.edges()):
                edge_id1 = edge[0]
                edge_id2 = edge[1]
                if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
                    #放入拓樸
                    
                    jitter_ms.append(GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["jitter_ms"])
                    loss_percent.append(GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["loss_percent"])
                    bandwidth_bytes_per_s.append(GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["bandwidth_bytes_per_s"])
                    latency_ms.append(GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["latency_ms"])
            ans=np.array([])
            ans_no_norm=np.array([])

            try:
                ans_no_norm=np.concatenate((jitter_ms,loss_percent,bandwidth_bytes_per_s,latency_ms)) 
                
                jitter_ms=np.interp(jitter_ms,(0,GLOBAL_VALUE.MAX_Jitter_ms),(0,1))
                loss_percent=np.interp(loss_percent,(0,GLOBAL_VALUE.MAX_Loss_Percent),(0,1))
                bandwidth_bytes_per_s=np.interp(bandwidth_bytes_per_s,(0,GLOBAL_VALUE.MAX_bandwidth_bytes_per_s),(0,1))
                latency_ms=np.interp(latency_ms,(0,GLOBAL_VALUE.MAX_DELAY_TO_LOSS_ms),(0,1))
                
                ans=np.concatenate((jitter_ms,loss_percent,bandwidth_bytes_per_s,latency_ms)) 
            except:
                print("one_row_observation error")
             
            if len(ans.tolist())!=0:
                return ans.tolist(),len(ans.tolist()),ans_no_norm.tolist()
            time.sleep(0.5)
예제 #2
0
def get_current_flow_group_entry(self, dst, priority):
    """
    根據dst ip與priority優先權 拿到目前網路已經設定的flow entry
    """
    all_flow_mod = []
    all_group_mod = []
    _cookie_id = GLOBAL_VALUE.get_cookie(dst, priority)
    for datapath_id in GLOBAL_VALUE.G.nodes:
        #搜尋
        if _cookie_id in GLOBAL_VALUE.G.nodes[(datapath_id,
                                               None)]["GROUP_TABLE"]:
            all_group_mod.append(
                GLOBAL_VALUE.G.nodes[(datapath_id,
                                      None)]["GROUP_TABLE"][_cookie_id])
        for match in GLOBAL_VALUE.G.nodes[(datapath_id,
                                           None)]["FLOW_TABLE"][2][priority]:
            mod = GLOBAL_VALUE.G.nodes[(
                datapath.id, None)]["FLOW_TABLE"][2][priority][match]
            try:
                ipv4_dst = msg.match.get("ipv4_dst")
                if ipv4_dst == dst:
                    all_flow_mod.append(mod)
            except:
                pass
    return all_flow_mod, all_group_mod
예제 #3
0
 def node_iteration():
     while True:
         for node_id in GLOBAL_VALUE.G.copy().nodes:
             if GLOBAL_VALUE.check_node_is_switch(node_id):
                 datapath = GLOBAL_VALUE.G.nodes[node_id]["datapath"]
                 func(datapath)
         hub.sleep(self.delta)
예제 #4
0
 def clear_link_tmp_data():
     for edge in list(GLOBAL_VALUE.G.edges()):
         edge_id1 = edge[0]
         edge_id2 = edge[1]
         if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
             # GLOBAL_VALUE.G[start_switch][end_switch]["port"][end_switch]
             link_data = GLOBAL_VALUE.G[edge_id1][edge_id2]
             link_data["tmp"] = nested_dict()
예제 #5
0
파일: RR.py 프로젝트: THU-DBLAB/IRBRL
    def check_all_edge(self)->int:
        #取出所有交換機的port

        #這裡必須等待所有交換機都連線控制器
        #FIXME 等待有更好的寫法
         
        while True:
            port_check=nested_dict(2,str)

            #確認port是否連接為host
            for node_id in GLOBAL_VALUE.G.copy().nodes:
                if GLOBAL_VALUE.check_node_is_switch(node_id):
                    for k in GLOBAL_VALUE.G.nodes[node_id]["port"]:
                        port_check[node_id[0]][k]=None
                        
                        if len(GLOBAL_VALUE.G.nodes[node_id]["port"][k]["host"])!=0:
                            pass        
                            port_check[node_id[0]][k]="host"      
            #確認port是否連接為edge
            count_edge=0
            for edge in list(GLOBAL_VALUE.G.edges()):
                edge_id1 = edge[0]
                edge_id2 = edge[1]
                
                if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
                    port_check[edge_id1[0]][edge_id1[1]]="edge"
                    port_check[edge_id2[0]][edge_id2[1]]="edge"
            print(port_check,"check_all_edge")
            #確認是否每個port連接對象完成
            check_ok=True
            count_edge=0
            for datapath_id in port_check:
                for port in port_check[datapath_id]:
                    if port_check[datapath_id][port]==None:
                        check_ok=False
                    elif port_check[datapath_id][port]=="edge":
                        count_edge=count_edge+1
            print(port_check,"check_all_edge2")
             
            if check_ok and count_edge!=0:
                return count_edge
            time.sleep(1)
예제 #6
0
 def sent_opeld_to_all_port():
     for node_id in GLOBAL_VALUE.G.copy().nodes:
         if GLOBAL_VALUE.check_node_is_switch(node_id):
             switch_data = GLOBAL_VALUE.G.nodes[node_id]
             #
             switch_data = switch_data.copy()
             for port_no in switch_data["port"].keys():
                 # if the port can working
                 if switch_data["port"][port_no]["OFPMP_PORT_DESC"]["state"] == ofproto_v1_5.OFPPS_LIVE:
                     hub.spawn(self.send_opeld_packet,
                               switch_data["datapath"], port_no, extra_byte=self.monitor_each_opeld_extra_byte, num_packets=self.monitor_sent_opedl_packets)
예제 #7
0
파일: RR.py 프로젝트: THU-DBLAB/IRBRL
    def start_dynamic_tc_module(self):
        print("start_dynamic_tc_module等待拓樸完成")
        hub.sleep(20)
        interface_list=[]
        for node_id in GLOBAL_VALUE.G.copy().nodes:
            if GLOBAL_VALUE.check_node_is_port(node_id):
                datapath_id=node_id[0]
                port_id=node_id[1]
                interface_list.append("s"+str(datapath_id)+"-eth"+str(port_id))

        self._dynamic_tc_module = Process(target=dynamic_tc.entry, args=(interface_list,))
        self._dynamic_tc_module.start()
예제 #8
0
def send_ADD_FlowMod(mod):
    """
    這裡是低階發送FlowMod為了統計與紀錄所有flow entry
    """
    datapath = mod.datapath
    OFPFlowMod = mod.__dict__
    table_id = OFPFlowMod["table_id"]
    match = OFPFlowMod["match"]
    priority = OFPFlowMod["priority"]
    ofp = datapath.ofproto
    # 要交換機當flow entry被刪除都要通知控制器
    mod.flags = ofp.OFPFF_SEND_FLOW_REM
    # if self._check_no_overlap_on_server(datapath.id,table_id,priority,match):
    mod.xid = GLOBAL_VALUE.get_xid(datapath.id)
    GLOBAL_VALUE.G.nodes[(datapath.id, None)
                    ]["FLOW_TABLE"][table_id][priority][str(match)] = mod
    GLOBAL_VALUE.error_search_by_xid[datapath.id][mod.xid]=mod
    datapath.send_msg(mod)
    #    return True
    return True
예제 #9
0
def arp_request_all(dst_ip):
    "暴力搜尋dst_ip的mac為多少:目的維護arp與了解到底哪個ip在哪個port這樣才能路由"
    for node_id in GLOBAL_VALUE.G.copy().nodes:
        if GLOBAL_VALUE.check_node_is_switch(node_id):
            switch_data = GLOBAL_VALUE.G.nodes[node_id]
            for port_no in switch_data["port"].keys():
                # if the port can working
                if switch_data["port"][port_no]["OFPMP_PORT_DESC"][
                        "state"] == ofproto_v1_5.OFPPS_LIVE:
                    # arp_src_ip="0.0.0.0"這種是ARP probe型態的封包
                    # An ARP Probe with an all-zero 'sender IP address' -rfc5227 [Page 6]
                    hub.spawn(send_arp_packet,
                              datapath=switch_data["datapath"],
                              out_port=port_no,
                              eth_src_mac='00:00:00:00:00:00',
                              eth_dst_mac="ff:ff:ff:ff:ff:ff",
                              arp_opcode=arp.ARP_REQUEST,
                              arp_src_mac='00:00:00:00:00:00',
                              arp_src_ip="0.0.0.0",
                              arp_dst_mac='00:00:00:00:00:00',
                              arp_dst_ip=dst_ip,
                              payload=GLOBAL_VALUE.ARP_SEND_FROM_CONTROLLER)
예제 #10
0
def send_add_group_mod_v1(datapath,
                          port_list: list,
                          weight_list: list,
                          group_id: int,
                          dry_run=False):
    #ofp_group_bucket_prop_weight 的weight為uint16_t所以0~65535
    #沒必要設定權重0所以要把數值壓縮在1~65535
    #注意型態weight_list [np.int64,np.int64...]
    print("send_add_group_mod_v1")
    weight_list = list(
        minmax_scale(weight_list, feature_range=(1, 65535)).astype(int))
    """
    group_id是給flow entry指引要導到哪個group entry
    """
    ofp = datapath.ofproto
    ofp_parser = datapath.ofproto_parser
    buckets = []
    #Each bucket of the group must have an unique Bucket ID-openflow1.51-p115 所以亂給個id給它 反正我沒用到
    bucket_id = 1
    for port, weight in zip(port_list, weight_list):
        #bucket_id=GLOBAL_VALUE.G.nodes[(datapath.id,None)]["now_max_group_id"]
        actions = [ofp_parser.OFPActionOutput(port)]
        #spec openflow1.5.1 p.116  struct ofp_group_bucket_prop_weight
        #注意ryu ofv1.5.1的group範例寫錯
        #下面這個寫法要靠自己挖ryu原始碼才寫出來,所以遇到問題盡量挖控制器ryu,openvswitch原始碼
        #ofp_bucket->properties->ofp_group_bucket_prop_weight-spec openflow1.5.1 p.115~p.116

        _weight = ofp_parser.OFPGroupBucketPropWeight(weight=int(weight),
                                                      length=8,
                                                      type_=ofp.OFPGBPT_WEIGHT)

        buckets.append(
            ofp_parser.OFPBucket(bucket_id=bucket_id,
                                 actions=actions,
                                 properties=[_weight]))
        bucket_id = bucket_id + 1

    #GLOBAL_VALUE.G.nodes[(datapath.id,None)]["now_max_group_id"]=GLOBAL_VALUE.G.nodes[(datapath.id,None)]["now_max_group_id"]+1
    #從多個路線根據權重(weight)隨機從buckets選一個OFPBucket(ofp.OFPGT_SELECT),OFPBucket裡面就放要actions要出去哪個port

    command = None
    if GLOBAL_VALUE.G.nodes[(datapath.id,
                             None)]["GROUP_TABLE"][group_id] == {}:
        command = ofp.OFPGC_ADD
    else:
        command = ofp.OFPGC_MODIFY
    #openvswitch擴展協議可以控制group table 的hash的演算法
    #https://github.com/openvswitch/ovs/blob/master/Documentation/group-selection-method-property.txt
    #底下黑魔法寫法 ryu的OFPGroupBucketPropExperimenter結構不適合寫我硬繞過去所以醜醜

    #目前範例不啟用

    properties = []
    """hash_alog="nohash"
    if hash_alog=="hash":
        #"hash" ascii == 0x68617368 
        hash_alog_magic=[0,0x68617368,0,0,0,0,0]
        _select_method=ofp_parser.OFPGroupBucketPropExperimenter(type_=ofp.OFPGBPT_EXPERIMENTER,exp_type=1,experimenter=0x0000154d,data=hash_alog_magic)
        properties=[_select_method]"""
    mod = ofp_parser.OFPGroupMod(datapath,
                                 command=command,
                                 type_=ofp.OFPGT_SELECT,
                                 group_id=group_id,
                                 buckets=buckets,
                                 properties=properties)
    if dry_run:
        return mod
    #xid為了讓控制器知道哪個動作是錯誤的
    mod.xid = GLOBAL_VALUE.get_xid(datapath.id)
    print("send_add_group_mod_v1acquire")

    datapath.send_msg(mod)

    print("send_add_group_mod_v1release")

    GLOBAL_VALUE.G.nodes[(datapath.id, None)]["GROUP_TABLE"][group_id] = mod
    #當發生錯誤就可以搜尋哪個動錯出錯
    GLOBAL_VALUE.error_search_by_xid[datapath.id][mod.xid] = mod
    return mod
예제 #11
0
def setting_multi_route_path(self,
                             route_path_list,
                             weight_list,
                             dst,
                             prev_path=[],
                             prev_weight=[],
                             tos=0,
                             idle_timeout=0,
                             hard_timeout=0,
                             delivery_schemes="unicast"):
    """
        這個版本比較笨需要全部刪除才能重新設定

        .. mermaid::

            graph TD
                Start --> 確保沒有其他線程正在設定dst_ip,tos的路徑
                確保沒有其他線程正在設定dst_ip,tos的路徑-->|否|確保沒有其他線程正在設定dst_ip,tos的路徑
                確保沒有其他線程正在設定dst_ip,tos的路徑-->|是|計算多條路權重合併
                計算多條路權重合併-->刪除dst_ip與tos的所有路徑
                刪除dst_ip與tos的所有路徑 -->  尋找所有岔路
                尋找所有岔路 --> 設定所有group[設定所有group entry]
                設定所有group[設定所有group entry] --> 設定非起點的flow[設定非起點的flow entry]
                設定非起點的flow[設定非起點的flow entry] --> 設定起點的flow[設定起點的flow entry]
                設定起點的flow[設定起點的flow entry] --> End

        .. mermaid::
        
            sequenceDiagram
                Title: 設定mulipath路徑流程
                autonumber
                交換機->>控制器: ofp_packet_in(flow table發生table miss的封包) 
                控制器->>控制器: 依照封包的tos去選擇,不同Qos設計出來的拓樸權重,該權重利用強化學習優化
                控制器->>交換機: ofp_group_mod(如果有岔路就需要設定group entry)

                rect rgba(0, 0, 255, .1)
                控制器->>+交換機: OFPT_BARRIER_REQUEST(確認先前設定已經完成)
                交換機->>-控制器: OFPT_BARRIER_REPLY(當完成設定就會回傳)
                Note over 交換機,控制器: 確保group entry設定完成
                end
                控制器->>交換機: ofp_flow_mod(設定非起點的flow entry,如果有岔路就需要設定group id)

                rect rgba(0, 0, 255, .1)
                控制器->>+交換機: OFPT_BARRIER_REQUEST(確認先前設定已經完成)
                交換機->>-控制器: OFPT_BARRIER_REPLY(當完成設定就會回傳)
                Note over 交換機,控制器: 確保非起點的flow entry設定完成
                end
                控制器->>交換機: ofp_flow_mod(設定起點的flow entry,如果有岔路就需要設定group id)
        """
    #確保不為空
    if route_path_list == []:
        return

    all_mod = []
    #route_path_list 必須保證free loop
    priority, dscp = prioritylib.tos_base(tos)
    #print(dst,priority)
    _cookie = GLOBAL_VALUE.get_cookie(dst, priority)

    for path, weight in zip(route_path_list, weight_list):
        a = ""
        for i in path[2::3]:
            a = a + "->" + str(i)
        #print(a)
    # https://osrg.github.io/ryu-book/zh_tw/html/spanning_tree.html
    # delivery_schemes https://en.wikipedia.org/wiki/Routing#Delivery_schemes
    # 單播多路徑unicast
    # FIXME 未來開發多播multicast dst     可能要很多個?
    # 多條路徑(route_path_list)結合每個路徑的權重(weight_list)
    # weight_list[0]代表route_path_list[0]的權重 以此類推
    # 探討group如何select bucket
    # flow_mask_hash_fields    https://github.com/openvswitch/ovs/blob/v2.15.0/lib/flow.c#L2462
    # pick_default_select_group https://github.com/openvswitch/ovs/blob/v2.15.0/ofproto/ofproto-dpif-xlate.c#L4564
    # group_best_live_bucket https://github.com/openvswitch/ovs/blob/v2.15.0/ofproto/ofproto-dpif-xlate.c#L1956

    print("載入原先的路徑")
    for path, weight in zip(prev_path, prev_weight):
        route_path_list.append(path)
        weight_list.append(weight)
    #紀錄每個交換機需要OUTPUT的
    print("紀錄每個交換機需要OUTPUT的")
    _switch = nested_dict(2, dict)
    for path, weight in zip(route_path_list, weight_list):
        for i in path[2::3]:
            set_datapath_id = i[0]
            set_out_port = i[1]
            if _switch[set_datapath_id][set_out_port] != {}:
                #FIXME 多條路線經過同的路徑 權重利用平均 最小數值為1
                _switch[set_datapath_id][set_out_port] = max(
                    int((_switch[set_datapath_id][set_out_port] + weight) / 2),
                    1)
            else:
                _switch[set_datapath_id][set_out_port] = weight
    print("刪除光原先的group entry flow entry重新設定")
    #刪除光原先的group entry flow entry重新設定
    self.clear_multi_route_path(dst, priority)
    print("設定只有岔路需要設定group entry")
    #設定只有岔路需要設定group entry
    set_switch_for_barrier = set()
    for set_datapath_id in _switch:
        tmp_datapath = GLOBAL_VALUE.G.nodes[(set_datapath_id,
                                             None)]["datapath"]
        ofp = tmp_datapath.ofproto
        parser = tmp_datapath.ofproto_parser
        #       交換機出路大於2大表有岔路               and  此交換機還沒設定過group entry
        if len(_switch[set_datapath_id].keys()
               ) >= 2 and set_datapath_id not in set_switch_for_barrier:
            port_list = list(_switch[set_datapath_id].keys())
            group_weight_list = []
            for p in list(_switch[set_datapath_id].keys()):
                group_weight_list.append(_switch[set_datapath_id][p])
            group_mod = OFPT_GROUP_MOD.send_add_group_mod_v1(tmp_datapath,
                                                             port_list,
                                                             group_weight_list,
                                                             group_id=_cookie)
            all_mod.append(group_mod)
            set_switch_for_barrier.add(tmp_datapath)

    print("確保剛才group entry 設定完成這樣後面用到group entry的路線才不會錯誤")
    #確保剛才group entry 設定完成這樣後面用到group entry的路線才不會錯誤
    for tmp_datapath in set_switch_for_barrier:
        self.wait_finish_switch_BARRIER_finish(tmp_datapath)

    #開始設定除了起點的flow entry
    print("開始設定除了起點的flow entry")
    set_switch_for_barrier = set()
    for path, weight in zip(route_path_list, weight_list):
        for i in path[5::3]:
            set_datapath_id = i[0]
            set_out_port = i[1]
            tmp_datapath = GLOBAL_VALUE.G.nodes[(set_datapath_id,
                                                 None)]["datapath"]
            set_switch_for_barrier.add(tmp_datapath)
            ofp = tmp_datapath.ofproto
            parser = tmp_datapath.ofproto_parser
            match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                    ipv4_dst=dst,
                                    ip_dscp=dscp)
            if len(_switch[set_datapath_id].keys()) >= 2:
                #有岔路需要group entry
                action = [parser.OFPActionGroup(group_id=_cookie)]
                instruction = [
                    parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
                                                 action)
                ]
                mod = parser.OFPFlowMod(datapath=tmp_datapath,
                                        priority=priority,
                                        table_id=2,
                                        command=ofp.OFPFC_ADD,
                                        match=match,
                                        cookie=_cookie,
                                        instructions=instruction,
                                        idle_timeout=idle_timeout,
                                        hard_timeout=hard_timeout)
                all_mod.append(mod)
                OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
            else:
                #沒有岔路不需要group entry
                action = [parser.OFPActionOutput(port=set_out_port)]
                instruction = [
                    parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
                                                 action)
                ]
                mod = parser.OFPFlowMod(datapath=tmp_datapath,
                                        priority=priority,
                                        table_id=2,
                                        command=ofp.OFPFC_ADD,
                                        match=match,
                                        cookie=_cookie,
                                        instructions=instruction,
                                        idle_timeout=idle_timeout,
                                        hard_timeout=hard_timeout)
                all_mod.append(mod)
                OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
    #確保已經設定
    print("確保已經設定")
    for tmp_datapath in set_switch_for_barrier:
        self.wait_finish_switch_BARRIER_finish(tmp_datapath)
    set_switch_for_barrier = set()
    #全部設定完成 才能開始設定開頭的路線
    print("全部設定完成 才能開始設定開頭的路線")
    for path, weight in zip(route_path_list, weight_list):
        i = path[2]  #開頭
        set_datapath_id = i[0]
        set_out_port = i[1]
        tmp_datapath = GLOBAL_VALUE.G.nodes[(set_datapath_id,
                                             None)]["datapath"]
        set_switch_for_barrier.add(tmp_datapath)
        ofp = tmp_datapath.ofproto
        parser = tmp_datapath.ofproto_parser
        match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                ipv4_dst=dst,
                                ip_dscp=dscp)
        if len(_switch[set_datapath_id].keys()) >= 2:
            action = [parser.OFPActionGroup(group_id=_cookie)]
            instruction = [
                parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, action)
            ]
            all_mod.append(mod)
            mod = parser.OFPFlowMod(datapath=tmp_datapath,
                                    priority=priority,
                                    table_id=2,
                                    command=ofp.OFPFC_ADD,
                                    match=match,
                                    cookie=_cookie,
                                    instructions=instruction,
                                    idle_timeout=idle_timeout,
                                    hard_timeout=hard_timeout)
            all_mod.append(mod)
            OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
        else:
            action = [parser.OFPActionOutput(port=set_out_port)]
            instruction = [
                parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, action)
            ]
            mod = parser.OFPFlowMod(datapath=tmp_datapath,
                                    priority=priority,
                                    table_id=2,
                                    command=ofp.OFPFC_ADD,
                                    match=match,
                                    cookie=_cookie,
                                    instructions=instruction,
                                    idle_timeout=idle_timeout,
                                    hard_timeout=hard_timeout)
            all_mod.append(mod)
            OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
    print("BARRIER 全部設定完成")
    for tmp_datapath in set_switch_for_barrier:
        self.wait_finish_switch_BARRIER_finish(tmp_datapath)
    print("BARRIER finish 全部設定完成")
    # FIXME 這個數值有最大值 需要回收
    GLOBAL_VALUE.PATH[dst][priority]["cookie"] = _cookie
    if GLOBAL_VALUE.PATH[dst][priority]["path"] == {}:
        GLOBAL_VALUE.PATH[dst][priority]["path"] = []
    if GLOBAL_VALUE.PATH[dst][priority]["weight"] == {}:
        GLOBAL_VALUE.PATH[dst][priority]["weight"] = []

    for p, w in zip(route_path_list, weight_list):
        if p not in GLOBAL_VALUE.PATH[dst][priority]["path"]:
            GLOBAL_VALUE.PATH[dst][priority]["path"].append(p)
            GLOBAL_VALUE.PATH[dst][priority]["weight"].append(w)

    if GLOBAL_VALUE.PATH[dst][priority]["graph"] == {}:
        GLOBAL_VALUE.PATH[dst][priority]["graph"] = nx.DiGraph()

    for path in route_path_list:
        prev_node = None
        for node in path:
            if prev_node != None:
                if GLOBAL_VALUE.PATH[dst][priority]["graph"] == {}:
                    GLOBAL_VALUE.PATH[dst][priority]["graph"] = nx.DiGraph()
                GLOBAL_VALUE.PATH[dst][priority]["graph"].add_edge(prev_node,
                                                                   node,
                                                                   weight=1)
            prev_node = node
    #print(all_mod)
    return all_mod
예제 #12
0
파일: RR.py 프로젝트: THU-DBLAB/IRBRL
    def _update_tui(self):
        title = """
███████╗██████╗ ███╗   ██╗    ███╗   ███╗ ██████╗ ███╗   ██╗██╗████████╗ ██████╗ ██████╗
██╔════╝██╔══██╗████╗  ██║    ████╗ ████║██╔═══██╗████╗  ██║██║╚══██╔══╝██╔═══██╗██╔══██╗
███████╗██║  ██║██╔██╗ ██║    ██╔████╔██║██║   ██║██╔██╗ ██║██║   ██║   ██║   ██║██████╔╝
╚════██║██║  ██║██║╚██╗██║    ██║╚██╔╝██║██║   ██║██║╚██╗██║██║   ██║   ██║   ██║██╔══██╗
███████║██████╔╝██║ ╚████║    ██║ ╚═╝ ██║╚██████╔╝██║ ╚████║██║   ██║   ╚██████╔╝██║  ██║
╚══════╝╚═════╝ ╚═╝  ╚═══╝    ╚═╝     ╚═╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝   ╚═╝    ╚═════╝ ╚═╝  ╚═╝Author:Lu-Yi-Hsun
        """
        Mapping_idx = 0
        MAX_TUI_LINE = 300
        for idx, i in enumerate(title.split("\n")):
            self.TUI_Mapping.append(i)
            Mapping_idx = idx
        for i in range(MAX_TUI_LINE):
            self.TUI_Mapping.append("")
        Mapping_start = Mapping_idx+1
        while True:
            Mapping_idx = Mapping_start
            for node_id in GLOBAL_VALUE.G.copy().nodes:
                if GLOBAL_VALUE.check_node_is_switch(node_id):
                    switch_title = Mapping_idx
                    Mapping_idx += 1
                    if_EDGE_SWITCH = ""
                    for port in GLOBAL_VALUE.G.copy().nodes[node_id]["port"].keys():
                        host = GLOBAL_VALUE.G.nodes[node_id]["port"][port]["host"]
                        if host != {}:
                            if_EDGE_SWITCH = "Edge Switch"
                        stats = GLOBAL_VALUE.G.nodes[node_id]["port"][port]["OFPMP_PORT_STATS"]
                        desc = GLOBAL_VALUE.G.nodes[node_id]["port"][port]["OFPMP_PORT_DESC"]
                        line = "★ port"+str(port)+" state "+str(desc["state"])+" duration_sec "+str(stats["duration_sec"])+" rx_bytes "+str(stats["rx_bytes"])+" tx_bytes "+str(
                            stats["tx_bytes"])+" rx_bytes_delta "+str(stats["rx_bytes_delta"])+" tx_bytes_delta "+str(stats["tx_bytes_delta"])+" host "+str(host)
                        self.TUI_Mapping[Mapping_idx] = line
                        Mapping_idx += 1

                    line = "datapath ID"+str(node_id)+" "+if_EDGE_SWITCH
                    self.TUI_Mapping[switch_title] = line
                    line = "all_port_duration_s " + \
                        str(GLOBAL_VALUE.G.nodes[node_id]["all_port_duration_s"])
                    self.TUI_Mapping[Mapping_idx] = line
                    """
                    'duration_sec': 26664, 'duration_nsec': 862000000, 'rx_packets': 22, 'tx_packets': 19
                    5, 'rx_bytes': 1636, 'tx_bytes': 12016, 'rx_dropped': 0, 'tx_dropped': 0, 'rx_errors': 0, 'tx_errors': 0
                    """
                    Mapping_idx += 1
                    self.TUI_Mapping[Mapping_idx] = ""
                    Mapping_idx += 1
                    self.TUI_Mapping[Mapping_idx] = "Show Flow Entry"
                    Mapping_idx += 1
                    for table_id in GLOBAL_VALUE.G.copy().nodes[node_id]["FLOW_TABLE"]:
                        for priority in GLOBAL_VALUE.G.copy().nodes[node_id]["FLOW_TABLE"][table_id]:
                            for match in GLOBAL_VALUE.G.copy().nodes[node_id]["FLOW_TABLE"][table_id][priority]:
                                self.TUI_Mapping[Mapping_idx] = "table_id: "+str(
                                    table_id)+" priority: "+str(priority)+" match: "+str(match)
                                Mapping_idx += 1

            self.TUI_Mapping[Mapping_idx] = "Topology Link"
            Mapping_idx += 1
            # self.TUI_Mapping[Mapping_idx]=str(GLOBAL_VALUE.G.edges())
            # print(GLOBAL_VALUE.G.edges())
            for edge in list(GLOBAL_VALUE.G.edges()):
                edge_id1 = edge[0]
                edge_id2 = edge[1]
                if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
                    # GLOBAL_VALUE.G[start_switch][end_switch]["port"][end_switch]
                    ed = GLOBAL_VALUE.G[edge_id1][edge_id2]
                    edge_start = "datapath ID " + \
                        str(edge_id1[0]) + " port_no "+str(edge_id1[1])
                    edge_end = "datapath ID " + \
                        str(edge_id2[0]) + " port_no "+str(edge_id2[1])

                    edge_data = edge_start+" ---> "+edge_end

                    self.TUI_Mapping[Mapping_idx] = edge_data
                    Mapping_idx += 1

                    link_data = ""

                    loss_percent = str(ed["detect"]["loss_percent"])
                    bandwidth_bytes_per_s = str(
                        ed["detect"]["bandwidth_bytes_per_s"])
                    latency_ms = str(ed["detect"]["latency_ms"])
                    jitter_ms = str(ed["detect"]["jitter_ms"])

                    link_data = "loss_percent:"+loss_percent + \
                        " "+"bandwidth_bytes_per_s:"+bandwidth_bytes_per_s+" " + \
                            "latency_ms:"+latency_ms+" "+"jitter_ms"+jitter_ms
                    # print(link_data)
                    self.TUI_Mapping[Mapping_idx] = link_data
                    Mapping_idx += 1
  #              GLOBAL_VALUE.G[start_switch][end_switch]["detect"][link_index]["jitter_ms"]=jitter#millisecond
   #             GLOBAL_VALUE.G[start_switch][end_switch]["detect"][link_index]["loss_percent"]=loss#%how many percent of the packet loss
    #            GLOBAL_VALUE.G[start_switch][end_switch]["detect"][link_index]["bandwidth_bytes_per_s"]=bw#
     #           GLOBAL_VALUE.G[start_switch][end_switch]["detect"][link_index]["latency_ms"]=delay_one_packet#from a to b ,just one way ,millisecond
      #          GLOBAL_VALUE.G[start_switch][end_switch]["weight"]=formula.OSPF(bw*8)

            for i in range(30):
                self.TUI_Mapping[Mapping_idx] = ""
                Mapping_idx += 1

            hub.sleep(1)
예제 #13
0
파일: RR.py 프로젝트: THU-DBLAB/IRBRL
    def rl_zmq_connecter(self):
        """
        這裡負責傳送必要資訊給強化學習並且拿回策略
        """
        self.clear_temp_file()
        print("請至少等待所有交換機都連線完成")
        time.sleep(10)

        #FIXME 這裡要處理等待拓樸探索完成,必須等待拓樸建構完成才知道強化學習輸出的結構,缺點無法應用在拓樸頻繁更動的環境
        count_edge=self.check_all_edge()
         
        
        #  Send reply back to client
        _,observation_space,_=self.one_row_observation()
        init_RL={"action_space":count_edge,"observation_space":observation_space}
        print(init_RL)
        init_RL_str=json.dumps(init_RL)
        action_uuid=0
        self.write_for_rl(str(init_RL_str))
        
        while True:
            #  Wait for next request from client
             
            message = self.read_for_robot()
            
            #  Do some 'work'
             
            try:
                message_list=json.loads(message)
                message_action_uuid=int(message_list["action_uuid"])
                #print(message_action_uuid,action_uuid)
                if message_action_uuid<action_uuid:
                    #為了確保action是新的
                    continue
                action_uuid=message_action_uuid
                message_list=message_list["action"]
            except:
                hub.sleep(1)
                continue
            print("ACTIONs",message_list)
            e_index=0
            #把ai回傳的權重放入拓樸
            for edge in list(GLOBAL_VALUE.G.edges()):
                edge_id1 = edge[0]
                edge_id2 = edge[1]
                if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
                    #放入拓樸
                    #每個
                    #print(edge_id1,edge_id2)
                    GLOBAL_VALUE.G[edge_id1][edge_id2]["ppinin"]=message_list[e_index]
                    e_index=e_index+1
                    print("權重\n\n") 
                    print(edge_id1,edge_id2,GLOBAL_VALUE.G[edge_id1][edge_id2]["ppinin"])
                    print("權重\n\n")  

            GLOBAL_VALUE.NEED_ACTIVE_ROUTE=True

            #這裡設定-10為了當沒有封包流動reward應該0但是一直頻繁設定網路我給負號獎勵
             
            time.sleep(10)
             
            #  Send reply back to client
            GLOBAL_VALUE.ALL_REWARD=GLOBAL_VALUE.ALL_REWARD-10
            obs,_,obs_no_norm=self.one_row_observation()
            step_data={"action_uuid":action_uuid,"obs":list(obs),"obs_no_norm":list(obs_no_norm),"reward":GLOBAL_VALUE.ALL_REWARD}
            
            #FIXME 回傳
            print("step_data",step_data)
            self.write_for_rl(str(json.dumps(step_data)))
예제 #14
0
def setting_multi_route_path_base_vlan(self, route_path_list, weight_list,
                                       ipv4_dst, ipv4_src):
    #利用vlan tag把每個simple path切開
    #舉例有5條路線
    #起始:一開始起點交換機就要從group entry裡面5個bucket選擇一個bucket,每個bucket代表某一條simple path,bucket做三個動作 1."Push VLAN header" 2."Set-Field VLAN_VID value"3."Output port" VLAN_VID為此simple path push vlan tag
    #中間:路由根據src dst vlan_id 去路由
    #最後:終點交換機要pop vlan tag才丟給host
    """
        非常重要要注意要清楚 vlan運作模式
        不管有沒有塞入vlan,ethertype永遠不變,只會向後擠
        還沒塞入vlan
        |dst-mac|src-mac|ethertype|payload
        塞入vlan
        |dst-mac|src-mac|0x8100|tci|ethertype|payload
        """
    priority = 2
    idle_timeout = 5
    _cookie = GLOBAL_VALUE.get_cookie()
    vlan_tag = 1
    for path in route_path_list:
        vlan_tci = ofproto_v1_5.OFPVID_PRESENT + vlan_tag  #spec openflow1.5.1 p.82,你要多加這個openvswitch才知道你要設定vlan_vid
        #path:[(1, 4), (1, None), (1, 2), (3, 1), (3, None), (3, 2), (4, 2), (4, None), (4, 3)]
        for index, i in enumerate(path[5::3]):
            set_datapath_id = i[0]
            set_out_port = i[1]
            tmp_datapath = GLOBAL_VALUE.G.nodes[(set_datapath_id,
                                                 None)]["datapath"]
            ofp = tmp_datapath.ofproto
            parser = tmp_datapath.ofproto_parser
            if index == (len(path) / 3) - 2:
                #最後
                #print("最後")
                match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                        vlan_vid=vlan_tci,
                                        ipv4_src=ipv4_src,
                                        ipv4_dst=ipv4_dst)
                action_set = [
                    parser.OFPActionPopVlan(),
                    parser.OFPActionOutput(port=set_out_port)
                ]
                instruction = [
                    parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
                                                 action_set)
                ]
                mod = parser.OFPFlowMod(datapath=tmp_datapath,
                                        priority=priority,
                                        table_id=2,
                                        command=ofp.OFPFC_ADD,
                                        match=match,
                                        cookie=_cookie,
                                        instructions=instruction,
                                        idle_timeout=idle_timeout)
                OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
            else:
                #中間
                #print("中間")
                match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                                        vlan_vid=vlan_tci,
                                        ipv4_dst=ipv4_dst,
                                        ipv4_src=ipv4_src)
                action = [parser.OFPActionOutput(port=set_out_port)]
                instruction = [
                    parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS,
                                                 action)
                ]
                mod = parser.OFPFlowMod(datapath=tmp_datapath,
                                        priority=priority,
                                        table_id=2,
                                        command=ofp.OFPFC_ADD,
                                        match=match,
                                        cookie=_cookie,
                                        instructions=instruction,
                                        idle_timeout=idle_timeout)
                OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
        vlan_tag = vlan_tag + 1
    #起始
    port_list = []
    vlan_tag = []
    vlan_index = 1
    for path in route_path_list:
        i = path[2]
        set_datapath_id = i[0]
        set_out_port = i[1]
        port_list.append(set_out_port)
        tmp_datapath = GLOBAL_VALUE.G.nodes[(set_datapath_id,
                                             None)]["datapath"]
        vlan_tag.append(vlan_index)
        vlan_index = vlan_index + 1
        #保證剛才路徑設定完成
        self.wait_finish_switch_BARRIER_finish(tmp_datapath)
    ofp = tmp_datapath.ofproto
    parser = tmp_datapath.ofproto_parser
    send_add_group_mod(self,
                       tmp_datapath,
                       port_list,
                       weight_list,
                       vlan_tag_list=vlan_tag,
                       group_id=_cookie)

    #確保先前的所有設定已經完成,才能開始設定起點的flow table
    #如果不確保會導致封包已經開始傳送但是路徑尚未設定完成的錯誤

    #保證group 設定完成
    self.wait_finish_switch_BARRIER_finish(tmp_datapath)
    match = parser.OFPMatch(eth_type=ether_types.ETH_TYPE_IP,
                            ipv4_dst=ipv4_dst,
                            ipv4_src=ipv4_src)
    action = [parser.OFPActionGroup(group_id=_cookie)]
    instruction = [
        parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, action)
    ]
    mod = parser.OFPFlowMod(datapath=tmp_datapath,
                            priority=priority,
                            table_id=2,
                            command=ofp.OFPFC_ADD,
                            match=match,
                            cookie=_cookie,
                            instructions=instruction,
                            idle_timeout=idle_timeout)
    OFPT_FLOW_MOD.send_ADD_FlowMod(mod)
    #上面都完成就紀錄

    GLOBAL_VALUE.PATH[ipv4_src][ipv4_dst]["cookie"][_cookie] = route_path_list
예제 #15
0
        def _update_link():
            print("_update_link")
            def clear_link_tmp_data():
                for edge in list(GLOBAL_VALUE.G.edges()):
                    edge_id1 = edge[0]
                    edge_id2 = edge[1]
                    if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
                        # GLOBAL_VALUE.G[start_switch][end_switch]["port"][end_switch]
                        link_data = GLOBAL_VALUE.G[edge_id1][edge_id2]
                        link_data["tmp"] = nested_dict()

            def sent_opeld_to_all_port():
                for node_id in GLOBAL_VALUE.G.copy().nodes:
                    if GLOBAL_VALUE.check_node_is_switch(node_id):
                        switch_data = GLOBAL_VALUE.G.nodes[node_id]
                        #
                        switch_data = switch_data.copy()
                        for port_no in switch_data["port"].keys():
                            # if the port can working
                            if switch_data["port"][port_no]["OFPMP_PORT_DESC"]["state"] == ofproto_v1_5.OFPPS_LIVE:
                                hub.spawn(self.send_opeld_packet,
                                          switch_data["datapath"], port_no, extra_byte=self.monitor_each_opeld_extra_byte, num_packets=self.monitor_sent_opedl_packets)
            while True:
                hub.sleep(1)
                #計算reward
                self.reward_cal()
                # 統計鏈路
                # NOTE start
                # print(GLOBAL_VALUE.G.nodes[datapath.id]["port"][1]["OFPMP_PORT_DESC"]["properties"],datapath.id)
                clear_link_tmp_data()  # 重算所有統計
                # sent opeld to all port of each switch for doing link detect and topology detect
                sent_opeld_to_all_port()  # 發送封包
                # wait for packet back
                hub.sleep(self.monitor_wait_opeld_back)
                # print(GLOBAL_VALUE.G[2][1]["tmp"])
                # print(GLOBAL_VALUE.G[2][1]["port"])
                for edge in list(GLOBAL_VALUE.G.edges()):
                    edge_id1 = edge[0]
                    edge_id2 = edge[1]
                    if GLOBAL_VALUE.check_edge_is_link(edge_id1, edge_id2):
                        start_switch = (edge_id1[0], None)
                        start_port_number = edge_id1[1]
                        end_switch = (edge_id2[0], None)
                        end_port_number = edge_id2[1]
                        # print(GLOBAL_VALUE.G[start_switch][end_switch]["tmp"])
                        packet_start_time = []
                        packet_end_time = []
                        seq_packet = GLOBAL_VALUE.G[edge_id1][edge_id2]["tmp"]
                        get_packets_number = len(seq_packet.keys())
                        # latency
                        for seq in seq_packet.keys():
                            packet_start_time.append(
                                seq_packet[seq]["start"])
                            packet_end_time.append(seq_packet[seq]["end"])
                        latency = []
                        for s_t, e_t in zip(packet_start_time, packet_end_time):
                            latency.append(e_t-s_t)

                        #all_t = max(packet_end_time)-min(packet_start_time)
                        # jitter

                        if len(packet_end_time) != 0 or len(packet_start_time) != 0:

                            curr_speed = min(int(GLOBAL_VALUE.G.nodes[start_switch]["port"][start_port_number]["OFPMP_PORT_DESC"]["properties"][0]["curr_speed"]), int(
                                GLOBAL_VALUE.G.nodes[end_switch]["port"][end_port_number]["OFPMP_PORT_DESC"]["properties"][0]["curr_speed"]))  # curr_speed kbps

                            tx_bytes_delta = int(
                                GLOBAL_VALUE.G.nodes[start_switch]["port"][start_port_number]["OFPMP_PORT_STATS"]["tx_bytes_delta"])

                            jitter = abs(np.std(latency) * 1000)  # millisecond
                            # A. S. Tanenbaum and D. J. Wetherall, Computer Networks, 5th ed. Upper Saddle River, NJ, USA: Prentice Hall Press, 2010.
                            # "The variation (i.e., standard deviation) in the delay or packet arrival times is called jitter."
                            # default one packet from A TO B latency millisecond(ms)
                            delay_one_packet = abs(np.mean(latency)*1000)
                            loss = 1-(get_packets_number /
                                      self.monitor_sent_opedl_packets)
                            # bytes_s=(get_packets_number*(self.monitor_each_opeld_extra_byte+16))/all_t

                            # available using bandwith bytes per second
                            # curr_speed is kbps
                            bw = ((1000*curr_speed)/8) - \
                                (tx_bytes_delta/self.delta)
                            # print(start_switch,end_switch,link_index,"jitter",jitter,"delay_one_packet",delay_one_packet,"loss",loss,"gbytes_s",bw)

                            # millisecond
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["jitter_ms"] = jitter
                            # %how many percent of the packet loss
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["loss_percent"] = loss
                            # available bandwidth
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["bandwidth_bytes_per_s"] = bw
                            # from a to b ,just one way ,millisecond
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["detect"]["latency_ms"] = delay_one_packet

                            # 這裡你可以自創演算法去評估權重
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["weight"] = delay_one_packet#formula.OSPF(bw*8)
                            #GLOBAL_VALUE.G[edge_id1][edge_id2]["ppinin"] = delay_one_packet
                             

                            #GLOBAL_VALUE.G[edge_id1][edge_id2]["ppinin"]=0

                            #print(GLOBAL_VALUE.G[edge_id1][edge_id2]["weight"],"weight")
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["hop"] = 1
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["low_delay"] = delay_one_packet
                            GLOBAL_VALUE.G[edge_id1][edge_id2]["low_jitter"] = jitter

                            GLOBAL_VALUE.G[edge_id1][edge_id2]["EIGRP"] = formula.EIGRP(
                                (bw*8)/1000, curr_speed, tx_bytes_delta, delay_one_packet, loss)
                            if self.set_weight_call_back_function != None:
                                self.set_weight_call_back_function(GLOBAL_VALUE.G[edge_id1][edge_id2], jitter, loss, bw, delay_one_packet)