Esempio n. 1
0
    def connect_all(self):
        """
        尝试连接之前初始化好的所有接口
        (因为初始化好的接口还没有得到socket相当于还没有连网线)
        由于是初始化好的接口,因此默认假设一定全都能连上,只是时间早晚的问题
        处理了:对方没有上线的情况 方法:晚一点再连

        这里如果要优化,可以使用一个队列,
        如果这个连接失败,放到队列末端,然后只要队列不空就继续循环取队头并尝试连接
        直到队列为空。
        """
        # NOTICE: O(n^2)
        while len(self.hosts) != self.connected_cnt:
            for host in self.hosts:
                # is_connected = False
                # for subnet in self.subnets:
                #     if subnet.prefix == Host.getSubnetPrefix(host):
                #         is_connected = True
                #         break
                if host.status == "down":
                    ret = self.try_connect(host)
                    # logger.debug("Trying connect %s -> %s", host.vip, host.counter_vip)
                    if ret == 0:  #TODO macro for SUCCESS ?
                        self.connected_cnt = self.connected_cnt + 1
                        logger.debug("Interface %s is on, connected to %s",
                                     host.vip, host.counter_vip)
                        host.status = "on"
Esempio n. 2
0
def ask_for_global_table():
    controller_index = config_data['controller_index']
    src_ip = ''
    dst_ip = ''
    netmask = ''
    for interface in config_data['interfaces']:
        if interface['counter_index'] != controller_index:
            continue
        # now counter_index is controller_index
        src_ip = interface['vip']
        dst_ip = interface['counter_vip']
        netmask = interface['netmask']
    logger.debug(
        'going to send route table request msg\n, \
        src_ip %s, dst_ip %s, netmask %s', src_ip, dst_ip, netmask)
    request_msg = {
        "code": 0,
        "msg": "request for route table",
        "src_index": ROUTER_INDEX
    }
    msg_bytes = utilities.objEncode(request_msg)
    pkg = route.IP_Package(src_ip, dst_ip, dst_ip, netmask, msg_bytes)
    pkg.protocol = 119
    errno = route.link_layer.send(pkg.to_bytes())
    if errno < 0:
        logger.warning('fail to send to link layer, errno: %d', errno)
 def run(self) -> None:
     logger.debug('network layer listerner begin to work')
     while True:
         recv = self.network_layer.recv()
         if recv:
             logger.info('network layer pkg received\n{}'.format(recv))
         time.sleep(0.1)
Esempio n. 4
0
 def broadcastMsg(self, data, protocol=0):
     interfaces = self.network_layer.interfaces
     for interface in interfaces:
         sip = interface.vip
         dip = interface.counter_vip
         logger.debug('broadcast to ip %s', dip)
         self.network_layer.send(sip, dip, utilities.objEncode(data),
                                 protocol)
Esempio n. 5
0
 def run_ping(self):
     logger.info("tracking direct router neighbor threading run...")
     for interface in self.network_layer.interfaces:
         src_ip = interface.vip
         dst_ip = interface.counter_vip
         netmask = interface.netmask
         msg = {'code': 0, 'msg': "are you still here?"}
         self.network_layer.send(src_ip, dst_ip, utilities.objEncode(msg),
                                 100)
         logger.debug('send ping from %s to %s', src_ip, dst_ip)
Esempio n. 6
0
 def broadcast_logout(self, index):
     global msgID
     logger.debug('###########broadcasting!!!!!########')
     logger.debug('broadcast,  id is %d, from index %d', msgID,
                  ROUTER_INDEX)
     for interface in self.interfaces:
         src_ip, dst_ip = interface
         msg = {"type": "logout", "index": index, "id": msgID}
         msgID += V
         self.network_layer.send(src_ip, dst_ip, utilities.objEncode(msg),
                                 119)
Esempio n. 7
0
    def run(self):
        """ 从队列中拿到一个包,做适当转换后,交给链路层 """
        while True:
            # 如果队列为空,那就等直到队列中有包
            while route_send_package.qsize() == 0:
                # NOTICE:此处循环可能会导致性能下降,CPU占用率100%
                time.sleep(0.2)
                continue
            # 从队列中获得一个包
            ip_package = route_send_package.get()

            # DEBUG信息
            logger.debug(' this package will be modiflied according to route table !')
            logger.debug(ip_package)

            # 使用成员函数处理IP包,修改其中的dest_ip字段,获得新的IP包
            ret_ip_package = self.ip_package_modifier(ip_package) # type: Optional["IP_Package"]
            if ret_ip_package == None:
                logger.info('{} is unreachable. \nShow your route table by "show route table"'.format(ip_package.final_ip))
                continue
            # DEBUG信息
            logger.debug('ip pkg has been modified. now forwarding...\n modified package is below')
            logger.debug(ret_ip_package)

            # 发送IP包
            link_layer.send(ret_ip_package.to_bytes())
Esempio n. 8
0
    def __init__(self, config) -> None:
        # NOTICE:这里有两种方案,一种是传json字符串,另一种是传文件名,然后就可以在路由器内部进行读取配置文件初始化
        # 从配置文件中初始化各项数据
        self.name = config['name']
        self.index = config['index']

        # 开启转发线程
        logger.debug('my_package_forward_thread start!')
        my_package_forward_thread.start()
        # 开启链路层监听线程,用于从链路层得到包
        my_monitor_link_layer.start()
        # 初始化转发表
        self.init_route_table(config)
        # 初始化网线接口
        self.interfaces = []
        self.init_interfaces(config)
Esempio n. 9
0
 def __init__(self, hosts, subnets):
     threading.Thread.__init__(self)
     self.hosts = hosts
     self.subnets = subnets
     for host in self.hosts:
         subnet_prefix = host.getSubnetPrefix(
         )  # use member function host.getSubnetPrefix, which call utilities.getSubnet()
         new_subnet = Subnet(subnet_prefix)
         # 新的子网中加入这台主机
         new_subnet.hosts.append(host)
         # 链路层子网列表中加入这个子网
         self.subnets.append(new_subnet)
         # 这台主机(该子网第一台主机)的监听线程开始工作
         host.start()
         logger.debug("Interface %s listening", host.vip)
     self.connected_cnt = 0
Esempio n. 10
0
def init_global_route_table(config_file: str, src: int) -> None:
    """
    用SPFA算法,读取配置文件,更新路由表中的最短路信息
    input:
        config_file: 储存有“所有route配置文件的文件名”文件名
    """
    interface2index.clear()
    index2interface.clear()
    graph_reset()
    logger.debug("[spfa] init graph\n %s", format(graph))
    for filename in json_files['filenames']:
        f = open(CONFIG_ROOT + '/' +
                 filename)  #TODO:(YB) refactor. let it be path.resolve
        json_data = json.load(f)
        f.close()

        node = json_data['index']  # 当前配置文件/test/route*.json的路由标号
        interfaces = json_data['interfaces']
        for interface in interfaces:
            cvip = interface['counter_vip']
            netmask = interface['netmask']

            # interface2index 记录了所有的interfaces.它是一个从interface到所属路由的映射。
            interface2index[(cvip, netmask)] = interface['counter_index']
            if interface['counter_index'] == src:
                # index2interface,
                # idx -> intf
                # 记录了,站在本路由的角度,到达idx这个路由,需要通过的intf是什么
                index2interface[node] = (interface['vip'],
                                         interface['netmask'])

            inf_node = interface['counter_index']
            weight = 1
            try:
                weight = interface['weight']
            except KeyError:
                logger.warning('no weight info in %s, %s defaut to 1',
                               filename, interface)
            graph[node][inf_node] = weight

    # C not in graph
    for i in range(V):
        graph[2][i] = -1
        graph[i][2] = -1

    logger.debug("[spfa] finished loading neighbour info into graph\n %s",
                 format(graph))
Esempio n. 11
0
    def task(self):
        time.sleep(0.1)
        msg_queue = []
        msg_queue.append(self.network_layer.recv_ospf())
        msg_queue.append(self.network_layer.recv())
        msg_queue.append(self.network_layer.recv_ping())

        available_msg = [msg for msg in msg_queue if not msg is None]
        for msg in available_msg:
            if msg.protocol == 100:
                data = utilities.objDecode(msg.data)
                sip = msg.src_ip
                dip = msg.dest_ip
                netmask = msg.net_mask
                if data['code'] == 0:
                    # get ping request from other
                    logger.info('get ping from %s\n', sip)
                    msg = {'code': 1, 'msg': 'I am here.'}
                    self.network_layer.send(dip, sip, utilities.objEncode(msg),
                                            100)
                if data['code'] == 1:
                    # get ping response from it
                    logger.info('ping response. I know %s reachable', sip)
                    self.tracking_neighbour_alive.wakeup(dip, sip)
            elif msg.protocol == 119:
                data = utilities.objDecode(msg.data)
                msgid = data['id']
                if msgid in known_msgid_list:
                    # logger.debug('already know %d, continue', msgid)
                    continue
                known_msgid_list.append(msgid)
                self.broadcastMsg(data, 119)
                msg_type = data['type']
                if msg_type == 'logout':
                    # pass #TODO: here, maybe bugs
                    lgout_index = data['index']
                    logger.info(
                        'get logout broadcast. now refresh route table according to broadcast %d',
                        lgout_index)
                    logout_refresh_route_table(lgout_index)
            else:
                logger.debug('recv msg!!\n%s', msg)
Esempio n. 12
0
def calculate_shortest_path(src: int):
    ret = []

    dist, prev = shortestPath.SPFA(graph, src)
    logger.debug("[controller] finished run spfa\n dist %s \n prev %s\n", dist,
                 prev)
    logger.debug("[controller, info] interface2index\n%s", interface2index)
    logger.debug("[controller, info] index2interface\n%s", index2interface)

    for ip, netmask in interface2index:
        # 自己的端口不需要作转发
        if interface2index[(ip, netmask)] == src:
            continue
        logger.debug('[controller] dealing with %s, %s', ip, netmask)
        subnet = utilities.get_subnet(ip, netmask)
        index = interface2index[(ip, netmask)]
        prev_index = prev[index]
        if prev_index == -1:
            continue
        if prev_index == src:
            target_index = interface2index[(ip, netmask)]
            (dst_ip, dst_nm) = index2interface[target_index]
            # route.my_route_table.update_item(ip, netmask, dst_ip)
            ret.append((ip, netmask, dst_ip))
            logger.info(
                '[1]add item into response msg\n \
                %s, %s, %s', ip, netmask, dst_ip)
        else:
            try_get = index2interface.get(prev_index)
            while try_get is None:
                prev_index = prev[prev_index]
                try_get = index2interface.get(prev_index)
            prev_ip, prev_netmask = try_get
            # route.my_route_table.update_item(ip, netmask, prev_ip)
            ret.append((ip, netmask, prev_ip))
            logger.info(
                '[2]add item into response msg\n \
                %s, %s, %s', ip, netmask, prev_ip)

    logger.debug("calculation return value\n%s", ret)
    return ret
Esempio n. 13
0
def main():
    '''main'''
    # open file

    network_layer = route.NetworkLayer(config_data)

    if is_controller:
        logger.debug("I am controller. not calculate until asked")
        #init_global_route_table(GLOBAL_ROUTE_INFORMATIOIN_FILE, 2)
        #ret = calculate_shortest_path(2)
        #for item in ret:
        #route.my_route_table.update_item(*item)

    network_layer_listener = NetworkLayerListener(network_layer)
    network_layer_listener.start()

    if not is_controller:
        logger.debug("begin to ask for global table")
        ask_for_global_table()
    consoler = console.Console(network_layer, route)
    consoler.task()
Esempio n. 14
0
 def send(self, ip_pkg: bytes) -> int:
     """
     实现假设:
         1. src这一台host自带的socket能够直接发送到dest
         2. 两台host在同一个子网内
     作用:
         1. 将ip_pkg从src这个host发送到dest这个host
     注意:
         1. dest这个参数似乎没用上
     """
     logger.debug("in link, DataLinkLayer, sending\n%s", ip_pkg)
     pkg = IP_Package.bytes_package_to_object(ip_pkg)
     ip1 = pkg.dest_ip
     nm = pkg.net_mask
     # def send(self, src, dest, ip_pkg):
     #     ip1, nm1 = src
     #     _, nm2 = dest
     #     if nm1 != nm2:
     #         logger.error('{} and {} not in same subnet'.format(str(nm1), str(nm2)))
     #         raise Exception("{} and {} not in same subnet".format(nm1, nm2))
     subnet_prefix = utilities.get_subnet(ip1, nm)
     # 实现了:找到目的ip对应子网,再从子网中找到对应host,然后就直接调用这个host的send
     for subnet in self.subnets:
         if subnet.prefix == subnet_prefix:
             for host in subnet.hosts:
                 if (host.counter_vip == ip1
                         or host.vip == ip1) and host.netmask == nm:
                     if host.status == "offline" or host.status == "down":
                         return -1
                 # TODO:允许以出端口作为dest_ip
                     try:
                         rsock = rdt_socket.rdt_socket(host.counter_socket)
                         rsock.sendBytes(ip_pkg)
                         return len(ip_pkg)
                     except Exception as e:
                         # 捕获所有异常,并且打印错误信息
                         logger.debug(traceback.format_exc())
                         return -1
Esempio n. 15
0
def init_shortest_path_prerequisite(src: int) -> None:
    """
    用SPFA算法,读取配置文件,更新路由表中的最短路信息
    input:
    """
    logger.debug("[ospf.spfa] init graph\n %s", format(graph))
    for filename in json_files['filenames']:
        f = open(CONFIG_ROOT + '/' +
                 filename)  #TODO:(YB) refactor. let it be path.resolve
        json_data = json.load(f)
        f.close()

        node = json_data['index']  # 当前配置文件/test/route*.json的路由标号
        interfaces = json_data['interfaces']
        for interface in interfaces:
            cvip = interface['counter_vip']
            netmask = interface['netmask']

            # interface2index 记录了所有的interfaces.它是一个从interface到所属路由的映射。
            interface2index[(cvip, netmask)] = interface['counter_index']
            if interface['counter_index'] == src:
                # index2interface,
                # idx -> intf
                # 记录了,站在本路由的角度,到达idx这个路由,需要通过的intf是什么
                index2interface[node] = (interface['vip'],
                                         interface['netmask'])

            inf_node = interface['counter_index']
            weight = 1
            try:
                weight = interface['weight']
            except KeyError:
                logger.warning('no weight info in %s, %s defaut to 1',
                               filename, interface)
            graph[node][inf_node] = weight
    logger.debug("[spfa] finished loading neighbour info into graph\n %s",
                 format(graph))
Esempio n. 16
0
 def run(self) -> None:
     logger.debug('network layer listener begin to work')
     while True:
         for protocol in ['rip', 'cost']:
             if protocol == 'rip':
                 pkg = network_layer.recv_rip()
                 if pkg is None:
                     continue
                 if(pkg.protocol == 120):
                     rip_msg = utilities.objDecode(pkg.data)
                     rip_worker.process(rip_msg)
             elif protocol == 'cost':
                 pkg = network_layer.recv_cost()
                 if pkg is None:
                     continue
                 if(pkg.protocol == 121):
                     cost_msg = utilities.objDecode(pkg.data)
                     _vip = cost_msg['vip']
                     _cost = cost_msg['cost']
                     for intf in rip_worker.interfaces:
                         if intf.vip == _vip:
                             logger.info('Cost %s -> %s changed to %d', rip_worker.route_name, intf.counter_name, _cost)
                             rip_worker.dis_vec[intf.counter_name]['cost'] = _cost
         time.sleep(0.01)
Esempio n. 17
0
def init_route_table():
    init_shortest_path_prerequisite(ROUTER_INDEX)
    ret = calculate_shortest_path(ROUTER_INDEX)
    for dest_net, netmask, dest_ip in ret:
        route.my_route_table.update_item(dest_net, netmask, dest_ip)
    logger.debug("finish init route table.")
Esempio n. 18
0
    def portmapping(self, vmname, vmip, vmport, hostport, action):
        if action == 'a':
            iptables_cmd = '%s %s PREROUTING -p tcp --dport %s -j DNAT --to %s:%s' \
                    %(self.cmd_iptables, '-A', hostport, vmip, vmport)
            logger.info('Add port mapping for %s, from %s to %s on hostmachine'%(vmname, vmport, hostport))
            logger.debug(iptables_cmd)

        elif action == 'd':
            iptables_cmd = '%s %s PREROUTING -p tcp --dport %s -j DNAT --to %s:%s' \
                    %(self.cmd_iptables, '-D', hostport, vmip, vmport)
            logger.info('Delete port mapping for %s, from %s to %s on hostmachine'%(vmname, vmport, hostport))
            logger.debug(iptables_cmd)
        else :
            logger.error('Error argument!')
            return 0

        (result, value) = pexpect.run(iptables_cmd, withexitstatus = 1)

        if value != 0 :
            logger.error(result)
            return 0

        return 1

        if connect:
            logger.info('Start.')
            logger.info('Database connected.')
            while 1:
                query_portreq = "SELECT * FROM %s WHERE state='adding' \
                        OR state='deleting 'ORDER BY hostport"%(porttb)
                db.query(query_portreq)
                req_res = db.store_result()
                fetched_req_data = req_res.fetch_row()
                while fetched_req_data:
                    state = fetched_req_data[0][idx_state]
                    vmname = fetched_req_data[0][idx_vmname]
                    vmport = fetched_req_data[0][idx_vmport]
                    oldhostport = fetched_req_data[0][idx_hostport]

                    if (state == 'adding') :
                        vmip = socket.gethostbyname(vmname)
                        newport = oldhostport
                        if (newport == '-1') :
                            newport = get_port()
                        if (newport != -1) :
                            portmapping(vmname, vmip, vmport, newport, 'a')
                            query = "UPDATE %s SET state='using', \
                                hostport='%s', ip='%s' \
                                WHERE hostport=%s"%(porttb, newport, vmip, oldhostport)
                            db.query(query)
                        else :
                            logger.error('No more port!')
                    elif (fetched_req_data[0][idx_state] == 'deleting') :
                        #delete port
                        vmip = fetched_req_data[0][idx_ip]
                        portmapping(vmname, vmip, vmport, oldhostport, 'd')
                        query = "DELETE FROM %s WHERE hostport=%s"%(porttb, oldhostport)
                        db.query(query)
                    else :
                        logger.error("I don't know what's wrong!")

                fetched_req_data = req_res.fetch_row()
            time.sleep(sleep_time)
Esempio n. 19
0
    def portmapping(self, vmname, vmip, vmport, hostport, action):
        if action == 'a':
            iptables_cmd = '%s %s PREROUTING -p tcp --dport %s -j DNAT --to %s:%s' \
                    %(self.cmd_iptables, '-A', hostport, vmip, vmport)
            logger.info(
                'Add port mapping for %s, from %s to %s on hostmachine' %
                (vmname, vmport, hostport))
            logger.debug(iptables_cmd)

        elif action == 'd':
            iptables_cmd = '%s %s PREROUTING -p tcp --dport %s -j DNAT --to %s:%s' \
                    %(self.cmd_iptables, '-D', hostport, vmip, vmport)
            logger.info(
                'Delete port mapping for %s, from %s to %s on hostmachine' %
                (vmname, vmport, hostport))
            logger.debug(iptables_cmd)
        else:
            logger.error('Error argument!')
            return 0

        (result, value) = pexpect.run(iptables_cmd, withexitstatus=1)

        if value != 0:
            logger.error(result)
            return 0

        return 1

        if connect:
            logger.info('Start.')
            logger.info('Database connected.')
            while 1:
                query_portreq = "SELECT * FROM %s WHERE state='adding' \
                        OR state='deleting 'ORDER BY hostport" % (porttb)
                db.query(query_portreq)
                req_res = db.store_result()
                fetched_req_data = req_res.fetch_row()
                while fetched_req_data:
                    state = fetched_req_data[0][idx_state]
                    vmname = fetched_req_data[0][idx_vmname]
                    vmport = fetched_req_data[0][idx_vmport]
                    oldhostport = fetched_req_data[0][idx_hostport]

                    if (state == 'adding'):
                        vmip = socket.gethostbyname(vmname)
                        newport = oldhostport
                        if (newport == '-1'):
                            newport = get_port()
                        if (newport != -1):
                            portmapping(vmname, vmip, vmport, newport, 'a')
                            query = "UPDATE %s SET state='using', \
                                hostport='%s', ip='%s' \
                                WHERE hostport=%s" % (porttb, newport, vmip,
                                                      oldhostport)
                            db.query(query)
                        else:
                            logger.error('No more port!')
                    elif (fetched_req_data[0][idx_state] == 'deleting'):
                        #delete port
                        vmip = fetched_req_data[0][idx_ip]
                        portmapping(vmname, vmip, vmport, oldhostport, 'd')
                        query = "DELETE FROM %s WHERE hostport=%s" % (
                            porttb, oldhostport)
                        db.query(query)
                    else:
                        logger.error("I don't know what's wrong!")

                fetched_req_data = req_res.fetch_row()
            time.sleep(sleep_time)
Esempio n. 20
0
CONFIG_NAME = sys.argv[1]
f = open(CONFIG_NAME, 'rt')
config_data = json.load(f)
f.close()
ROUTER_INDEX = config_data['index']

disable_node = []
interface2index = {}  # type: Dict[Tuple[str, str], int]
index2interface = {}  # type: Dict[int, Tuple[str, str]]

# config_file中的内容是,所有test/route*.json的文件的文件名
f = open(GLOBAL_ROUTE_INFORMATIOIN_FILE, 'rt')
json_files = json.load(f)
f.close()
logger.debug("[controller] read all files\n %s ", format(json_files))

V = len(json_files['filenames'])
msgID = ROUTER_INDEX
known_msgid_list = []
# graph 是用于求最短路的邻接矩阵
graph = [[-1 for i in range(V)] for j in range(V)]  # type: List[List[int]]


def logout_refresh_route_table(index):
    if index in disable_node:
        return
    disable_node.append(index)
    logger.info('refreshing router table ,logout index is %d', index)
    for i in range(V):
        graph[index][i] = -1
Esempio n. 21
0
    def process(self, rip_msg : dict):
        medium = rip_msg['from']
        # 步骤一:阻止含有之前已经处理过的离线的路由器的信息的rip报文
        if medium in self.tear_down:
            return
        
        for rname, detail in rip_msg['dv'].items():
            for drname in self.tear_down:
                if drname in detail['path']:
                    logger.debug("[RIP] [Dropped] DV of %s contain offline route %s", medium, drname)
                    return

        for rname in rip_msg['topo'].keys():
            if rname in self.tear_down:
                logger.debug("[RIP] [Dropped] TOPO of %s contain offline route %s", medium, rname)
                return

        logger.debug("[RIP] received rip package from %s", medium)
        new_tear_down = set(rip_msg['tear_down']) - set(self.tear_down)
        self.tear_down = list(set().union(self.tear_down, rip_msg['tear_down']))

        # 步骤二:删除自身所有有关新得知的离线了的路由器的信息
        # 删除距离向量中的这一行
        if len(new_tear_down) != 0:
            to_del = []
            for drname in new_tear_down:
                if drname in self.dis_vec.keys():
                    to_del.append(drname)
            for drname in to_del:
                del self.dis_vec[drname]

            # 删除距离向量中所有途径offline路由器的
            to_del = []
            for drname in new_tear_down:
                for rname, detail in self.dis_vec.items():
                    if drname in detail['path']:
                        to_del.append(rname)
            for rname in to_del:
                del self.dis_vec[rname]


            for drname in new_tear_down:
                # 删除路由表中有关的
                for vip, nm in self.topo[drname]:
                    route.my_route_table.delete_item(vip, nm)
                    route.my_route_table.delete_item(utilities.get_subnet(vip, nm), nm)
                # 网络层端口中将其设为offline
                for intf in network_layer.interfaces:
                    if intf.counter_name == drname:
                        intf.status = "offline"
                # 删除关于它的拓扑记录
                del self.topo[drname]
                self.dis_mat = {}
                for intf in self.interfaces:
                    self.dis_mat[intf.counter_name] = {}
                return

        for dest, intfs in rip_msg['topo'].items():
            if dest not in self.topo:
                self.topo[dest] = intfs
                logger.info("[RIP] learned topo of {} : {}".format(dest, intfs))
                if dest in self.direct_routes:
                    for vip, netmask in intfs:
                        logger.info("[RIP] Updating route table\n{} {} THROUTH {}".format(vip, netmask, self.next_hop[dest]))
                        route.my_route_table.update_item(vip, netmask, self.next_hop[dest])

        # 步骤三:更新自己的距离向量和拓扑图,因为可能学习到新的节点
        # if medium not in self.topo.keys():
        #     self.topo[medium] = rip_msg['intfs']
        if medium not in self.dis_vec.keys():
                logger.critical("Unexpected rip msg from %s", rip_msg['from'])
        else:
            mininum = DV_INF
            for dest, detail in rip_msg['dv'].items():
                if not dest in self.topo.keys():
                    continue
                cost = detail['cost']
                newcost = self.dis_vec[medium]['cost'] + cost
                if dest == self.route_name:
                    continue
                elif dest not in self.dis_vec.keys():
                    newpath = detail['path']
                    newpath.insert(0, self.route_name)
                    self.dis_vec[dest] = \
                        {
                            "cost": newcost,
                            "path": newpath
                        }
                    logger.info("[RIP] New shortest path found\n{} -> {} cost {}, path: {}".format(
                        self.route_name, dest, self.dis_vec[dest]['cost'], self.dis_vec[dest]['path']))
                    for vip, netmask in self.topo[dest]:
                        logger.info("[RIP] Updating route table\n{} {} THROUTH {}".format(vip, netmask, self.next_hop[medium]))
                        route.my_route_table.update_item(vip, netmask, self.next_hop[medium])

        # 步骤四:更新距离矩阵中的一行
        self.dis_mat[medium] = rip_msg['dv']
        logger.debug('{}'.format(utilities.obj_to_beautiful_json(self.dis_mat)))
        # 步骤五:运行核心的dv算法
        for dest, detail in self.dis_vec.items():
            # 直连的链路cost不在这里更新cost,只在cost change protocol中更新
            if dest in self.direct_routes:
                continue
            # 不需要对未知子网Interfaces情况的路由器计算距离,计算了也没用,也加不了路由表
            if not dest in self.topo.keys():
                continue
            mininum = DV_INF
            new_path = []
            medium = ''
            for entry_route, dv in self.dis_mat.items():
                # 去不到就continue,相当于设置了正无穷
                if dest not in dv.keys():
                    continue

                new_cost = self.dis_vec[entry_route]['cost'] + dv[dest]['cost']
                if new_cost < mininum:
                    # 毒性逆转(poisoned reverse)
                    # 如果可能的最短路径中包含目的节点自身
                    if dest in dv[dest]['path'] and dest != dv[dest]['path'][-1]:
                        continue
                    logger.debug('maybe shortest : {} to {}'.format(self.route_name, dest))
                    logger.debug('{} plus {}'.format(dest, dv[dest]['path']))
                    mininum = new_cost
                    medium = entry_route
                    new_path = dv[dest]['path']
                    if new_path[0] != self.route_name:
                        new_path.insert(0, self.route_name)

            # 更新距离向量和路由表,并打印适量调试信息
            old_cost = detail['cost']
            detail['cost'] = mininum
            if mininum >= DV_INF:
                detail['path'] = []
            else:
                logger.debug("{} to {} now walks {}".format(self.route_name, dest, new_path))
                detail['path'] = new_path
            if medium != '':
                for vip, netmask in self.topo[dest]:
                    route.my_route_table.update_item(vip, netmask, self.next_hop[medium])

            if old_cost != detail['cost']:
                 logger.info("[RIP] New shortest path found\n{} -> {} cost {}, path: {}".format(
                     self.route_name, dest, self.dis_vec[dest]['cost'], self.dis_vec[dest]['path']))
Esempio n. 22
0
 def run(self):
     logger.debug("rip protocol is working")
     while True:
         logger.debug("[RIP] Broadcasting RIP msg")
         self.broadcast(self.interfaces)
         time.sleep(2)
Esempio n. 23
0
 def run(self):
     logger.debug("Trying to connect all counterpart interface")
     self.connect_all()