Source code for controller_module.GLOBAL_VALUE


import networkx as nx
# RYU
from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_5
# for RYU decorator doing catch Event
from ryu.controller.handler import set_ev_cls
from ryu.controller.handler import HANDSHAKE_DISPATCHER, CONFIG_DISPATCHER, MAIN_DISPATCHER, DEAD_DISPATCHER
from ryu.controller import ofp_event
from ryu.lib.packet import ethernet, arp, icmp, ipv4
from ryu.lib.packet import ether_types, in_proto, icmpv6
from ryu.lib.packet import lldp
from ryu.lib.packet import packet
from ryu.utils import hex_array
from ryu.lib import hub
from ryu import cfg
from nested_dict import *

route_control_sem=hub.Semaphore(1)

NEED_ACTIVE_ROUTE=False
 
"""當從強化學習拿到策略才需要開始更新"""
FLOW_ENTRY_IDLE_TIMEOUT=10#sec
"""當flow entry多久沒有流量就就可刪除"""
MAX_K_SELECT_PATH=1#k shortest path最多選擇幾條多路徑
MAX_Loss_Percent=0.2
MAX_Jitter_ms=200#ms 需要預設最大的jitter可能範圍
MAX_DELAY_TO_LOSS_ms=1000#ms
"""多長的延遲被當作遺失"""
MAX_bandwidth_bytes_per_s=1000000#最大可用頻寬


ARP_SEND_FROM_CONTROLLER = b'\xff\11'  # (bytes)
OpELD_EtherType = 0x1105  
"""Openflow Extend Link Detect"""
OpEQW_EtherType = 0x5157
"""Openflow Extend QoS Weight"""
PATH = nested_dict()
"""ffdd
Tos(8bit)
QoS
bit 11     00       11      11
    delay  jitter   loss    bandwidth
priority是抽象網路切片 依靠Tos(8bit)0~255
Tos*2
__________________________________________________
table:2結構
        .
        .以此類推
        .
priority:4 Tos:1 
priority:3 Tos:1 備用路線

priority:2 Tos:0 dst:10.0.0.1
priority:1 Tos:0 dst:10.0.0.1 備用路線為了在動態路由 切換時的備用路線
priority:0 負責找不道路徑去問控制器
__________________________________________________

利用vlan_id動態切換?

起點交換機    priority:2  Tos:0 
            priority:1  Tos:0  
從頭
-s4-s3
|p1 p1
s1-s2-s3  
p2 p2
p1 p1 p1
::

    GLOBAL_VALUE.PATH[dst][priority]|["cookie"]=<class 'int'>
                            |["path"]=[[(2, 3), (2, None), (2, 2), (3, 3), (3, None), (3, 4)]]
                            |["weight"][1,2]
                            |["graph"]= nx.DiGraph()
                    
::
                    
"""

reward_max_size=3
ALL_REWARD=0
REWARD=nested_dict()
"""
這個負責統計SRC->DST路線品質
是給強化學習反饋學習用的
來源與目的地在同的交換機就不統計

::

    GLOBAL_VALUE.REWARD[SRC][dst][priority]|
                                            |["package"][封包]["start"]=time.time()
                                                             |["end"]=time.time()
                                            |["detect"]|["latency_ms"]:0~max
                                                        |["jitter_ms"]:0~max
                                                        |["bandwidth_bytes_per_s"]:0~max_bandwidth 重要!!這個代表封包傳送的頻寬
                                                        |["loss_percent"]:0~1%
::
                    
"""

MTU=1500
ip_get_datapathid_port = nested_dict()

reuse_cookie={}
cookie=1

G = nx.DiGraph()#: initial value: par1
"""有向拓樸,負責儲存整體網路狀態與拓樸


G的儲存結構

交換機($datapath.id,None)的資訊:
    ::

        GLOBAL_VALUE.G.nodes[($datapath.id,None)]
                                                |["datapath"]=<Datapath object>
                                                |["port"]={$port_id:{
                                                                    "OFPMP_PORT_DESC":{"port_no": 1, "length": 72, "hw_addr": "be:f3:b6:8a:f8:1e", "config": 0,"state": 4, "properties": [{"type": 0, "length": 32, "curr": 2112,"advertised": 0, "supported": 0, "peer": 0, "curr_speed": 10000000,"max_speed": 0}], "update_time": 1552314248.2066813},
                                                                    "OFPMP_PORT_STATS":{'length': 304, 'port_no': 2, 'duration_sec': 17, 'duration_nsec': 235000000, 'rx_packets': 11, 'tx_packets': 10, 'rx_bytes': 698, 'tx_bytes': 684, 'rx_dropped': 0, 'tx_dropped': 0, 'rx_errors': 0, 'tx_errors': 0, 'properties': [{'type': 0, 'length': 40, 'rx_frame_err': 0, 'rx_over_err': 0, 'rx_crc_err': 0, 'collisions': 0}, {'type': 65535, 'length': 184, 'experimenter': 43521, 'exp_type': 1, 'data': [0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295]}], 'update_time': 1553333684.6574402, 'rx_bytes_delta': 14, 'tx_bytes_delta': 14},
                                                                    #for ARP table
                                                                    "host":{[ip address]:[mac adress]}
                                                                    }
                                                            }
                                                #sec 'active working duration of all port '
                                                |["all_port_duration_s"]=<class 'int'>
                                                #temp when del the port, a new port restart,    #OFPMP_PORT_STATS's duration_sec will be zero
                                                |["all_port_duration_s_temp"]=<class 'int'>
                                                |["FLOW_TABLE"][$table_id<class 'int'>][$priority<class 'int'>][$match<class 'str'>]=<class 'ryu.ofproto.ofproto_v1_5_parser.OFPFlowMod'>
                                                |["now_max_group_id"]=0
                                                |["now_max_xid"]=0
                                                |["GROUP_TABLE"][$group_id<class 'int'>]=<class 'ryu.ofproto.ofproto_v1_5_parser.OFPGroupMod'>
    ::

從交換機`$datapath.id1`的`$datapath.port1` port 到 交換機`$datapath.id2`的`$datapath.port2` port的鏈路資訊:
    ::
    
        GLOBAL_VALUE.G[($datapath.id1,$datapath.port1)][($datapath.id2,$datapath.port2)]|["detect"]|["latency_ms"]:0~max
                                                                                            |["jitter_ms"]:0~max
                                                                                            |["bandwidth_bytes_per_s"]:0~max_bandwidth 重要!!這個代表鏈路可用的頻寬
                                                                                            |["loss_percent"]:0~1%
                                                                                |["tmp"][$seq]={"start":timestamp,"end":timestamp}
    ::
"""

error_search_by_xid=nested_dict(2,dict)
"""
紀錄當初xid所作的openflow message
"""
xid_sem=hub.Semaphore(1)
"""
sadd
""" 
sem = hub.Semaphore(1)
"""負責mutex get_cookie"""
barrier_lock={}
"""dd
利用DiGraph抽象全雙工,並且直接呼叫nx.shortest_path(self.G,(交換機1,None),(交換機2,None),weight="weight")導出路由細節
節點(Node)
    -交換機-這個Node會塞交換機的統計訊息
    -交換機每個port
線(Edge)
    -交換機與port
    -port與port-這個Edge會塞鏈路計算的統計訊息
所以需要check_edge_is_link,check_node_is_switch
"""

"""
            weight=0         Edge          weight=0
            +----+        +-------+        +----+
Switch1  v    | port22 v       | port55 v    |Switch2
+--------+    +--------+       +--------+    +--------+
|(1,None)|    | (1,22) |       | (2,55) |    |(2,None)|
+--------+    +--------+       +--------+    +--------+
    Node   |    ^        |       ^        |    ^  Node
            +----+        +-------+        +----+
            weight=0         Edge          weight=0
"""
# NOTE NODE STRUCT SPEC
"""
node spec
len(ofp_multipart_type)==20
""$"" mean python variable
 
                                    
"""





[docs]def get_xid(datapath_id): """ xid是標示每次發送的openflow message的id,當此openflow message發生錯誤 ddssad 控制器就會回傳此xid讓控制器知道什麼封包出錯 dsdsa dsadsa """ xid_sem.acquire() G.nodes[(datapath_id, None)]["now_max_xid"]=G.nodes[(datapath_id, None)]["now_max_xid"]+1 _xid=G.nodes[(datapath_id, None)]["now_max_xid"] xid_sem.release() return _xid
#!SECTION # ──────────────────────────────────────────────────────────────────────────────── """SECTION For DiGraph +-+-+-+ +-+-+-+-+-+-+-+ |F|o|r| |D|i|G|r|a|p|h| +-+-+-+ +-+-+-+-+-+-+-+ """
[docs]def check_node_is_switch(ID): # if ID=(datapath_id,None) it mean that node is switch if ID[1] == None: return True else: return False
[docs]def check_node_is_port(ID): # if ID=(datapath_id,None) it mean that node is switch if ID[1] != None: return True else: return False
#!SECTION zmq_socket=None