Files
netstack/tcpip/link/channel/channel.go

102 lines
2.5 KiB
Go

package channel
import (
"netstack/tcpip"
"netstack/tcpip/buffer"
"netstack/tcpip/stack"
)
type PacketInfo struct {
Header buffer.View
Payload buffer.View
Proto tcpip.NetworkProtocolNumber
}
type Endpoint struct {
dispatcher stack.NetworkDispatcher
mtu uint32
linkAddr tcpip.LinkAddress // MAC地址
C chan PacketInfo
}
//创建一个新的抽象cahnnel Endpoint 可以接受数据 也可以外发数据
func New(size int, mtu uint32, linkAddr tcpip.LinkAddress) (tcpip.LinkEndpointID, *Endpoint) {
e := &Endpoint{
C: make(chan PacketInfo, size),
mtu: mtu,
linkAddr: linkAddr,
}
return stack.RegisterLinkEndpoint(e), e
}
// Drain 流走 释放channel中的数据
func (e *Endpoint) Drain() int {
c := 0
for {
select {
case <-e.C:
c++
default:
return c
}
}
}
// Inject 注入
func (e *Endpoint) Inject(protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
e.InjectLinkAddr(protocol, "", vv)
}
// InjectLinkAddr injects an inbound packet with a remote link address.
func (e *Endpoint) InjectLinkAddr(protocol tcpip.NetworkProtocolNumber, remoteLinkAddr tcpip.LinkAddress, vv buffer.VectorisedView) {
// 这里的实现在NIC.go中 由 网卡对象进行数据分发
e.dispatcher.DeliverNetworkPacket(e, remoteLinkAddr, "" /* localLinkAddr */, protocol, vv.Clone(nil))
}
func (e *Endpoint) MTU() uint32 {
return e.mtu
}
// Capabilities返回链路层端点支持的功能集。
func (e *Endpoint) Capabilities() stack.LinkEndpointCapabilities {
return 0
}
// MaxHeaderLength 返回数据链接(和较低级别的图层组合)标头可以具有的最大大小。
// 较高级别使用此信息来保留它们正在构建的数据包前面预留空间。
func (e *Endpoint) MaxHeaderLength() uint16 {
return 0
}
// 本地链路层地址
func (e *Endpoint) LinkAddress() tcpip.LinkAddress {
return e.linkAddr
}
// channel 向外写数据
func (e *Endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload buffer.VectorisedView,
protocol tcpip.NetworkProtocolNumber) *tcpip.Error {
p := PacketInfo{
Header: hdr.View(),
Proto: protocol,
Payload: payload.ToView(),
}
select {
case e.C <- p:
default:
}
return nil
}
// Attach 将数据链路层端点附加到协议栈的网络层调度程序。
func (e *Endpoint) Attach(dispatcher stack.NetworkDispatcher) {
e.dispatcher = dispatcher
}
// 是否已经添加了网络层调度器
func (e *Endpoint) IsAttached() bool {
return e.dispatcher != nil
}