Skip to content

Instantly share code, notes, and snippets.

@huiyiqun
Created November 4, 2015 13:41
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huiyiqun/2de3dbfb7900478e9380 to your computer and use it in GitHub Desktop.
Save huiyiqun/2de3dbfb7900478e9380 to your computer and use it in GitHub Desktop.
读macvlan代码的心得(为了给macvlan添加multicast支持)

Macvlan 内核代码阅读备忘

暂时没有博客,就放到这里了。

Macvlan和Macvtap的关系

Macvtap的代码没有去深读,从代码头上的注释来看,macvtap主要是在macvlan的基础上封装了一个char设备,维护一个队列,因此网络相关的主要逻辑应该在macvlan里。

Macvlan的数据结构里的逻辑关系(主要看macvlan_common_newlink)

    +--------------------------------------------------------------------------------------------------------------------------+
    |                                                                                                                          |
    |                         +--------------------------------------------------------------------------------------------+   |
    |                         |                                +---------------+                                           |   |
    |  register_rx_handler    |                        +------->macvlan_device0|                                           |   |
    |        +----------------------+                  |       +---------------+           +-------------------+           |   |
    |        |                |     |                  |       |    priv_data+------------->       vlan0       |           |   |
    |        |                | +---+----+             |       |               |           +-------------------+           |   |
    |   +----v-------+        +->  port  |             |       |               |           |    lowerdevice+-------------------+
    +---> phy_device |          +--------+             |       |               |           |                   |           |
        +------------+          |passthru|             |       |               |           |         port+-----------------+
                                |        |             |       |               |           |                   |
                                |  vlans+--------------+       |               |           |         mode      |
                                |        |             |       |               |           |                   |
                                +--------+             |       |               |           |                   |
                                                       |       +---------------+           |                   |
                                                       |                                   |                   |
                                                       |       +---------------+           +-------------------+
                                                       +------->macvlan_device1|
                                                       |       +---------------+
                                                       |
                                                       |       +---------------+
                                                       +------->macvlan_device2|
                                                               +---------------+

(如果屏幕不够宽的话,上面的图需要缩一下浏览器才能看到)

对于phy_device来说,port是唯一的,第一个macvlan设备创建的时候会创建这个port,它注册了一个handler来处理phy_device收到的frame,再将frame分发给macvlan设备。

任何设备都有一个priv_data用于存自己需要的东西macvlan设备的这个参数是一个macvlan_dev,代码中通常叫它vlan。

multicast support

根据ldd3的说法,为了兼容性,linux内核把网卡设备对multicast的支持分成了三个级别:

  1. 完全不认识 multicast frame(只能通过promisc接收这些frame)
  2. 认识但是不能设置multicast表(只能通过promisc和allmulti接收这些frame)
  3. 认识并且可以设置multicast表(可以通过设置multicast_list或者设置promisc或allmulti接收这些frame)

书中没有提到kernel怎么区分这三种设备,但是kernel通过如下方法和属性来使用网卡的multicast支持:

  • dev->mc_list 用于存该设备的multicast表的链表
  • dev->set_multicast_list 一个函数,当上面的链表或dev->flag更新后kernel会调用这个函数来提醒驱动更新网络设备中的表。
  • dev->flag | IFF_MULTICAST 如果这个flag没有被设置,kernel认为这个设备不支持multicast,也就是上面的第一个级别。

值得注意的一点是,ether_setup(用来初始化ethernet设备,许多非ethernet的网卡也用它来省事,包括macvlan)这个函数中将dev->flag设成了 IFF_MULTICAST | IFF_BROADCAST。

步骤分析

为了让macvlan设备能正确地获得自己需要的multicast的frame,有两个条件,第一是phy_device正确地设置了multicast_list,第二是port能正确地根据multicast_list将frame送到macvlan_device。

根据上面的分析,为了让macvlan支持multicast需要做的事情如下:

  1. 根据 lowerdevice->flag | IFF_MULTICAST 来设置 dev->flag | IFF_MULTICAST,如果底层设备都不支持multicast,还玩个屁,promisc了事。
  2. 实现 macvlan 设备的 set_multicast_list 方法,把 dev->mc_list 的内容加到 lowerdevice 的 multicast 列表里。
  3. 修改 port 的 handler 的代码,让 multicast 的 frame 能正确地传到 macvlan。

问题分析

能预期到的问题:

  1. 如何把 dev->mc_list 的内容加到 lowerdevice 的 multicast 里(看代码的时候看到了dev_uc_add用来增加单播地址,应该有对应的多播的方法dev_mc_*)。
  2. 如何高效地把多播的包发到 macvlan(单播应该是用了port->vlan_source_hash,多播大概可以复用)
  3. 如何在清理的时候正确地删除向lowerdevice添加的多播地址(dev_mc_unsync?)。

TODO

还有什么需要读

macvlan_fdb_del 和 macvlan_fdb_add 好像做了一些向lowerdevice增删地址的事情。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment