Linux网络栈出口路径注入IP包:自定义模块致VM挂起排查
问题:Linux内核环回模块重注入数据包导致VM挂起
我是资深软件工程师,但在网络领域存在知识盲区。现需开发一款特殊Linux内核环回模块,区别于普通lo接口,要求重注入的数据包可正常转发。
测试场景
- 执行
ping google.com -I la强制使用la接口访问google.com - 数据包被导向la接口
la_xmit捕获该数据包la_xmit通过netif_rx将新数据包注入网络栈- 数据包进入网络栈并正常路由
- 期望数据包从
eth0发出
编写的最小可行模块代码
#include <linux/module.h> #include <linux/init.h> #include <linux/skbuff.h> #include <net/ip_tunnels.h> MODULE_LICENSE("GPL"); MODULE_AUTHOR("me"); MODULE_DESCRIPTION("re-injector"); struct net_device *my_netdev; static netdev_tx_t la_xmit(struct sk_buff *captured_skb, struct net_device *dev) { int len = captured_skb->len; // move to a new skb struct sk_buff *skb = alloc_skb(len, GFP_KERNEL); memcpy(skb_put(skb, len), captured_skb->data, len); dev_kfree_skb(captured_skb); // initialize new packet skb_tx_timestamp(skb); skb_clear_tstamp(skb); skb_orphan(skb); skb_dst_force(skb); // inject into network stack int skb_len = skb->len; // copy now, after netif, it's not ours anymore int err = netif_rx(skb); if (likely(err == NET_RX_SUCCESS)) dev_lstats_add(my_netdev, skb_len); return NETDEV_TX_OK; } const struct net_device_ops ndo = { .ndo_start_xmit = la_xmit }; static void setup_netdev(struct net_device *dev) { dev->netdev_ops = &ndo; dev->header_ops = &ip_tunnel_header_ops; dev->mtu = 1500; dev->flags |= IFF_POINTOPOINT; dev->flags |= IFF_NOARP; dev->flags |= IFF_MULTICAST; } static int __init la_init(void) { my_netdev = alloc_netdev(0, "la", NET_NAME_UNKNOWN, setup_netdev); register_netdev(my_netdev); return 0; } static void __exit la_cleanup(void) { unregister_netdev(my_netdev); free_netdev(my_netdev); } module_init(la_init); module_exit(la_cleanup);
实现说明与问题现象
我参考net/loopback.c的逻辑实现注入,选用netif_rx而非__netif_rx,因后者会假设为入站流量而跳过部分路由流程。
实际结果:VM突然挂起,使用sudo journalctl -k -b -1查看上一会话日志未发现任何报错。
内容的提问来源于stack exchange,提问作者NRagot
相关产品推荐
相关产品推荐

