mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-08 14:20:18 +08:00
更新笔记 添加更详细的注释 截止到地址解析的实现
This commit is contained in:
@@ -91,6 +91,7 @@ func (n *NIC) isPromiscuousMode() bool {
|
||||
// 相当于给网卡添加ip地址
|
||||
func (n *NIC) addAddressLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address,
|
||||
peb PrimaryEndpointBehavior, replace bool) (*referencedNetworkEndpoint, *tcpip.Error) {
|
||||
// 检查网卡绑定的协议栈是否注册过该网络协议
|
||||
netProto, ok := n.stack.networkProtocols[protocol]
|
||||
if !ok {
|
||||
return nil, tcpip.ErrUnknownProtocol
|
||||
@@ -112,15 +113,20 @@ func (n *NIC) addAddressLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.
|
||||
n.removeEndpointLocked(ref) // 这里被调用的时候已经上过锁了 NOTE
|
||||
}
|
||||
|
||||
// 新建一个网络端点的引用 为什么是一个引用
|
||||
// 这是为了复用 所有使用该IP地址的传输层报文都可以复用它
|
||||
ref := &referencedNetworkEndpoint{
|
||||
refs: 1,
|
||||
ep: ep,
|
||||
nic: n,
|
||||
protocol: protocol,
|
||||
holdsInsertRef: true,
|
||||
refs: 1, // 初始的引用计数
|
||||
ep: ep, // 引用的网络端点
|
||||
nic: n, // 网络端点所在的网卡
|
||||
protocol: protocol, // 网络协议
|
||||
holdsInsertRef: true, // 防止空引用
|
||||
}
|
||||
|
||||
// Set up cache if link address resolution exists for this protocol.
|
||||
// 如果该网卡驱动 配置了允许地址解析
|
||||
// 我们让网卡绑定的协议栈来作为该网络端点的MAC解析缓存器
|
||||
// 这样当我们向目标地址发送ip报文的时候 会检查缓存里是否存在 ip:mac 的对应关系
|
||||
// 如果不存在 就会调用arp协议发广播来定位这个ip对应的设备
|
||||
if n.linkEP.Capabilities()&CapabilityResolutionRequired != 0 {
|
||||
if _, ok := n.stack.linkAddrResolvers[protocol]; ok {
|
||||
ref.linkCache = n.stack
|
||||
@@ -134,12 +140,17 @@ func (n *NIC) addAddressLocked(protocol tcpip.NetworkProtocolNumber, addr tcpip.
|
||||
log.Printf("基于[%d]协议 为 #%d 网卡 添加网络层实现 并绑定地址到: %s\n", netProto.Number(), n.id, ep.ID().LocalAddress)
|
||||
})
|
||||
|
||||
/*
|
||||
[tcp]->192.168.1.1->192.168.1.2->172.10.1.1->...
|
||||
[udp]->10.10.1.1->192.168.1.1->...
|
||||
**/
|
||||
l, ok := n.primary[protocol]
|
||||
if !ok {
|
||||
l = &ilist.List{}
|
||||
n.primary[protocol] = l
|
||||
}
|
||||
|
||||
// 保存该ip的引用
|
||||
switch peb {
|
||||
case CanBePrimaryEndpoint:
|
||||
l.PushBack(ref) // 目前走这一支
|
||||
|
@@ -298,13 +298,21 @@ func New(network []string, transport []string, opts Options) *Stack {
|
||||
}
|
||||
|
||||
s := &Stack{
|
||||
// 用来保存各种传输层协议
|
||||
transportProtocols: make(map[tcpip.TransportProtocolNumber]*transportProtocolState),
|
||||
// 用来保存各种网络层协议
|
||||
networkProtocols: make(map[tcpip.NetworkProtocolNumber]NetworkProtocol),
|
||||
// 用来保存各种地址解析协议
|
||||
linkAddrResolvers: make(map[tcpip.NetworkProtocolNumber]LinkAddressResolver),
|
||||
// 用来保存所有使用该协议栈的网卡实例
|
||||
nics: make(map[tcpip.NICID]*NIC),
|
||||
// 链路层MAC缓存器
|
||||
linkAddrCache: newLinkAddrCache(ageLimit, resolutionTimeout, resolutionAttempts),
|
||||
// 端口管理器
|
||||
PortManager: ports.NewPortManager(),
|
||||
// 协议栈时钟
|
||||
clock: clock,
|
||||
// 协议栈状态管理器
|
||||
stats: opts.Stats.FillIn(),
|
||||
}
|
||||
|
||||
@@ -474,8 +482,9 @@ func (s *Stack) CreateNamedNIC(id tcpip.NICID, name string, linkEP tcpip.LinkEnd
|
||||
return s.createNIC(id, name, linkEP, true)
|
||||
}
|
||||
|
||||
// 新建一个网卡对象,并且激活它 激活就是准备好熊网卡中读取和写入数据
|
||||
// 新建一个网卡对象,并且激活它 激活就是准备好从网卡中读取和写入数据
|
||||
func (s *Stack) createNIC(id tcpip.NICID, name string, linkEP tcpip.LinkEndpointID, enable bool) *tcpip.Error {
|
||||
// 从全局寻找该链路层设备是否注册过
|
||||
ep := FindLinkEndpoint(linkEP)
|
||||
if ep == nil {
|
||||
return tcpip.ErrBadLinkEndpoint
|
||||
@@ -488,8 +497,10 @@ func (s *Stack) createNIC(id tcpip.NICID, name string, linkEP tcpip.LinkEndpoint
|
||||
if _, ok := s.nics[id]; ok {
|
||||
return tcpip.ErrDuplicateNICID
|
||||
}
|
||||
// 新建网卡对象 包括 网卡归属的协议栈 网卡号 网卡名 网卡驱动
|
||||
n := newNIC(s, id, name, ep)
|
||||
|
||||
// 给协议栈注册这个网卡设备
|
||||
s.nics[id] = n
|
||||
if enable {
|
||||
n.attachLinkEndpoint()
|
||||
@@ -586,9 +597,9 @@ func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address,
|
||||
}
|
||||
|
||||
var ref *referencedNetworkEndpoint
|
||||
if len(localAddr) != 0 {
|
||||
if len(localAddr) != 0 { // 要是指定了本地ip
|
||||
ref = nic.findEndpoint(netProto, localAddr, CanBePrimaryEndpoint) // 找到绑定LocalAddr的IP端
|
||||
} else {
|
||||
} else { // 要是没指定本地ip 从当前网卡绑定的所有ip里找个能用的
|
||||
ref = nic.primaryEndpoint(netProto)
|
||||
}
|
||||
if ref == nil {
|
||||
@@ -606,7 +617,6 @@ func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address,
|
||||
logger.GetInstance().Info(logger.IP, func() {
|
||||
log.Println(r.LocalLinkAddress, r.LocalAddress, r.RemoteLinkAddress, r.RemoteAddress, r.NextHop)
|
||||
})
|
||||
log.Println(s.routeTable[i])
|
||||
return r, nil
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,8 @@ type transportEndpoints struct {
|
||||
|
||||
// transportDemuxer 解复用战队传输端点的数据包
|
||||
// 他执行两级解复用:首先基于网络层和传输协议 然后基于端点ID
|
||||
// 在我们注册完各种网络层、传输层协议后,我们还需要一个分流器让各种数据准确地找到自己的处理端,不能让一个ipv4的tcp连接最终被一个ipv6的udp处理端解析。
|
||||
// 那么对于任意一个传输层数据流,它应当唯一标识为 `网络层协议-传输层协议-目标IP-目标端口-本地IP-本地端口`的一个六元组
|
||||
type transportDemuxer struct {
|
||||
protocol map[protocolIDs]*transportEndpoints
|
||||
}
|
||||
|
Reference in New Issue
Block a user