NIC 对象绑定IP还未实现完成 明天继续

This commit is contained in:
impact-eintr
2022-11-24 21:32:04 +08:00
parent e51d8ea721
commit 4589d971fd
5 changed files with 165 additions and 10 deletions

View File

@@ -1,11 +1,32 @@
package stack package stack
import ( import (
"log"
"netstack/ilist" "netstack/ilist"
"netstack/tcpip" "netstack/tcpip"
"netstack/tcpip/buffer"
"sync" "sync"
) )
// PrimaryEndpointBehavior 是端点首要行为的枚举
type PrimaryEndpointBehavior int
const (
// CanBePrimaryEndpoint indicates the endpoint can be used as a primary
// endpoint for new connections with no local address. This is the
// default when calling NIC.AddAddress.
CanBePrimaryEndpoint PrimaryEndpointBehavior = iota
// FirstPrimaryEndpoint indicates the endpoint should be the first
// primary endpoint considered. If there are multiple endpoints with
// this behavior, the most recently-added one will be first.
FirstPrimaryEndpoint
// NeverPrimaryEndpoint indicates the endpoint should never be a
// primary endpoint.
NeverPrimaryEndpoint
)
// 代表一个网卡对象 当我们创建好tap网卡对象后 我们使用NIC来代表它在我们自己的协议栈中的网卡对象 // 代表一个网卡对象 当我们创建好tap网卡对象后 我们使用NIC来代表它在我们自己的协议栈中的网卡对象
type NIC struct { type NIC struct {
stack *Stack stack *Stack
@@ -24,7 +45,57 @@ type NIC struct {
promiscuous bool // 混杂模式 promiscuous bool // 混杂模式
primary map[tcpip.NetworkProtocolNumber]*ilist.List primary map[tcpip.NetworkProtocolNumber]*ilist.List
// 网络层端的记录 // 网络层端的记录
endpoints map[NetworkEndpoingID]*referencedNetworkEndpoint endpoints map[NetworkEndpointID]*referencedNetworkEndpoint
// 子网的记录 // 子网的记录
subnets []tcpip.Subnet subnets []tcpip.Subnet
} }
// 创建新的网卡对象
func newNIC(stack *Stack, id tcpip.NICID, name string, ep LinkEndpoint) *NIC {
return &NIC{
stack: stack,
id: id,
name: name,
linkEP: ep,
demux: nil, // TODO 需要处理
primary: make(map[tcpip.NetworkProtocolNumber]*ilist.List),
endpoints: make(map[NetworkEndpointID]*referencedNetworkEndpoint),
}
}
func (n *NIC) attachLinkEndpoint() {
n.linkEP.Attach(n)
}
// 在NIC上添加addr地址注册和初始化网络层协议
// 相当于给网卡添加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 {
log.Println("添加失败")
return nil, tcpip.ErrUnknownProtocol
}
log.Println(netProto.Number(), "添加ip", addr.String())
// TODO 接着这里实现 22/11/24 21:29
return nil, nil
}
func (n *NIC) AddAddress(protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) *tcpip.Error {
return n.AddAddressWithOptions(protocol, addr, CanBePrimaryEndpoint)
}
func (n *NIC) AddAddressWithOptions(protocol tcpip.NetworkProtocolNumber,
addr tcpip.Address, peb PrimaryEndpointBehavior) *tcpip.Error {
n.mu.Lock()
_, err := n.addAddressLocked(protocol, addr, peb, false)
n.mu.Unlock()
return err
}
func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, dstLinkAddr, srcLinkAddr tcpip.LinkAddress,
protocol tcpip.NetworkProtocolNumber, vv buffer.VectorisedView) {
// TODO 需要完成逻辑
log.Println(vv.ToView())
}

View File

@@ -1,6 +1,7 @@
package stack package stack
import ( import (
"log"
"netstack/ilist" "netstack/ilist"
"netstack/sleep" "netstack/sleep"
"netstack/tcpip" "netstack/tcpip"
@@ -89,9 +90,16 @@ type NetworkDispatcher interface {
type LinkEndpointCapabilities uint type LinkEndpointCapabilities uint
// type TransportProtocolFactory func() TransportProtocol TODO
type NetworkProtocolFactory func() NetworkProtocol
var ( var (
// 以下两个map需要在init函数中注册
// 传输层协议的注册存储结构 TODO // 传输层协议的注册存储结构 TODO
// 网络层协议的注册存储结构 TODO //transportProtocols = make(map[string]TransportProtocolFactory)
// 网络层协议的注册存储结构
networkProtocols = make(map[string]NetworkProtocolFactory)
linkEPMu sync.RWMutex linkEPMu sync.RWMutex
nextLinkEndpointID tcpip.LinkEndpointID = 1 nextLinkEndpointID tcpip.LinkEndpointID = 1
@@ -100,7 +108,8 @@ var (
// ==============================网络层相关============================== // ==============================网络层相关==============================
type NetworkProtocol interface { type NetworkProtocol interface {
// TODO 需要添加 Number() tcpip.NetworkProtocolNumber
// todo 需要添加
} }
// NetworkEndpoint是需要由网络层协议例如ipv4ipv6的端点实现的接口 // NetworkEndpoint是需要由网络层协议例如ipv4ipv6的端点实现的接口
@@ -108,7 +117,7 @@ type NetworkEndpoint interface {
// TODO 需要添加 // TODO 需要添加
} }
type NetworkEndpoingID struct { type NetworkEndpointID struct {
LocalAddress tcpip.Address LocalAddress tcpip.Address
} }
@@ -147,6 +156,12 @@ type referencedNetworkEndpoint struct {
holdsInsertRef bool holdsInsertRef bool
} }
// 注册一个新的网络协议工厂
func RegisterNetworkProtocolFactory(name string, p NetworkProtocolFactory) {
networkProtocols[name] = p
log.Println(networkProtocols)
}
// 注册一个链路层设备 // 注册一个链路层设备
func RegisterLinkEndpoint(linkEP LinkEndpoint) tcpip.LinkEndpointID { func RegisterLinkEndpoint(linkEP LinkEndpoint) tcpip.LinkEndpointID {
linkEPMu.Lock() linkEPMu.Lock()

View File

@@ -1,6 +1,7 @@
package stack package stack
import ( import (
"log"
"netstack/tcpip" "netstack/tcpip"
"netstack/tcpip/ports" "netstack/tcpip/ports"
"sync" "sync"
@@ -48,6 +49,31 @@ type Stack struct {
clock tcpip.Clock clock tcpip.Clock
} }
func New(network []string) *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),
}
// 添加指定的网络端协议 必须已经在init中注册过
for _, name := range network {
// 先检查这个网络协议是否注册过工厂方法
netProtoFactory, ok := networkProtocols[name]
if !ok {
log.Println(name)
continue // 没有就略过
}
netProto := netProtoFactory() // 制造一个该型号协议的示实例
s.networkProtocols[netProto.Number()] = netProto // 注册该型号的网络协议
}
// 添加指定的传输层协议 必已经在init中注册过
// TODO
return s
}
func (s *Stack) CreateNIC(id tcpip.NICID, linkEP tcpip.LinkEndpointID) *tcpip.Error { func (s *Stack) CreateNIC(id tcpip.NICID, linkEP tcpip.LinkEndpointID) *tcpip.Error {
return s.createNIC(id, "", linkEP, true) return s.createNIC(id, "", linkEP, true)
} }
@@ -66,10 +92,30 @@ func (s *Stack) createNIC(id tcpip.NICID, name string, linkEP tcpip.LinkEndpoint
if _, ok := s.nics[id]; ok { if _, ok := s.nics[id]; ok {
return tcpip.ErrDuplicateNICID return tcpip.ErrDuplicateNICID
} }
n := newIC(s, id, name, ep) n := newNIC(s, id, name, ep)
s.nics[id] = n s.nics[id] = n
if enable { if enable {
n.attachLinkEndpoint() n.attachLinkEndpoint()
} }
return nil
}
// 给网卡添加ip地址
func (s *Stack) AddAddress(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber, addr tcpip.Address) *tcpip.Error {
return s.AddAddressWithOptions(id, protocol, addr, CanBePrimaryEndpoint)
}
func (s *Stack) AddAddressWithOptions(id tcpip.NICID, protocol tcpip.NetworkProtocolNumber,
addr tcpip.Address, peb PrimaryEndpointBehavior) *tcpip.Error {
s.mu.RLock()
defer s.mu.RUnlock()
nic := s.nics[id]
if nic == nil {
return tcpip.ErrUnknownNICID
}
return nic.AddAddressWithOptions(protocol, addr, peb)
} }

View File

@@ -1,6 +1,9 @@
package stack_test package stack_test
import ( import (
"log"
"netstack/tcpip"
"netstack/tcpip/buffer"
"netstack/tcpip/link/channel" "netstack/tcpip/link/channel"
"netstack/tcpip/stack" "netstack/tcpip/stack"
"testing" "testing"
@@ -10,12 +13,33 @@ const (
defaultMTU = 65536 defaultMTU = 65536
) )
type fakeNetworkProtocol struct {
}
func (f *fakeNetworkProtocol) Number() tcpip.NetworkProtocolNumber {
return 114514
}
func init() {
stack.RegisterNetworkProtocolFactory("fakeNet", func() stack.NetworkProtocol {
return &fakeNetworkProtocol{}
})
}
func TestStackBase(t *testing.T) { func TestStackBase(t *testing.T) {
myStack := &stack.Stack{} myStack := stack.New([]string{"fakeNet"})
id, _ := channel.New(10, defaultMTU, "") id, ep := channel.New(10, defaultMTU, "") // 这是一个物理设备
log.Println(id)
if err := myStack.CreateNIC(1, id); err != nil { if err := myStack.CreateNIC(1, id); err != nil { // 将上面的物理设备抽象成我们的网卡对象
panic(err) panic(err)
} }
myStack.AddAddress(1, 114514, "\x01") // 给网卡对象绑定一个IP地址 可以绑定多个
buf := buffer.NewView(30)
for i := range buf {
buf[i] = 1
}
ep.Inject(114514, buf.ToVectoriseView())
} }

View File

@@ -108,12 +108,11 @@ type Stats struct {
} }
func (a Address) String() string { func (a Address) String() string {
fmt.Println(string(a), len(a))
switch len(a) { switch len(a) {
case 4: case 4:
fmt.Println(string(a))
return fmt.Sprintf("%d.%d.%d.%d", int(a[0]), int(a[1]), int(a[2]), int(a[3])) return fmt.Sprintf("%d.%d.%d.%d", int(a[0]), int(a[1]), int(a[2]), int(a[3]))
case 16: case 16:
fmt.Println(string(a))
// Find the longest subsequence of hexadecimal zeros. // Find the longest subsequence of hexadecimal zeros.
start, end := -1, -1 start, end := -1, -1
for i := 0; i < len(a); i += 2 { for i := 0; i < len(a); i += 2 {