服务器具有固定的192.168.2.100地址,设备具有固定的192.168.2.101地址.启动时,它会连接下载固件.
在当前设置中,只有一个设备可以同时工作.但是我希望能够尽可能多地闪存设备(因为我们可以有一些大规模的闪存要求).
为了绕过路由问题,我制作了一个xinetd版本,将setsockopt设置为SO_BIND_DEVICE.
但我没有说的是,Linux无法同时处理两个接口上的ARP请求.
如果我同时执行“ping 192.168.2.101 -I usb0”和“ping 192.168.2.101 -I usb1”,它将在一个界面上运行:
ARP,Request who-has sk tell 192.168.2.100,length 28 ARP,Reply 192.168.2.101 is-at 7a:0f:66:7c:fc:2c (oui Unknown),length 28 IP 192.168.2.100 > 192.168.2.101: ICMP echo request,id 21807,seq 1,length 64 IP 192.168.2.101 > 192.168.2.100: ICMP echo reply,length 64
但另一方面它不会:
IP 192.168.2.100 > 192.168.2.101: ICMP echo request,id 31071,length 64 ARP,Request who-has 192.168.2.100 tell 192.168.2.101,seq 2,length 64 IP 192.168.2.100 > 192.168.2.101: ICMP echo request,id 31077,length 28
服务器似乎没有回答ARP请求.
这是使用/etc/network/if-up.d/000-first脚本在服务器上处理设备连接的方法:
ifconfig $IFACE up ifconfig $IFACE 192.168.2.100 PID=/var/run/xinetd-$IFACE.pid # this is the modified xinetd version to bind on one address kill -9 `cat $PID` xinetd -pidfile $PID -interface $IFACE # I tried this to force the handling of ARP table per interface,but it doesn't change anything: # /usr/sbin/arpd -b /tmp/$IFACE.db -a 3 -k $IFACE
这是修改后的xinetd版本:
https://github.com/fclairamb/xinetd/commit/1f5c1e8f9944e372b137e6aa46247f8de807bece#L8R253
解决方法
echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
选项1:一些connmark / policy route mangling
如果单独使用代理arp不起作用,我不能保证这会起作用,但我认为它值得一试.我要描述的是如何设置策略路由以使用conntrack基于输入接口绑定响应.我将描述如何为两个接口设置它,它应该很容易扩展到任何数字.另一方面,它可能只是变得非常困惑而不是工作(可能是因为内核arp表不知道它应该缓存每个设备的ip / mac对).如果发生这种情况,请尝试第二种更难看的方法.
首先,设置一些connmark mangle规则:
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT
在/ etc / iproute2 / rt_tables中添加两个表,100和101,将它们标记为usb0和usb1
100 usb0 101 usb1
对于这些表中的每一个,添加以下内容(将< N>替换为适当的数字):
ip route add 192.168.2.0/24 dev usb<N> table usb<N> ip rule add fw <N> table usb<N> iptables -t mangle -A PREROUTING -i usb<N> -j MARK --set-mark <N>
我不确定,但您可能需要设置一个这样的虚拟接口,以便您的tftp守护进程监听:
modprobe dummy ifconfig dummy0 192.168.2.100/32 up echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp sysctl net.ipv4.ip_forward=1 iptables -I FORWARD -s 192.168.2.100 -j ACCEPT iptables -I FORWARD -d 192.168.2.100 -j ACCEPT
现在测试两个设备.如果它工作,优秀,否则尝试下一个方法:
选项2:每个usb网络设备的kvm容器
选项2更加丑陋,涉及一些桥接和qemu / kvm. virt-manager可能是创建这些东西的最简单方法.
创建tap设备和桥接器,每个usb接口一个.
tunctl -t tap<N> brctl addbr usb<N>br brctl addif usb<N>br tap<N> brctl addif usb<N>br usb<N> # this may need to be done each time the usb device is connected/disconnected.
创建一个kvm映像文件或启动CD,设计为只读并托管您的tftp服务器和映像…或省略只读,并为每个vm制作一个映像文件(使用快照更好,但更多的是范围比这个答案得到的).
使用tap界面和图像文件运行kvm并测试usb网络连接.
对照
如果connmark / policy route工作,则同步维护tftp存储库要容易得多.使用KVM,您可能需要为每个VM映像创建一个存储库(除非您将只读目录传递给每个VM,这是可行的). Connmark /策略路由有点挑剔,但它也只需要一个tftp服务器,但如果你的端口不够随机,conntrack可能会混淆并覆盖端口重叠(或者它可能没有).另一方面,桥接到kvms需要更多的内存;每个连接的USB设备都有一个完整的虚拟机,但每次都有可能工作,因为虚拟机有一个完整的隔离网络堆栈可以使用,而主机内核只需要通过网桥来回传递数据包,尤其是桥接过滤时已关闭.
希望这两个中的一个适合你.