当前Linux内核的实现,一个socket监听在一个特定的网络命名空间中,不同的命名空间可有具有相同的socket,即可监听相同的地址端口,这样很好的实现网络隔离虚拟化的功能。但是对于网路设备来说,并不需要如此完全的隔离。比如VPN设备/路由器等,一个ike进程或者quagga进程能监听在所有的命名空间,更利于实现和管理。

这样就要求应用层socket能够接收到所有命名空间的数据包,并且能够感知当前连接的命名空间。

数据包接收

内核默认创建一个网络命名空间(init_net),起初所有的socket都监听在默认的网络命名空间。要能够接收其它命名空间的数据包,需要修改sock查找函数。在一个新的连接请求进来之后,查找监听sock时(__inet_lookup_listener),内核默认仅在接收数据包所在的命名空间查找。修改为在找不到的情况下,去init_net命名空间查找,此时,监听在init_net的socket就能接收到新的连接了。

sk = __inet_lookup_listener(dev_net(dev), hashinfo, saddr, sport, daddr, hnum, dif, flags);
if (!sk) {sk = __inet_lookup_listener(&init_net, hashinfo, saddr, sport, daddr, hnum, dif, flags);
}

以上是TCP的sock查找修改,对于UDP可做相同的修改。

数据包发送

sock的查找修改之后已经可以接收到新的连接请求,但是并没有修改sock结构中的sk_net的值,其还是init_net(socket总监听在此命名空间),不能使用其查找路由。如要能正常回复此连接请求(SYN+ACK),我们的sock需要使用接收到数据包的接口所在net_namespace的路由。所以在请求路由时,使用接收命名空间查找:

static inline struct net *sock_net(const struct sock *sk)
{return read_pnet(&sk->sk_net);
}
struct dst_entry *inet_csk_route_req(struct sock *sk, struct flowi4 *fl4, const struct request_sock *req)
{rt = ip_route_output_flow(skb_real_net, fl4, sk);
}

发送连接建立之后正常的数据包涉及到的也是路由问题,如何告诉内核代码要在哪个命名空间发送?此时需要在创建子sock的时候,把真正的接收命名空间保存在子sock中。在发送时使用。例如ip_queue_xmit函数,查询路由时使用真正的child_sk_real_net去查:

int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
{rt = ip_route_output_ports(child_sk_real_net, fl4, sk, daddr, inet->inet_saddr,inet->inet_dport, inet->inet_sport, sk->sk_protocol, RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
}

方能找到正确的出口路由,正常发送数据包。实现应用层socket监听多个网络命名空间。

实现socket监听所有网络命名空间相关推荐

  1. Linux内核网络协议栈8—socket监听

    几个问题  了解以下几个问题的同学可以直接忽略下文: 1.listen 库函数主要做了什么?  2. 什么是最大并发连接请求数?  3.什么是等待连接队列? socket 监听相对还是比较简单的,先看 ...

  2. Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

    本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.c ...

  3. 多线程使用SO_REUSEPORT来实现多个socket监听同一个端口

    在十几年前的 FreeBSD 中就存在 SO_REUSEPORT 参数来实现多个 socket 监听同一个端口,来提升服务器的负载,在 Linux 3.9 开始也引入了这个功能,下面就看一下例子. # ...

  4. android 信号强度变化,Android监听WIFI网络的变化并且获得当前信号强度

    MainActivity如下: package cc.testwifi; import android.os.Bundle; import android.app.Activity; /** * De ...

  5. 安卓网络连接全解:包括网络连接状态的监听、网络数据使用状态的监听、获取当前网络连接情况、启动wifi、获取当前连接wifi的网络情况、扫描wifi热点

    全栈工程师开发手册 (作者:栾鹏) 安卓教程全解 安卓网络连接情况全解:包括网络连接状态的监听.网络数据使用状态的监听.获取当前网络连接情况.启动wifi.获取当前连接wifi的网络情况.扫描wifi ...

  6. html5中检测网络状态的方法,前端js监听浏览器网络变化

    首先,为什么要让前端判断用户的网络状态呢--为了更好的用户体验. 其次,前端能否判断网络状态?有哪些方法? 1,可以做到渐进式判断,不能做到绝对准确. 2,使用的是navigator.onLine或n ...

  7. Android监听手机网络变化

    Android监听手机网络变化 手机网络状态发生变化会发送广播,利用广播接收者,监听手机网络变化 效果图 注册广播接收者 <?xml version="1.0" encodi ...

  8. java起socket监听,java socket 监听示例,javasocket,java socket监

    java socket 监听示例,javasocket,java socket监 java socket监听示例: socket监听需要使用SocketServer类,如下代码:package cn. ...

  9. linux listen监听,Linux网络协议栈 -- socket listen监听

    一.sys_listen 对面向连接的协议,在调用 bind(2)后,进一步调用 listen(2),让套接字进入监听状态: int listen(int sockfd, int backlog); ...

  10. python tcp不用循环监听_网络编程: TCP

    1. IP 地址 概念: 标识网络中设备的地址(需要联网才有没有联网, 是没有这个地址) 表现形式: ipv4 目前主要使用的, 点分十进制的格式,(192.168.3.43) 分为 4 段, 每段的 ...

最新文章

  1. Linux01-Linux高级特殊权限SUID详解25
  2. SQL Server 批量完整备份
  3. python多线程同步与互斥_Python之多线程:线程互斥与线程同步
  4. Linux 内核完成 urb: 完成回调处理者
  5. 十进制 转换 2-10 进制,int的扩展方法
  6. 计算机桌面上的声音图标没了怎么办,Win7电脑右下角声音图标不见了怎么办?...
  7. H3C vrrp *** ipsec 基本配置
  8. 直方图均衡化 原理、流程、公式推导及matlab实现
  9. win 10 系统怎么显示隐藏文件
  10. 4G智能模组SIM7600CE兼容移远EC20
  11. 20000本当当豆瓣畅销书电子书免费领取,免费送
  12. mac换硬盘重装系统记录
  13. Win10系统Edge可以上网其他浏览器不能上网怎么回事
  14. landsat7数据预处理
  15. Qt 数字报阅读器 图文版
  16. Linux下删除特殊字符的文件或文件夹
  17. Python之freshman07 面向对象编程jinjie
  18. 【转】经济学名词解释大全汇总
  19. mysql 慢查询优化_MySQL 性能优化之慢查询
  20. page31-layui点击显示和隐藏页面层

热门文章

  1. 史上最难php,世界上最难的简单几何体 - 我为数学狂 - 简单学习网论坛_中高考学习交流论坛_中学生学习论坛 - Powered by phpwind...
  2. Altium Designer之泪点和常规铺铜操作笔记
  3. UNI/TUBE2新配对上线,Eswap迎来新机遇
  4. 谷歌是如何跌下神坛的?
  5. SuperMemo 15.1
  6. python查火车票_Python查询火车票(三)
  7. Busting Frame Busting
  8. python之生成器函数
  9. 明日之后手机正版服务器,明日之后能不能换区 明日之后手游渠道服怎么转换成网易官方服...
  10. 2022考研:数学考研备考规划