diff --git a/tcpip/ilist/list.go b/tcpip/ilist/list.go new file mode 100644 index 0000000..b292e85 --- /dev/null +++ b/tcpip/ilist/list.go @@ -0,0 +1,150 @@ +// 包 ilist 提供了侵入式链表的实现 +package ilist + +type Linker interface { + Next() Element + Prev() Element + SetNext(Element) + SetPrev(Element) +} + +type Element interface { + Linker +} + +// ElementMapper 默认提供身份映射。 +// 如果它们不相同,则可以替换它以提供将元素映射到链接器对象的结构。 +// 在以下情况下通常不需要 ElementMapper:Linker 保持原样,Element 保持原样, +// 或者 Linker 和 Element 是相同类型 +type ElementMapper struct{} + +// linkerFor maps an Element to a Linker. +// This default implementation should be inline 1d +func (ElementMapper) linkerFor(elem Element) Linker { + return elem +} + +type List struct { + head Element + tail Element +} + +func (l *List) Reset() { + l.head = nil + l.tail = nil +} + +func (l *List) Empty() bool { + return l.head == nil +} + +func (l *List) Front() Element { + return l.head +} + +func (l *List) Back() Element { + return l.tail +} + +func (l *List) PushFront(e Element) { + ElementMapper{}.linkerFor(e).SetPrev(nil) + ElementMapper{}.linkerFor(e).SetNext(l.head) //当前头部作为新头部的下一个节点 + + if l.head != nil { + ElementMapper{}.linkerFor(l.head).SetPrev(e) + } else { + l.tail = e + } + l.head = e +} + +func (l *List) PushBack(e Element) { + ElementMapper{}.linkerFor(e).SetPrev(l.tail) // 当前尾部作为新尾部的上一个节点 + ElementMapper{}.linkerFor(e).SetNext(nil) + + if l.tail != nil { + ElementMapper{}.linkerFor(l.tail).SetNext(e) + } else { + l.head = e + } + l.tail = e +} + +// 将m尾插到l,然后清除m +func (l *List) PushBackList(m *List) { + // 如果没有 + if l.head == nil { + l.head = m.head + l.tail = m.tail + } else { + ElementMapper{}.linkerFor(l.tail).SetNext(m.head) + ElementMapper{}.linkerFor(m.head).SetPrev(l.tail) + l.tail = m.tail + } + m.head = nil + m.tail = nil +} + +func (l *List) InsertAfter(b, e Element) { + a := ElementMapper{}.linkerFor(b).Next() + ElementMapper{}.linkerFor(e).SetNext(a) + ElementMapper{}.linkerFor(e).SetPrev(b) + ElementMapper{}.linkerFor(b).SetNext(e) + + if a != nil { + ElementMapper{}.linkerFor(a).SetPrev(e) + } else { + l.tail = e + } +} + +func (l *List) InsertBefore(a, e Element) { + b := ElementMapper{}.linkerFor(a).Prev() + ElementMapper{}.linkerFor(e).SetPrev(b) + ElementMapper{}.linkerFor(e).SetNext(a) + ElementMapper{}.linkerFor(a).SetPrev(e) + + if b != nil { + ElementMapper{}.linkerFor(b).SetNext(e) + } else { + l.head = e + } +} + +func (l *List) Remove(e Element) { + prev := ElementMapper{}.linkerFor(e).Prev() + next := ElementMapper{}.linkerFor(e).Next() + + if prev != nil { + ElementMapper{}.linkerFor(prev).SetNext(next) + } else { + l.tail = next + } + + if next != nil { + ElementMapper{}.linkerFor(next).SetPrev(prev) + } else { + l.tail = prev + } +} + +type Entry struct { + next Element + prev Element +} + +func (e *Entry) Next() Element { + return e.next +} + +func (e *Entry) Prev() Element { + return e.prev +} + +func (e *Entry) SetNext(elem Element) { + e.next = elem +} + +func (e *Entry) SetPrev(elem Element) { + e.prev = elem +} diff --git a/tcpip/link/fdbased/endpoint.go b/tcpip/link/fdbased/endpoint.go index ef0764d..86a9157 100644 --- a/tcpip/link/fdbased/endpoint.go +++ b/tcpip/link/fdbased/endpoint.go @@ -38,9 +38,6 @@ type endpoint struct { views []buffer.View dispatcher stack.NetworkDispatcher - // handleLocal indicates whether packets destined to itself should be - // handled by the netstack internally (true) or be forwarded to the FD - // endpoint (false). // handleLocal指示发往自身的数据包是由内部netstack处理(true)还是转发到FD端点(false)。 // Resend packets back to netstack if destined to itself // Add option to redirect packet back to netstack if it's destined to itself. diff --git a/tcpip/seqnum/seqnum.go b/tcpip/seqnum/seqnum.go new file mode 100644 index 0000000..713f5a5 --- /dev/null +++ b/tcpip/seqnum/seqnum.go @@ -0,0 +1,8 @@ +// 包 seqnum 定义了 TCP 序列号的类型和方法,以便它们适合 32 位字并在发生溢出时正常工作 +package seqnum + +// 一个序列号的值 +type Value uint32 + +// size表示一个序号窗口的大小(长度) +type Size uint32 diff --git a/tcpip/stack/nic.go b/tcpip/stack/nic.go index c1e0d48..6348305 100644 --- a/tcpip/stack/nic.go +++ b/tcpip/stack/nic.go @@ -4,6 +4,7 @@ import ( "sync" "github.com/impact-eintr/netstack/tcpip" + "github.com/impact-eintr/netstack/tcpip/ilist" ) type referencedNetworkEndpoint struct { @@ -33,7 +34,24 @@ type NIC struct { promiscuous bool primary map[tcpip.NetworkProtocolNumber]*ilist.List // 网络层端的记录 - endpoints map[tcpip.NetworkEndpointID]*referencedNetworkEndpoint + endpoints map[NetworkEndpointID]*referencedNetworkEndpoint // 子网的记录 subnets []tcpip.Subnet } + +// 根据参数新建一个NIC +func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint) *NIC { + return &NIC{ + stack: stack, + id: id, + name: name, + linkEP: ep, + demux: newTransportDemuxer(stack), + primary: make(map[tcpip.NetworkProtocolNumber]*ilist.List), + endpoints: make(map[NetworkEndpointID]*referencedNetworkEndpoint), + } +} + +type NetworkEndpointID struct { + LocalAddress tcpip.Address +} diff --git a/tcpip/stack/stack.go b/tcpip/stack/stack.go index 9b15899..941c8be 100644 --- a/tcpip/stack/stack.go +++ b/tcpip/stack/stack.go @@ -2,10 +2,12 @@ package stack import ( "sync" + "time" "github.com/impact-eintr/netstack/tcpip" "github.com/impact-eintr/netstack/tcpip/buffer" "github.com/impact-eintr/netstack/tcpip/ports" + "github.com/impact-eintr/netstack/tcpip/seqnum" ) type transportProtocolState struct { @@ -45,4 +47,42 @@ type TCPProbeFunc func(s TCPEndpointState) // TCPEndpointState 是 TCP 端点内部状态的副本 type TCPEndpointState struct { + ID TCPEndpointID // ID 是端点的 TransportEndpointID 的副本 + SegTime time.Time // SegTime 表示收到该段的绝对时间 + RcvBufSize int // RcvBufSize 是端点的接收套接字缓冲区的大小 + RcvBufUsed bool // RcvBufUsed 是端点的接收套接字缓冲区中实际保存的字节数 + RcvClosed bool // RcvClosed 如果为真,表示端点已经关闭读取 + SendTSOk bool // SendOk 用于指示何时协商了 TS 选项。当 sendOk 为真时,每个非 RST 段都应根据 RFC 7323#section-1.1 携带 TS + + // 应该在时间戳的TSEcr 字段中为端点发送的未来段发送的时间戳。当此端点接收到新段时,如果需要,将更新此字段 + RecentTS uint32 + // TSOffset 是添加到时间戳选项中 TSVal 字段值的随机偏移量 + TSOffset uint32 + + // 如果对等方在 SYN/SYN-ACK 中发送 TCPSACKPermitted 选项,则 SACKPermitted 设置为 true + SACKPermitted bool + SACK TCPSACKInfo // SACK 保存该端点的 TCP SACK 相关信息 + SndBufSize int // SndBufSize 是套接字发送缓冲区的大小 + SndBufUsed bool // SndBufUsed 是端点的发送套接字缓冲区中实际发送的字节数 + SndClosed bool // SndClosed 表示端点已关闭发送 + + sndBufInQueue seqnum.Size // SndBufInQueue 是发送队列中的字节数 + + // PacketTooBigCount 用于通知主协程收到“数据包太大”控制数据包的次数 + PacketTooBigCount int + + SndMTU int // SndMTU 是在收到的控制数据包中看到的最小 MTU + Receiver TCPReceiverState + Sender TCPSenderState +} + +type TCPReceiverState struct { +} + +type TCPSenderState struct { +} + +// 根据nic id和linkEP id来创建和注册一个网卡对象 +func (s *Stack) CreateNIC(id tcpip.NICID, linkEP tcpip.LinkEndpointID) *tcpip.Error { + return s.createNIC(id, "", linkEP, true) }