mirror of
https://github.com/impact-eintr/netstack.git
synced 2025-10-06 05:16:50 +08:00
udp基本写完了 关于socket的不少细节还没看 另外在网络栈静置一段时间后再次发起连接将无法找到路由
This commit is contained in:
@@ -202,7 +202,7 @@ func (c *linkAddrCache) makeAndAddEntry(k tcpip.FullAddress, v tcpip.LinkAddress
|
||||
|
||||
// get reports any known link address for k.
|
||||
func (c *linkAddrCache) get(k tcpip.FullAddress, linkRes LinkAddressResolver, localAddr tcpip.Address, linkEP LinkEndpoint, waker *sleep.Waker) (tcpip.LinkAddress, <-chan struct{}, *tcpip.Error) {
|
||||
log.Printf("link addr get linkRes: %#v, addr: %+v", linkRes, k)
|
||||
log.Println("在arp本地缓存中寻找", k)
|
||||
if linkRes != nil {
|
||||
if addr, ok := linkRes.ResolveStaticAddress(k.Addr); ok {
|
||||
return addr, nil, nil
|
||||
|
@@ -302,6 +302,23 @@ func (n *NIC) Subnets() []tcpip.Subnet {
|
||||
return append(sns, n.subnets...)
|
||||
}
|
||||
|
||||
// RemoveAddress removes an address from n.
|
||||
func (n *NIC) RemoveAddress(addr tcpip.Address) *tcpip.Error {
|
||||
n.mu.Lock()
|
||||
r := n.endpoints[NetworkEndpointID{addr}]
|
||||
if r == nil || !r.holdsInsertRef {
|
||||
n.mu.Unlock()
|
||||
return tcpip.ErrBadLocalAddress
|
||||
}
|
||||
|
||||
r.holdsInsertRef = false
|
||||
n.mu.Unlock()
|
||||
|
||||
r.decRef()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeliverNetworkPacket 当 NIC 从物理接口接收数据包时,将调用函数 DeliverNetworkPacket,用来分发网络层数据包。
|
||||
// 比如 protocol 是 arp 协议号,那么会找到arp.HandlePacket来处理数据报。
|
||||
// 简单来说就是根据网络层协议和目的地址来找到相应的网络层端,将网络层数据发给它,
|
||||
@@ -323,7 +340,7 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr, localLin
|
||||
return
|
||||
}
|
||||
src, dst := netProto.ParseAddresses(vv.First())
|
||||
log.Printf("设备[%v]准备从 [%s] 向 [%s] 分发数据: %v\n", linkEP.LinkAddress(), src, dst, func() []byte {
|
||||
log.Printf("网卡[%v]准备从 [%s] 向 [%s] 分发数据: %v\n", linkEP.LinkAddress(), src, dst, func() []byte {
|
||||
if len(vv.ToView()) > 64 {
|
||||
return vv.ToView()[:64]
|
||||
}
|
||||
@@ -334,6 +351,8 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr, localLin
|
||||
if ref := n.getRef(protocol, dst); ref != nil {
|
||||
r := makeRoute(protocol, dst, src, linkEP.LinkAddress(), ref)
|
||||
r.RemoteLinkAddress = remoteLinkAddr
|
||||
log.Println("准备前往 IP 将本地和远端的MAC、IP 保存在路由中 以便协议栈使用",
|
||||
r.LocalLinkAddress, r.RemoteLinkAddress, r.LocalAddress, r.RemoteAddress)
|
||||
ref.ep.HandlePacket(&r, vv)
|
||||
ref.decRef()
|
||||
return
|
||||
@@ -377,7 +396,7 @@ func (n *NIC) getRef(protocol tcpip.NetworkProtocolNumber, dst tcpip.Address) *r
|
||||
|
||||
n.mu.RLock()
|
||||
if ref, ok := n.endpoints[id]; ok && ref.tryIncRef() {
|
||||
log.Println("找到了目标网络层实现: ", id.LocalAddress)
|
||||
log.Println("找到了目标网络端(绑定过的IP): ", id.LocalAddress)
|
||||
n.mu.RUnlock()
|
||||
return ref
|
||||
}
|
||||
@@ -434,7 +453,7 @@ func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolN
|
||||
n.stack.stats.MalformedRcvdPackets.Increment()
|
||||
return
|
||||
}
|
||||
log.Println("准备分发传输层数据报", n.stack.transportProtocols, srcPort, dstPort)
|
||||
log.Println("网卡准备分发传输层数据报", n.stack.transportProtocols, srcPort, dstPort)
|
||||
id := TransportEndpointID{dstPort, r.LocalAddress, srcPort, r.RemoteAddress}
|
||||
// 调用分流器,根据传输层协议和传输层id分发数据报文
|
||||
if n.demux.deliverPacket(r, protocol, vv, id) {
|
||||
@@ -480,7 +499,6 @@ type referencedNetworkEndpoint struct {
|
||||
// linkCache is set if link address resolution is enabled for this
|
||||
// protocol. Set to nil otherwise.
|
||||
linkCache LinkAddressCache
|
||||
linkAddrCache
|
||||
|
||||
// holdsInsertRef is protected by the NIC's mutex. It indicates whether
|
||||
// the reference count is biased by 1 due to the insertion of the
|
||||
|
@@ -49,7 +49,7 @@ type LinkEndpoint interface {
|
||||
IsAttached() bool
|
||||
}
|
||||
|
||||
// LinkAddressResolver 是对可以解析链接地址的 NetworkProtocol 的扩展 TODO 需要解读
|
||||
// LinkAddressResolver 是对可以解析链接地址的 NetworkProtocol 的扩展 其实就是ARP
|
||||
type LinkAddressResolver interface {
|
||||
LinkAddressRequest(addr, localAddr tcpip.Address, linkEP LinkEndpoint) *tcpip.Error
|
||||
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"netstack/sleep"
|
||||
"netstack/tcpip"
|
||||
"netstack/tcpip/buffer"
|
||||
"netstack/tcpip/header"
|
||||
)
|
||||
|
||||
// 贯穿整个协议栈的路由,也就是在链路层和网络层都可以路由
|
||||
@@ -57,11 +58,48 @@ func (r *Route) Stats() tcpip.Stats {
|
||||
return r.ref.nic.stack.Stats()
|
||||
}
|
||||
|
||||
// PseudoHeaderChecksum forwards the call to the network endpoint's
|
||||
// implementation.
|
||||
// udp或tcp伪首部校验和的计算
|
||||
func (r *Route) PseudoHeaderChecksum(protocol tcpip.TransportProtocolNumber) uint16 {
|
||||
return header.PseudoHeaderChecksum(protocol, r.LocalAddress, r.RemoteAddress)
|
||||
}
|
||||
|
||||
// Capabilities returns the link-layer capabilities of the route.
|
||||
func (r *Route) Capabilities() LinkEndpointCapabilities {
|
||||
return r.ref.ep.Capabilities()
|
||||
}
|
||||
|
||||
// Resolve 如有必要,解决尝试解析链接地址的问题。如果地址解析需要阻塞,则返回ErrWouldBlock,
|
||||
// 例如等待ARP回复。地址解析完成(成功与否)时通知Waker。
|
||||
// 如果需要地址解析,则返回ErrNoLinkAddress和通知通道,以阻止顶级调用者。
|
||||
// 地址解析完成后,通道关闭(不管成功与否)。
|
||||
func (r *Route) Resolve(waker *sleep.Waker) (<-chan struct{}, *tcpip.Error) {
|
||||
if !r.IsResolutionRequired() {
|
||||
// Nothing to do if there is no cache (which does the resolution on cache miss) or
|
||||
// link address is already known.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
nextAddr := r.NextHop
|
||||
if nextAddr == "" {
|
||||
// Local link address is already known.
|
||||
if r.RemoteAddress == r.LocalAddress { // 发给自己
|
||||
r.RemoteLinkAddress = r.LocalLinkAddress // MAC 就是自己
|
||||
return nil, nil
|
||||
}
|
||||
nextAddr = r.RemoteAddress // 下一跳是远端机
|
||||
}
|
||||
|
||||
// 调用地址解析协议来解析IP地址
|
||||
linkAddr, ch, err := r.ref.linkCache.GetLinkAddress(r.ref.nic.ID(), nextAddr, r.LocalAddress, r.NetProto, waker)
|
||||
if err != nil {
|
||||
return ch, err
|
||||
}
|
||||
r.RemoteLinkAddress = linkAddr
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// RemoveWaker removes a waker that has been added in Resolve().
|
||||
func (r *Route) RemoveWaker(waker *sleep.Waker) {
|
||||
nextAddr := r.NextHop
|
||||
|
@@ -38,7 +38,7 @@ type transportProtocolState struct {
|
||||
type Stack struct {
|
||||
transportProtocols map[tcpip.TransportProtocolNumber]*transportProtocolState // 各种传输层协议
|
||||
networkProtocols map[tcpip.NetworkProtocolNumber]NetworkProtocol // 各种网络层协议
|
||||
linkAddrResolvers map[tcpip.NetworkProtocolNumber]LinkAddressResolver // 各种链接解析器
|
||||
linkAddrResolvers map[tcpip.NetworkProtocolNumber]LinkAddressResolver // 支持链接层反向解析的网络层协议
|
||||
|
||||
demux *transportDemuxer // 传输层的复用器
|
||||
|
||||
@@ -103,6 +103,12 @@ func New(network []string, transport []string, opts Options) *Stack {
|
||||
}
|
||||
netProto := netProtoFactory() // 制造一个该型号协议的示实例
|
||||
s.networkProtocols[netProto.Number()] = netProto // 注册该型号的网络协议
|
||||
// 判断该协议是否支持链路层地址解析协议接口,如果支持添加到 s.linkAddrResolvers 中,
|
||||
// 如:ARP协议会添加 IPV4-ARP 的对应关系
|
||||
// 后面需要地址解析协议的时候会更改网络层协议号来找到相应的地址解析协议
|
||||
if r, ok := netProto.(LinkAddressResolver); ok {
|
||||
s.linkAddrResolvers[r.LinkAddressProtocol()] = r // 其实就是说: 声明arp支持地址解析
|
||||
}
|
||||
}
|
||||
|
||||
// 添加指定的传输层协议 必已经在init中注册过
|
||||
@@ -335,6 +341,19 @@ func (s *Stack) ContainsSubnet(id tcpip.NICID, subnet tcpip.Subnet) (bool, *tcpi
|
||||
return false, tcpip.ErrUnknownNICID
|
||||
}
|
||||
|
||||
// RemoveAddress removes an existing network-layer address from the specified
|
||||
// NIC.
|
||||
func (s *Stack) RemoveAddress(id tcpip.NICID, addr tcpip.Address) *tcpip.Error {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
if nic, ok := s.nics[id]; ok {
|
||||
return nic.RemoveAddress(addr)
|
||||
}
|
||||
|
||||
return tcpip.ErrUnknownNICID
|
||||
}
|
||||
|
||||
// FindRoute 路由查找实现,比如当tcp建立连接时,会用该函数得到路由信息
|
||||
func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address,
|
||||
netProto tcpip.NetworkProtocolNumber) (Route, *tcpip.Error) {
|
||||
@@ -354,7 +373,7 @@ func (s *Stack) FindRoute(id tcpip.NICID, localAddr, remoteAddr tcpip.Address,
|
||||
|
||||
var ref *referencedNetworkEndpoint
|
||||
if len(localAddr) != 0 {
|
||||
ref = nic.findEndpoint(netProto, localAddr, CanBePrimaryEndpoint)
|
||||
ref = nic.findEndpoint(netProto, localAddr, CanBePrimaryEndpoint) // 找到绑定LocalAddr的IP端
|
||||
} else {
|
||||
ref = nic.primaryEndpoint(netProto)
|
||||
}
|
||||
@@ -426,7 +445,7 @@ func (s *Stack) GetLinkAddress(nicid tcpip.NICID, addr, localAddr tcpip.Address,
|
||||
}
|
||||
s.mu.RUnlock()
|
||||
|
||||
fullAddr := tcpip.FullAddress{NIC: nicid, Addr: addr}
|
||||
fullAddr := tcpip.FullAddress{NIC: nicid, Addr: addr} // addr 可能是Remote IP Address
|
||||
// 根据网络层协议号找到对应的地址解析协议
|
||||
linkRes := s.linkAddrResolvers[protocol]
|
||||
return s.linkAddrCache.get(fullAddr, linkRes, localAddr, nic.linkEP, w)
|
||||
@@ -497,3 +516,14 @@ func (s *Stack) TransportProtocolInstance(num tcpip.TransportProtocolNumber) Tra
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// JoinGroup joins the given multicast group on the given NIC.
|
||||
func (s *Stack) JoinGroup(protocol tcpip.NetworkProtocolNumber, nicID tcpip.NICID, multicastAddr tcpip.Address) *tcpip.Error {
|
||||
// TODO: notify network of subscription via igmp protocol.
|
||||
return s.AddAddressWithOptions(nicID, protocol, multicastAddr, NeverPrimaryEndpoint)
|
||||
}
|
||||
|
||||
// LeaveGroup leaves the given multicast group on the given NIC.
|
||||
func (s *Stack) LeaveGroup(protocol tcpip.NetworkProtocolNumber, nicID tcpip.NICID, multicastAddr tcpip.Address) *tcpip.Error {
|
||||
return s.RemoveAddress(nicID, multicastAddr)
|
||||
}
|
||||
|
Reference in New Issue
Block a user