暂时没有博客,就放到这里了。
Macvtap的代码没有去深读,从代码头上的注释来看,macvtap主要是在macvlan的基础上封装了一个char设备,维护一个队列,因此网络相关的主要逻辑应该在macvlan里。
+--------------------------------------------------------------------------------------------------------------------------+
| |
| +--------------------------------------------------------------------------------------------+ |
| | +---------------+ | |
| 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。
根据ldd3的说法,为了兼容性,linux内核把网卡设备对multicast的支持分成了三个级别:
- 完全不认识 multicast frame(只能通过promisc接收这些frame)
- 认识但是不能设置multicast表(只能通过promisc和allmulti接收这些frame)
- 认识并且可以设置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需要做的事情如下:
- 根据 lowerdevice->flag | IFF_MULTICAST 来设置 dev->flag | IFF_MULTICAST,如果底层设备都不支持multicast,还玩个屁,promisc了事。
- 实现 macvlan 设备的 set_multicast_list 方法,把 dev->mc_list 的内容加到 lowerdevice 的 multicast 列表里。
- 修改 port 的 handler 的代码,让 multicast 的 frame 能正确地传到 macvlan。
能预期到的问题:
- 如何把 dev->mc_list 的内容加到 lowerdevice 的 multicast 里(看代码的时候看到了dev_uc_add用来增加单播地址,应该有对应的多播的方法dev_mc_*)。
- 如何高效地把多播的包发到 macvlan(单播应该是用了port->vlan_source_hash,多播大概可以复用)
- 如何在清理的时候正确地删除向lowerdevice添加的多播地址(dev_mc_unsync?)。
还有什么需要读
macvlan_fdb_del 和 macvlan_fdb_add 好像做了一些向lowerdevice增删地址的事情。