计网lab4总结 简单交换机

文章介绍了如何使用自定义类`SwitchTableElement`构建数据结构,处理网络帧,包括转发表的创建、源/目的地址解析、老化机制以及广播帧的处理。作者强调了数据结构在简化代码和逻辑中的作用,同时提到了关键部分如转发表的查找和广播操作的实现细节。
摘要由CSDN通过智能技术生成

数据结构

对mac地址编写class数据结构

class SwitchTableElement
{
  public:
  mac_addr_t mac; //mac地址

  //默认构造函数
  SwitchTableElement()
  {
    for(int i = 0;i < 6;i++) mac[i] = 0;
  }
  //基于mac地址的构造函数
  SwitchTableElement(mac_addr_t a)
  {
    for(int i = 0;i < 6;i++) mac[i] = a[i];
  }
  //复制构造函数
  SwitchTableElement(const SwitchTableElement &a)
  {
    for(int i = 0;i < 6;i++) this->mac[i] = a.mac[i];
  }
  //重载赋值运算符
  SwitchTableElement& operator=(const SwitchTableElement &a)
  {
    for(int i = 0;i < 6;i++) this->mac[i] = a.mac[i];
    return *this;
  }
  //重载比较运算符,用于map散列
  bool friend operator<(const SwitchTableElement& a, const SwitchTableElement& b)
  {
    long p = 0; long q = 0;
    for(int i = 0;i < 6;i++)//将6个8bit的地址聚合为long类型来完成比较
    {
      p += (a.mac[i] << ((5 - i) * 8));
      q += (b.mac[i] << ((5 - i) * 8));
    }
    return p < q;
  }
};

从端口处理进入的帧

ProcessFrame函数,收取framePtr并提取所需信息

  1. srcAddr
  2. dstAddr

将提取到的源地址和目的地址转换为mac地址(SwitchTableElement类)

构造map,用于存储转发表(pair的两个变量分别是该条路径的老化记数和该条路径的起始地址——源地址)

std::map<SwitchTableElement, std::pair<int, int> >::iterator it;

map帮助我们在逆向学习时定位secMac是否是存在于转发表中的,如果存在,则更新老化记数,否则应当进行逆向学习

    if(switchTable.find(srcMac) == switchTable.end())//不存在,逆向学习
    {
      std::pair<int, int> p(10, inPort);
      switchTable[srcMac] = p;
    }

对广播帧进行处理

从framePtr中提取framType

老化指令

对每一个mac表项,将老化计数减1,归零删除该表项

      for(it = switchTable.begin();it != switchTable.end();it++)
      {
        it->second.first--;
        if(it->second.first <= 0)
        {
          it = switchTable.erase(it);//erase返回此次删除后下一个有效的迭代器
          it--;//循环结束会++,故此处--使得下一次循环遍历到此次删除后的下一个有效迭代器
        }
      }
待转发的帧
    else//待转发的帧
    {
      //检查目的mac是否在转发表中且有效
      for(it = switchTable.begin();it != switchTable.end();it++)
      {
        if(isSameMac(dstAddr, (uint8_t*)(it->first.mac)) && it->second.first > 0)
        {
          break;
        }
      }

      if(it == switchTable.end())//不在转发表中或已经失效,则广播
      {
        return 0;
      }
      else//可以找到有效的转发表项
      {
        if(inPort == it->second.second) return -1;//出入端口相同,丢弃
        else return  it->second.second;//出入端口不同,转发
      }
    }

复盘

  1. 数据结构可以简化你的工作量和思路,我的代码是以两段struct构造数组嵌套而成的转发表,这加大了我的代码编写难度和思维量。
  2. 对于一些细节bug需要把握,比如:
            if(it->second.first <= 0)
            {
              it = switchTable.erase(it);//erase返回此次删除后下一个有效的迭代器
              it--;//循环结束会++,故此处--使得下一次循环遍历到此次删除后的下一个有效迭代器
            }
  3. 广播的返回值是需要值得注意的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值