发现有网站转内容不写来源。。只好加上这个

本文原创于 http://blog.kangkang.org ,欢迎转载但请保留来源。

北京联通几个月前开始搞 IPTV 促销,只要 20M 宽带用两年,就可以免费赠送 IPTV。我等羊(dan4)毛(teng2)党自然是第一时间薅下。和大多数人家不一样,我家是 FTTB ,入户的是网线不是光缆。来安装的人带了一个家庭网关接在入户线上,然后其中一个口是专门给 IPTV 的,剩下三个可以接路由器拨号上网。在这个结构里面显然家庭网关这个角色很是多余,就是为了把一根网线上分在不同 VLAN 里面的上网流量和 IPTV 流量给分开到不同的网口。这事情常见的家庭路由器配合相应的软件也是可以做的,而且这个家庭网关明显属于很粗制滥造的那种,和其他联通设备一样,它支持无线,支持路由,只是都被关掉了,通过破解的手段可以打开,但是打开了一天我就被迫又换回去了,因为这玩意当路由用实在太不稳定了,无线也经常掉线。

上网搜了一下,已经有不少资料了,不过基本是南方电信的 IPTV 设置,跟北京的不太一样,偶尔有一两个讲北京的,还是光纤入户用光猫的那种,跟我光纤入楼的情况差别比较大。经过无数次的失败试验(此处省略 N 字,过程实在是太折腾了,几台 RG100A 和主力的 MW4530R 刷挂了不知道多少次),最终摸清楚了北京联通 FTTB 方式下 IPTV 的接入方式。

光纤入楼和入户最大的区别,就是入楼的之前入户网线里面就只有一路上网流量,而开启 IPTV 以后就变成两路,为了平滑过渡,北京联通搞出来一个非常神奇的机制。平时上网的 PPPOE 走 untagged 流量,这个时候除了 3999 之外其他的 VLAN 都是无效的,你就算发送其他 VLAN 的数据包,也不会有人回应你。而一旦有某个特定 MAC 地址的设备(就是联通送的那个家庭网关),从 3999 VLAN 上发出 PPPOE 请求,其他几个 VLAN 就被激活了,同时原来 untagged PPPOE 停止响应。在我这里上网的 VLAN 会变成 344,IPTV 是 1544,还有一个 2744 不知道是干啥用的。更坑爹的是,1544 VLAN 上传输的是 IPTV 的控制数据和点播数据,但是通过组播传送过来直播数据则又是 untagged 状态。于是就能看到从 1544 VLAN 上传过去的 igmp 报文,却传过来 untagged 的组播数据。

这个配置看起来相当折腾人,不过在 openwrt 这么灵活的环境里面,还是能配置起来的,但是受限于芯片能力,RG100A-AA 只好下岗,因为他的芯片只支持连续的 16 个 VLAN 同时工作,像 344 1544 这样的没法同时支持。MW4530R 的芯片是支持这么多 VLAN 的,但是代码里面默认只开了 128 个,需要手动修改 linux/drivers/net/phy/ar8216.c 里面的 AR8X16_MAX_VLANS 为 4096。此外 AR 系列芯片的驱动是不支持在同一个网口上面混合 tagged 和 untagged 的流量的,而且据说修改驱动不好使,好在有个变通的方法,他硬件可以给每个网口设定一个 pvid,让硬件把这个端口上 untagged 的流量当做 pvid 这个 vlan 来处理。

另外一个难点是需要在两个 vlan 上进行双拨,用不同的 mac 地址,其中一个要设定为联通家庭网关的 mac,这个搞过双拨的都知道用 macvlan,但是 openwrt 的网络代码部分升级成 netifd 架构以后,macvlan 的支持被丢掉了,手动在 openwrt 的网络脚本里面加命令很容易搞得一团糟。这个没有什么好办法,而且 netifd 几乎没有任何说明文档,硬着头皮啃了半天代码,实现了粗糙的 macvlan 支持,同样设置 pvid 的代码本来 openwrt 里面也有,升级到 netifd 以后也没了,一起实现了一下。

总体初始化流程是

1: 设置 3999 vlan 创建 eth0.3999,绑定 cpu 和 wan port
2: 在 eth0.3999 上创建 eth2 的 macvlan, 设置 mac 为家庭网关
3: 在 eth2 上创建 pppoe 链接,用户名密码是家庭网关的 tr069 账号(见下面配置文件),但不要设置为默认路由,也不用他的 dns
4: 设置 344 vlan, 绑定 cpu 和 wan port。创建 eth0.344
5: 在 eth0.344 上创建 pppoe 链接,设置为上网用户名密码
6:创建 1544 vlan,绑定 wan port 和 iptv port (untagged)。这个不用绑 cpu port,因为我们只需要交换机硬件转发。
7: 设置 wan port 的 pvid 为 1544

openwrt 需要装上 kmod_macvlan 和 ip 两个包,另外代码需要修改 ar8216.c 的 vlan 个数。 最后还需要 macvlan.sh 和 setpvid.sh,下载来放在 openwrt 的 /lib/netifd/proto 里面,可能需要加执行权限,不确定。

最后我的 /etc/config/network 配置大概如下。 0 口是 cpu, 1 口是 wan, 5 口是 iptv

config switch
option reset ‘1’
option enable_vlan ‘1’
option name ‘switch0’

config interface ’loopback’
option ifname ’lo’
option proto ‘static’
option ipaddr ‘127.0.0.1’
option netmask ‘255.0.0.0’

config switch_vlan
option vlan ‘1’
option ports ‘0t 2 3 4’
option device ‘switch0’

config interface ’lan’
option ifname ’eth0.1’
option type ‘bridge’
option proto ‘static’
option ipaddr ‘192.168.1.1’
option netmask ‘255.255.255.0’

config switch_vlan
option vlan ‘3999’
option ports ‘0t 1t’
option device ‘switch0’

config interface ’tr069base’
option ifname ’eth0.3999’
option proto ‘macvlan’ # macvlan 支持,需要我做的 macvlan.sh
option device ’eth2’
option hwaddr ‘XX:XX:XX:XX:XX:XX’ # 家庭网关 mac

config interface ’tr069’
option ifname ’eth2’
option proto ‘pppoe’
option username ‘bjcnc-hgw@hgw-nms’
option password ’tr069 密码’ # 这个值是我监听联通家庭网关得到的,不确定别人的是不是一样,所以不贴了。
option defaultroute ‘0’
option peerdns ‘0’

config switch_vlan
option vlan ‘344’
option ports ‘0t 1t’
option device ‘switch0’

config interface ‘wan’
option ifname ’eth0.344’
option proto ‘pppoe’
option username ‘adsl 拨号用户名’
option password ‘adsl 拨号密码’

config switch_vlan
option vlan ‘1544’
option ports ‘1t 5’
option device ‘switch0’

config interface ‘iptv’
option ifname ’eth0.1544’
option proto ‘setpvid’ # 实现的 pvid 支持,需要 setpvid.sh
option device ‘switch0’
option port ‘1’
option pvid ‘1544’

话说如果是光纤到户,用光猫的一般就不用这么费劲了,买一个支持直接分 vlan 的光猫就可以了。这个实在是太折腾了。。。

Update: 刚刚 Build 了一个都改好的 mw4530r 固件,有兴趣的可以从这里下载,不过不是 12.09 release 的,是 trunk 里面的当前最新版本,12.09 release 在我这里跟 ubuntu 的 sky2 驱动有兼容问题,ubuntu 网卡流量一大驱动就会出错,路由器固件升级到 trunk 就没这毛病了。