浅析linux网桥设置MAC地址时的行关

Linux系统
56
linux
linux 举报
04月11日 14:44

浅析linux网桥设置MAC地址时的行关 

linux    网桥    MAC                                          


先说现象

brctl addbr br0

ifconfig br0

br0 MAC is 00:00:00:00:00:00


brctl addif br0 eth1  (eth1 is xx:xx:xx:xx:xx:33)

ifconfig br0

br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, auto change


brctl addif br0 eth2  (eth2 is xx:xx:xx:xx:xx:30)

ifconfig br0

br0 MAC is xx:xx:xx:xx:xx:30  same as eth2, For eth2 less than eth1, auto change


ifconfig eth2 hw ether xx:xx:xx:xx:xx:50

ifconfig br0

br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, auto change


ifconfig br0 hw ether xx:xx:xx:xx:xx:99

ifconfig br0

br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, NOT change



ifconfig br0 hw ether xx:xx:xx:xx:xx:33  ;same as eth1

ifconfig eth2 hw ether xx:xx:xx:xx:xx:20  ;less than eth1

ifconfig br0

br0 MAC is xx:xx:xx:xx:xx:33  same as eth1, `ifconfig br0 hw` NOT effective


ifconfig eth1 hw ether xx:xx:xx:xx:xx:50  ;upper op,we set br0 = eth1's MAC,now we change eth1 MAC

ifconfig br0

br0 MAC is xx:xx:xx:xx:xx:20  same as eth2, auto change


结论:

  br0如果没有指定hw MAC, br0的MAC地址会根据bridge中port的变化,自动选择port中最小的一个MAC地址作为br0的MAC地址。

  br0只能指定port中有的interface的MAC作为br0的MAC地址。

 

源代码分析:

  source code dir is: linux-2.4.x/net/bridge

 

  - br_device.c

      br_dev_setup() 注册了一些函数,其中  dev->set_mac_address = br_set_mac_address;  //这个就是ifconfig br0 hw ether调用的函数了

     

      static int  br_set_mac_address(struct net_device *dev, void *addr)

          {

            struct net_bridge *br = dev->priv;

            struct sockaddr *sa = (struct sockaddr *) addr;

           

          。。。。。 

          //here ! copy MAC addr to br->preferred_id.addr

            memcpy(br->preferred_id.addr, sa->sa_data, ETH_ALEN);

         

            br_stp_recalculate_bridge_id(br);

         

          。。。。。

          }


 

  - br_stp_if.c

      static unsigned char br_mac_zero[6] = {0,0,0,0,0,0};

     

      /* called under bridge lock */

      void br_stp_recalculate_bridge_id(struct net_bridge *br)

      {

        unsigned char *addr;

        struct net_bridge_port *p;

     

        //初始br0的MAC为00:00:00:00:00:00

        addr = br_mac_zero;

     

        p = br->port_list;

        while (p != NULL) {

          /* match against preferred address first */

          if (memcmp(p->dev->dev_addr, br->preferred_id.addr, ETH_ALEN) == 0) {

            addr = p->dev->dev_addr;

            //匹配port的MAC地址与首选MAC是否相符

            break;

          }

         

          if (addr == br_mac_zero ||

              memcmp(p->dev->dev_addr, addr, ETH_ALEN) < 0)

          //寻找MAC最小的那一个

            addr = p->dev->dev_addr;

     

          p = p->next;

        }

     

        //如果没有Port的话,就为0;

        //如果没有设置首选MAC,就等于最小的那一个。

        //如果设置了首选MAC,则首选MAC必须同其中一个port的MAC匹配,才等于首选MAC

        if (memcmp(br->bridge_id.addr, addr, ETH_ALEN))

          br_stp_change_bridge_id(br, addr);

      }

 

  - 什么时候会执行br_stp_recalculate_bridge_id呢

      - in br_device.c 中 br_set_mac_address()

      - in br_if.c 中 br_del_if() & br_add_if()

      - in br_notify.c 中 br_devic_event()的 NETDEV_CHANGEADDR 事件,该事件是任意port有修改addr就会触发的

     

     

看过代码就很容易理解bridge在处理自身MAC地址时的行为了


倒序看帖 只看楼主
热点关注
/lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
服务停止、启动、重启一体化脚本,万能语言启动脚本
shell参数判断
在后台用进程名运行bash脚本
shell脚本每行后面多了一个^M的原因和解决办法
定时检测服务,检测down掉后重启。系统检测到DMSERVER运行正常
挂载磁盘的时候遇到一个问题,挂载完磁盘之后重启服务器挂载的盘丢失了.
中标麒麟系统Your trial is EXPIRED and no VALID licens
termux 开启ssh并用用户名和密码登陆
组成共享库的目标文件和一般的目标文件有所不同,在编译时要加-fPIC和-share选项,例如:
gcc指定链接库路径后还是找不到库文件
./configure -build,-host,-target设置
shell脚本每行后面多了一个^M的原因和解决办法
shell 中 if [ “x${var}“ == “x“ ] 中 x的作用
查看linux机器是32位还是64位的方法