第一百二十九章:网络之道
问道期涉及内核源码:
一
林小源站在网络之海的最高处,回望整个旅程。从 socket 到 TCP,从 UDP 到路由,从 sk_buff 到 netfilter,从 eBPF 到网络命名空间——每一步都让他对网络有了更深的理解。
"你看到了什么?"一个苍老的声音从身后传来。
林小源转身,看到一个白发老者坐在山顶的石亭中。老者的面前摆着一盘棋,棋盘上每一层都是不同的网络协议——应用层、传输层、网络层、链路层,像一座四层的宝塔。
"分层。"林小源说,"网络的核心是分层。"
老者微微点头:"说下去。"
"每一层都有自己的职责。"林小源走到棋盘旁,"应用层处理应用逻辑——HTTP、SSH。传输层处理端到端通信——TCP、UDP。网络层处理路由和寻址——IP。链路层处理物理传输——以太网。每一层对上层提供抽象,对下层隐藏细节。"
"那端到端原则呢?"
林小源拿起一颗棋子:"可靠性应该在端点实现,而不是在网络中间。路由器只负责转发,不负责可靠性。TCP 在端点实现可靠性,UDP 把选择权交给应用程序。网络保持简单,复杂性留给需要它的人。"
二
"还有呢?"老者问。
"抽象。"林小源说,"socket 是通信端点的抽象——不管 TCP 还是 UDP,都用同样的接口。sk_buff 是数据包的抽象——从应用层到链路层,同一个结构体。net_device 是网络设备的抽象——物理网卡、虚拟设备、bridge,都实现同样的接口。"
"可编程呢?"
"eBPF。"林小源的眼睛亮了起来,"eBPF 让网络变得可编程——用户可以在内核中运行自定义程序,实现流量过滤、负载均衡、性能监控。不需要修改内核代码,不需要重新编译内核。"
"隔离呢?"
"网络命名空间。"林小源说,"每个容器有自己的网络栈——独立的 IP、路由、防火墙。veth pair 连接命名空间,bridge 交换流量。容器以为自己有独立的网络,实际上是命名空间的隔离。"
三
老者站起身,走到山崖边,望着远方的大海。
"你看到了设计的权衡。"老者说。
林小源走到他身边:"可靠 vs 快速——TCP 可靠但有开销,UDP 快速但不可靠。安全 vs 性能——过滤有开销,但安全更重要。简单 vs 功能——简单的协议更高效,但功能丰富更实用。"
"那你觉得网络的哲学是什么?"
林小源沉思了很久:"分层让复杂变简单。端到端原则让网络保持简单。抽象让不同实现有统一的接口。可编程让内核可以扩展。隔离让多个世界共存。"
"还有呢?"
"权衡。"林小源说,"没有完美的设计,只有适合的设计。每个选择都有代价——可靠性有开销,安全有开销,功能有复杂性。好的设计不是追求完美,而是在约束中找到最优解。"
老者微微一笑:"你已经理解了网络之道。"
/*
* 网络的核心思想:
*
* 1. 分层
* 应用层: HTTP, SSH
* 传输层: TCP, UDP
* 网络层: IP
* 链路层: 以太网
* 每层对上层提供抽象
*
* 2. 端到端原则
* 可靠性在端点实现
* 网络只负责传输
* UDP 贯彻了这个原则
*
* 3. 抽象
* socket — 通信端点
* sk_buff — 数据包
* net_device — 网络设备
*
* 4. 可编程
* eBPF — 内核中的可编程
* netfilter — 钩子机制
*
* 5. 隔离
* 网络命名空间
* 容器网络
*/
printf("=== 网络之道 — 分层的艺术 ===\n\n");
printf("网络的核心思想:\n\n");
printf("1. 分层:\n");
printf(" 应用层: HTTP, SSH\n");
printf(" 传输层: TCP, UDP\n");
printf(" 网络层: IP\n");
printf(" 链路层: 以太网\n\n");
printf("2. 端到端原则:\n");
printf(" 可靠性在端点实现\n");
printf(" 网络只负责传输\n\n");
printf("3. 抽象:\n");
printf(" socket — 通信端点\n");
printf(" sk_buff — 数据包\n");
printf(" net_device — 网络设备\n\n");
printf("4. 可编程:\n");
printf(" eBPF — 内核中的可编程\n");
printf(" netfilter — 钩子机制\n\n");
printf("5. 隔离:\n");
printf(" 网络命名空间\n");
printf(" 容器网络\n\n");
printf("--- 设计的权衡 ---\n");
printf("可靠 vs 快速:\n");
printf(" TCP 可靠但有开销\n");
printf(" UDP 快速但不可靠\n\n");
printf("安全 vs 性能:\n");
printf(" 过滤有开销\n");
printf(" 但安全更重要\n\n");
printf("简单 vs 功能:\n");
printf(" 简单的协议更高效\n");
printf(" 但功能丰富更实用\n");#include <stdio.h>
/*
* 网络的核心思想:
*
* 1. 分层
* 应用层: HTTP, SSH
* 传输层: TCP, UDP
* 网络层: IP
* 链路层: 以太网
* 每层对上层提供抽象
*
* 2. 端到端原则
* 可靠性在端点实现
* 网络只负责传输
* UDP 贯彻了这个原则
*
* 3. 抽象
* socket — 通信端点
* sk_buff — 数据包
* net_device — 网络设备
*
* 4. 可编程
* eBPF — 内核中的可编程
* netfilter — 钩子机制
*
* 5. 隔离
* 网络命名空间
* 容器网络
*/
int main() {
printf("=== 网络之道 — 分层的艺术 ===\n\n");
printf("网络的核心思想:\n\n");
printf("1. 分层:\n");
printf(" 应用层: HTTP, SSH\n");
printf(" 传输层: TCP, UDP\n");
printf(" 网络层: IP\n");
printf(" 链路层: 以太网\n\n");
printf("2. 端到端原则:\n");
printf(" 可靠性在端点实现\n");
printf(" 网络只负责传输\n\n");
printf("3. 抽象:\n");
printf(" socket — 通信端点\n");
printf(" sk_buff — 数据包\n");
printf(" net_device — 网络设备\n\n");
printf("4. 可编程:\n");
printf(" eBPF — 内核中的可编程\n");
printf(" netfilter — 钩子机制\n\n");
printf("5. 隔离:\n");
printf(" 网络命名空间\n");
printf(" 容器网络\n\n");
printf("--- 设计的权衡 ---\n");
printf("可靠 vs 快速:\n");
printf(" TCP 可靠但有开销\n");
printf(" UDP 快速但不可靠\n\n");
printf("安全 vs 性能:\n");
printf(" 过滤有开销\n");
printf(" 但安全更重要\n\n");
printf("简单 vs 功能:\n");
printf(" 简单的协议更高效\n");
printf(" 但功能丰富更实用\n");
return 0;
}道藏笔记
内核启示
网络的本质是"分层"。
核心思想:
- 分层 — 每层有自己的职责
- 端到端 — 可靠性在端点实现
- 抽象 — socket、sk_buff、net_device
- 可编程 — eBPF
- 隔离 — 网络命名空间
设计的权衡:
- 可靠 vs 快速
- 安全 vs 性能
- 简单 vs 功能
网络之道是"分层"——让复杂变简单。
网络之道
网络之道总结中,让网络在不改内核代码的前提下变得可编程的机制是什么?