美文网首页
RIP实验报告(转载自百度文库)

RIP实验报告(转载自百度文库)

作者: 张慕晖 | 来源:发表于2017-11-24 05:28 被阅读177次

    原文地址:https://wenku.baidu.com/view/9ef65744fad6195f312ba65d.html

    一、 实验目的

    通过简单实现路由协议RIP,深入理解计算机网络中的核心技术——路由技术,并了解计算机网络的路由转发原理。

    二、 实验要求

    1. RIP报文有效性检查
    2. 处理Request报文
    3. 处理Response报文
    4. 路由表项超时删除
    5. 路由表项定时发送

    三、 实验接口

    1. RIP报文处理函数

    int  stud_rip_packet_recv(char  *pBuffer,  int  bufferSize,  UINT8  iNo,  UINT32 srcAdd)
    
    pBuffer:指向接收到的RIP报文内容的指针
    bufferSize:接收到的RIP报文的长度
    iNo:接收该报文的接口号
    srcAdd:接收到的报文的源IP地址
    

    2. RIP超时处理函数

    void  stud_rip_route_timeout(UINT32  destAdd,  UINT32  mask,  unsigned  char msgType)
    
    destAdd:路由超时消息中路由的目标地址
    mask:路由超时消息中路由的掩码
    msgType:消息类型,包括以下两种定义:
    #define RIP_MSG_SEND_ROUTE
    #define RIP_MSG_DELE_ROUTE
    

    四、 实验基本框架

    1. 当系统收到RIP报文时

    当系统收到RIP报文时,会调用stud_rip_packet_recv函数,此函数应该实现如下功能:

    • 对RIP报文进行合法性检查,若报文存在错误,则调用ip_DiscardPkt函数,并在type参数中传入错误编号。
    • 对于Request报文,应该将根据本地的路由表信息组成Response报文,并通过rip_sendIpPkt函数发送出去。注意,由于实现水平分割,组Response报文时应该检查该Request报文的来源接口,Response报文中的路由信息不包括来自该来源接口的路由。
    • 对于Response报文,应该提取出该报文中携带的路由信息,对于本地路由表中已存在的项要判断该条路由信息的metric值,若为16,则应置本地路由表中对应路由为无效,否则若更新表项的metric值小于路由表中相应表项metric值时就替代原来的表项。注意要将metric值加1。对于本地路由表中不存在的项,则将metric值加1后将该路由项加入本地路由表,注意,若metric值加1后为16说明路由已经失效,则不用添加。

    2. RIP超时处理函数

    RIP协议每隔30秒,重新广播一次路由信息,系统调用该函数并置msgType为RIP_MSG_SEND_ROUTE来进行路由信息广播。该函数应该在每个接口上分别广播自己的RIP路由信息,即通过rip_sendIpPkt 函数发送RIP Response报文。由于实现水平分割,报文中的路由信息不包括来自该接口的路由信息。

    RIP协议每个路由表项都有相关的路由超时计时器,当路由超时计时器过期时,该路径就标记为失效的,但仍保存在路由表中,直到路由清空计时器过期才被清掉。当超时定时器被触发时,系统会调用该函数并置msgType为RIP_MSG_DELE_ROUTE,并通过destAdd和mask参数传入超时的路由项。该函数应该置本地路由的对应项为无效,即metric值置为16。

    五、 源代码及注释

    #include "sysinclude.h"
    
    extern void rip_sendIpPkt(unsigned char *pData, UINT16 len,unsigned short dstPort,UINT8 iNo);
    
    extern struct stud_rip_route_node *g_rip_route_table;//路由器表头
    
    void sendTo(UINT8 iNo){//向iNo发送本地路由表表
        int cnt = 0;
        struct stud_rip_route_node* local_table = g_rip_route_table;//取路由表头
        while (local_table != NULL) {
            if (local_table->if_no != iNo)//水平分裂算法,不把路由项信息回传给发送者
                cnt++;
            local_table = local_table->next;
        }
        char* response_table = new char[4 + cnt * 20];//路由表,包括所有不来自请求者的路由表项
        response_table[0] = 2;//标识为一个response
        response_table[1] = 2;//版本号
        response_table[2] = 0;//要求为0
        response_table[3] = 0;//要求为0
        local_table = g_rip_route_table;
        for (int i = 0; i < cnt; i++)
        {
            while (local_table->if_no == iNo)//跳过来自请求方的路由项,不发送
                local_table = local_table->next;
            *(short *)(response_table + 4 + i * 20) = htons(2);//地址类字段,长度为2byte,RIP规定为2
            *(short *)(response_table + 6 + i * 20) = htons(0);//IP地址字段,长度为2byte,置为0
            *(unsigned int *)(response_table + 8 + i * 20) = htonl(local_table->dest);//长度为4byte,复制并转成网络字节序
            *(unsigned int *)(response_table + 12 + i * 20) = htonl(local_table->mask);//长度为4byte,同上
            *(unsigned int *)(response_table + 16 + i * 20) = htonl(local_table->nexthop);//长度为4byte,同上
            *(unsigned int *)(response_table + 20 + i * 20) = htonl(local_table->metric);//长度为4byte,同上
            local_table = local_table->next;
        }
        rip_sendIpPkt((unsigned char*)response_table, 4 + cnt * 20, 520, iNo);//发送分组
    }
    
    int stud_rip_packet_recv(char *pBuffer,int bufferSize,UINT8 iNo,UINT32 srcAdd)
    {   
        if(*pBuffer == 1){////查看命令字段是request,处理请求
            sendTo(iNo);
            return 0;
        }
        if(*pBuffer == 2){// 查看命令字段,是response,更新本地路由信息
            pBuffer = pBuffer + 4;//跳过RIP头
            for (int i = 0; i < (bufferSize-4)/20 ;++i) {//发来的RIP分组的数量,依次检查每一个RIP分组
                bool flag = false;//查找成功标志,若查找成功,置为true
                struct stud_rip_route_node *local_table = g_rip_route_table;
                while (local_table) {//遍历本地路由表,查找是否有当前位置一致的表项
                    if (local_table->dest == ntohl(*(unsigned int *)(pBuffer+4)) &&
                        local_table->mask == ntohl(*(unsigned int *)(pBuffer+8))) {//符合(即原路由表中已有),则修改本地路由表信息
                        flag = true;//查找成功
                        if (local_table->nexthop == srcAdd) {//已存在
                            local_table->metric = ntohl(*(unsigned int *)(pBuffer + 16)) + 1;//跳数加1
                            if (local_table->metric > 16)//大于16,则置成16(RIP最多只能支持16跳)
                                local_table->metric = 16;
                            local_table->if_no = iNo;
                        } else {//未存在
                            if (ntohl(*(unsigned int *)(pBuffer + 16)) < local_table->metric) {//需要更新
                                local_table->nexthop = srcAdd;
                                local_table->metric = ntohl(*(unsigned int *)(pBuffer+16)) + 1;//跳数加1
                                if (local_table->metric > 16)
                                    local_table->metric = 16;
                                local_table->if_no = iNo;
                            }
                        }
                    }
                    local_table = local_table->next;
                }
                if (!flag) {//查找不成功,local_table到达本地路由表的尾端,增加新的表项
                    struct stud_rip_route_node *new_item = new struct stud_rip_route_node();
                    local_table = g_rip_route_table;
                    while (local_table->next)
                        local_table = local_table->next;
                    new_item->dest = ntohl(*(unsigned int *)(pBuffer + 4));
                    new_item->mask = ntohl(*(unsigned int *)(pBuffer + 8));
                    new_item->nexthop = srcAdd;
                    new_item->metric = ntohl(*(unsigned int *)(pBuffer + 16)) + 1;
                    new_item->next = NULL;
                    new_item->if_no = iNo;
                    if (new_item->metric < 16)//查看此表项是否有效,有效则添加
                        local_table->next = new_item;
                }
                pBuffer = pBuffer + 20;//移向下一位置
            }
            return 0;
        }
    }
    
    void stud_rip_route_timeout(UINT32 destAdd, UINT32 mask, unsigned char msgType)
    {
        if (msgType == RIP_MSG_SEND_ROUTE){//定时发送
            for(int i = 1; i <= 2; i ++)
                sendTo(i);
        }
        else if(msgType == RIP_MSG_DELE_ROUTE) {//删除本地路由表中的超时路由项
            stud_rip_route_node *local_table = g_rip_route_table;
            while (local_table) {//遍历路由表
                if (local_table->dest == destAdd && local_table->mask == mask)
                    local_table->metric = 16;//置为16,表示无效
                local_table = local_table->next;
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:RIP实验报告(转载自百度文库)

          本文链接:https://www.haomeiwen.com/subject/tjqxbxtx.html