ip报文的分片机制 解析中 学得胃疼。。。

This commit is contained in:
impact-eintr
2022-11-27 22:44:41 +08:00
parent 5e317b273a
commit 553a16f655
9 changed files with 681 additions and 5 deletions

View File

@@ -167,4 +167,6 @@ CIDR无类域间路由打破了原本的ABC类地址的规划限定使用
| 15 | 0 | Information request (obsolete)——信息请求(作废不用)   | | 15 | 0 | Information request (obsolete)——信息请求(作废不用)   |
| 16 | 0 | Information reply (obsolete)——信息应答(作废不用)   | | 16 | 0 | Information reply (obsolete)——信息应答(作废不用)   |
| 17 | 0 | Address mask request——地址掩码请求   | | 17 | 0 | Address mask request——地址掩码请求   |
| 18 | 0 | Address mask | reply——地址掩码应答 | | 18 | 0 | Address mask | reply——地址掩码应答 |
IP 层最重要的目的是让两个主机之间通信无论他们相隔多远。IP 协议理论上允许的最大 IP 数据报为 65535 字节16 位来表示包总长)。但是因为协议栈网络层下面的数据链路层一般允许的帧长远远小于这个值,例如以太网的 MTU 通常在 1500 字节左右。所以较大的 IP 数据包会被分片传递给数据链路层发送,分片的 IP 数据报可能会以不同的路径传输到接收主机,接收主机通过一系列的重组,将其还原为一个完整的 IP 数据报再提交给上层协议处理。IP 分片会带来一定的问题,分片和重组会消耗发送方、接收方一定的 CPU 等资源,如果存在大量的分片报文的话,可能会造成较为严重的资源消耗;分片丢包导致的重传问题;分片攻击。

View File

@@ -0,0 +1,77 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package fragmentation
import (
"container/heap"
"fmt"
"netstack/tcpip/buffer"
)
type fragment struct {
offset uint16
vv buffer.VectorisedView
}
type fragHeap []fragment
func (h *fragHeap) Len() int {
return len(*h)
}
func (h *fragHeap) Less(i, j int) bool {
return (*h)[i].offset < (*h)[j].offset
}
func (h *fragHeap) Swap(i, j int) {
(*h)[i], (*h)[j] = (*h)[j], (*h)[i]
}
func (h *fragHeap) Push(x interface{}) {
*h = append(*h, x.(fragment))
}
func (h *fragHeap) Pop() interface{} {
old := *h
n := len(old)
x := old[n-1]
*h = old[:n-1]
return x
}
// reassamble empties the heap and returns a VectorisedView
// containing a reassambled version of the fragments inside the heap.
func (h *fragHeap) reassemble() (buffer.VectorisedView, error) {
curr := heap.Pop(h).(fragment)
views := curr.vv.Views()
size := curr.vv.Size()
if curr.offset != 0 {
return buffer.VectorisedView{}, fmt.Errorf("offset of the first packet is != 0 (%d)", curr.offset)
}
for h.Len() > 0 {
curr := heap.Pop(h).(fragment)
if int(curr.offset) < size {
curr.vv.TrimFront(size - int(curr.offset))
} else if int(curr.offset) > size {
return buffer.VectorisedView{}, fmt.Errorf("packet has a hole, expected offset %d, got %d", size, curr.offset)
}
size += curr.vv.Size()
views = append(views, curr.vv.Views()...)
}
return buffer.NewVectorisedView(size, views), nil
}

View File

@@ -0,0 +1,68 @@
package fragmentation
import (
"log"
"netstack/tcpip/buffer"
"sync"
"time"
)
// DefaultReassembleTimeout is based on the linux stack: net.ipv4.ipfrag_time.
const DefaultReassembleTimeout = 30 * time.Second
// HighFragThreshold is the threshold at which we start trimming old
// fragmented packets. Linux uses a default value of 4 MB. See
// net.ipv4.ipfrag_high_thresh for more information.
const HighFragThreshold = 4 << 20 // 4MB
// LowFragThreshold is the threshold we reach to when we start dropping
// older fragmented packets. It's important that we keep enough room for newer
// packets to be re-assembled. Hence, this needs to be lower than
// HighFragThreshold enough. Linux uses a default value of 3 MB. See
// net.ipv4.ipfrag_low_thresh for more information.
const LowFragThreshold = 3 << 20 // 3MB
type Fragmentation struct {
mu sync.Mutex
highLimit int
lowLimit int
reassemblers map[uint32]*reassembler
rList reassemblerList
size int
timeout time.Duration
}
func NewFragmentation(highMemoryLimit, lowMemoryLimit int, reassemblingTimeout time.Duration) *Fragmentation {
if lowMemoryLimit >= highMemoryLimit {
lowMemoryLimit = highMemoryLimit
}
if lowMemoryLimit < 0 {
lowMemoryLimit = 0
}
return &Fragmentation{
reassemblers: make(map[uint32]*reassembler),
highLimit: highMemoryLimit,
lowLimit: lowMemoryLimit,
timeout: reassemblingTimeout,
}
}
func (f *Fragmentation) Process(id uint32, first, last uint16, more bool, vv buffer.VectorisedView) (buffer.VectorisedView, bool) {
log.Println("分片机制工作中", id, first, last, vv.First())
f.mu.Lock()
r, ok := f.reassemblers[id]
if ok && r.tooOld(f.timeout) {
// This is very likely to be an id-collision or someone performing a slow-rate attack.
//f.release(r)
ok = false
}
if !ok {
r = newReassembler(id)
f.reassemblers[id] = r
f.rList.PushFront(r)
}
f.mu.Unlock()
return buffer.VectorisedView{}, false
}

View File

@@ -0,0 +1,139 @@
package fragmentation_test
import (
"netstack/tcpip"
"netstack/tcpip/buffer"
"netstack/tcpip/header"
"netstack/tcpip/link/channel"
"netstack/tcpip/network/arp"
"netstack/tcpip/network/ipv4"
"netstack/tcpip/stack"
"testing"
"time"
)
const (
stackLinkAddr = tcpip.LinkAddress("\x0a\x0a\x0b\x0b\x0c\x0c") // 0a:0a:0b:0b:0c:0c
stackAddr1 = tcpip.Address("\x0a\x00\x00\x01") // 10.0.0.1
stackAddr2 = tcpip.Address("\x0a\x00\x00\x02") // 10.0.0.2
stackAddrBad = tcpip.Address("\x0a\x00\x00\x03") // 10.0.0.3
)
type testContext struct {
t *testing.T
linkEP *channel.Endpoint
s *stack.Stack
}
func newTestContext(t *testing.T) *testContext {
s := stack.New([]string{ipv4.ProtocolName, arp.ProtocolName}, nil, stack.Options{})
const defaultMTU = 65536
id, linkEP := channel.New(256, defaultMTU, stackLinkAddr)
if err := s.CreateNIC(1, id); err != nil {
t.Fatalf("CreateNIC failed: %v", err)
}
if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr1); err != nil {
t.Fatalf("AddAddress for ipv4 failed: %v", err)
}
if err := s.AddAddress(1, ipv4.ProtocolNumber, stackAddr2); err != nil {
t.Fatalf("AddAddress for ipv4 failed: %v", err)
}
if err := s.AddAddress(1, arp.ProtocolNumber, arp.ProtocolAddress); err != nil {
t.Fatalf("AddAddress for arp failed: %v", err)
}
s.SetRouteTable([]tcpip.Route{{
Destination: "\x00\x00\x00\x00",
Mask: "\x00\x00\x00\x00",
Gateway: "",
NIC: 1,
}})
return &testContext{
t: t,
s: s,
linkEP: linkEP,
}
}
func (c *testContext) cleanup() {
close(c.linkEP.C)
}
func TestFragmentationBase(t *testing.T) {
c := newTestContext(t)
defer c.cleanup()
const senderMAC = "\x01\x02\x03\x04\x05\x06"
const senderIPv4 = "\x0a\x00\x00\x02"
v := make(buffer.View, header.ARPSize)
h := header.ARP(v)
h.SetIPv4OverEthernet()
h.SetOp(header.ARPRequest) // 一个ARP请求
copy(h.HardwareAddressSender(), senderMAC) // Local MAC
copy(h.ProtocolAddressSender(), senderIPv4) // Local IP
inject := func(addr tcpip.Address) {
copy(h.ProtocolAddressTarget(), addr)
c.linkEP.Inject(arp.ProtocolNumber, v.ToVectorisedView()) // 往链路层注入一个arp报文 链路层将会自动分发它
}
inject(stackAddr1) // target IP 10.0.0.1
select {
case pkt := <-c.linkEP.C:
if pkt.Proto != arp.ProtocolNumber {
t.Fatalf("stackAddr1: expected ARP response, got network protocol number %v", pkt.Proto)
}
rep := header.ARP(pkt.Header)
if !rep.IsValid() {
t.Fatalf("stackAddr1: invalid ARP response len(pkt.Header)=%d", len(pkt.Header))
}
if tcpip.Address(rep.ProtocolAddressSender()) != stackAddr1 {
t.Errorf("stackAddr1: expected sender to be set")
}
if got := tcpip.LinkAddress(rep.HardwareAddressSender()); got != stackLinkAddr {
t.Errorf("stackAddr1: expected sender to be stackLinkAddr, got %q", got)
}
case <-time.After(100 * time.Millisecond):
t.Fatalf("Case #1 Time Out\n")
}
// 一个纯粹的IP报文
v = make(buffer.View, header.IPv4MinimumSize+256)
hdr := buffer.NewPrependable(header.IPv4MinimumSize)
ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize))
buf := make(buffer.View, 256)
for i := range buf {
buf[i] = 1
}
payload := buffer.NewVectorisedView(256, buf.ToVectorisedView().Views())
length := uint16(hdr.UsedLength() + payload.Size())
// ip首部编码
ip.Encode(&header.IPv4Fields{
IHL: header.IPv4MinimumSize,
TotalLength: length,
ID: uint16(2),
Flags: 0x1,
FragmentOffset: 1024,
TTL: 255,
Protocol: uint8(0x6), // tcp 伪装报文
SrcAddr: senderIPv4,
DstAddr: stackAddr1,
})
//ip.SetFlagsFragmentOffset()
// 计算校验和和设置校验和
ip.SetChecksum(^ip.CalculateChecksum())
copy(v, ip)
copy(v[header.IPv4MinimumSize:], payload.First())
inject = func(addr tcpip.Address) {
copy(h.ProtocolAddressTarget(), addr)
c.linkEP.Inject(ipv4.ProtocolNumber, v.ToVectorisedView()) // 往链路层注入一个arp报文 链路层将会自动分发它
}
inject(stackAddr1)
}

View File

@@ -0,0 +1,118 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package fragmentation
import (
"container/heap"
"fmt"
"math"
"sync"
"time"
"netstack/tcpip/buffer"
)
type hole struct {
first uint16
last uint16
deleted bool
}
type reassembler struct {
reassemblerEntry
id uint32
size int
mu sync.Mutex
holes []hole
deleted int
heap fragHeap
done bool
creationTime time.Time
}
func newReassembler(id uint32) *reassembler {
r := &reassembler{
id: id,
holes: make([]hole, 0, 16),
deleted: 0,
heap: make(fragHeap, 0, 8),
creationTime: time.Now(),
}
r.holes = append(r.holes, hole{
first: 0,
last: math.MaxUint16,
deleted: false})
return r
}
// updateHoles updates the list of holes for an incoming fragment and
// returns true iff the fragment filled at least part of an existing hole.
func (r *reassembler) updateHoles(first, last uint16, more bool) bool {
used := false
for i := range r.holes {
if r.holes[i].deleted || first > r.holes[i].last || last < r.holes[i].first {
continue
}
used = true
r.deleted++
r.holes[i].deleted = true
if first > r.holes[i].first {
r.holes = append(r.holes, hole{r.holes[i].first, first - 1, false})
}
if last < r.holes[i].last && more {
r.holes = append(r.holes, hole{last + 1, r.holes[i].last, false})
}
}
return used
}
func (r *reassembler) process(first, last uint16, more bool, vv buffer.VectorisedView) (buffer.VectorisedView, bool, int) {
r.mu.Lock()
defer r.mu.Unlock()
consumed := 0
if r.done {
// A concurrent goroutine might have already reassembled
// the packet and emptied the heap while this goroutine
// was waiting on the mutex. We don't have to do anything in this case.
return buffer.VectorisedView{}, false, consumed
}
if r.updateHoles(first, last, more) {
// We store the incoming packet only if it filled some holes.
heap.Push(&r.heap, fragment{offset: first, vv: vv.Clone(nil)})
consumed = vv.Size()
r.size += consumed
}
// Check if all the holes have been deleted and we are ready to reassamble.
if r.deleted < len(r.holes) {
return buffer.VectorisedView{}, false, consumed
}
res, err := r.heap.reassemble()
if err != nil {
panic(fmt.Sprintf("reassemble failed with: %v. There is probably a bug in the code handling the holes.", err))
}
return res, true, consumed
}
func (r *reassembler) tooOld(timeout time.Duration) bool {
return time.Now().Sub(r.creationTime) > timeout
}
func (r *reassembler) checkDoneOrMark() bool {
r.mu.Lock()
prev := r.done
r.done = true
r.mu.Unlock()
return prev
}

View File

@@ -0,0 +1,173 @@
package fragmentation
// ElementMapper provides an identity mapping by default.
//
// This can be replaced to provide a struct that maps elements to linker
// objects, if they are not the same. An ElementMapper is not typically
// required if: Linker is left as is, Element is left as is, or Linker and
// Element are the same type.
type reassemblerElementMapper struct{}
// linkerFor maps an Element to a Linker.
//
// This default implementation should be inlined.
//
//go:nosplit
func (reassemblerElementMapper) linkerFor(elem *reassembler) *reassembler { return elem }
// List is an intrusive list. Entries can be added to or removed from the list
// in O(1) time and with no additional memory allocations.
//
// The zero value for List is an empty list ready to use.
//
// To iterate over a list (where l is a List):
// for e := l.Front(); e != nil; e = e.Next() {
// // do something with e.
// }
//
// +stateify savable
type reassemblerList struct {
head *reassembler
tail *reassembler
}
// Reset resets list l to the empty state.
func (l *reassemblerList) Reset() {
l.head = nil
l.tail = nil
}
// Empty returns true iff the list is empty.
func (l *reassemblerList) Empty() bool {
return l.head == nil
}
// Front returns the first element of list l or nil.
func (l *reassemblerList) Front() *reassembler {
return l.head
}
// Back returns the last element of list l or nil.
func (l *reassemblerList) Back() *reassembler {
return l.tail
}
// PushFront inserts the element e at the front of list l.
func (l *reassemblerList) PushFront(e *reassembler) {
reassemblerElementMapper{}.linkerFor(e).SetNext(l.head)
reassemblerElementMapper{}.linkerFor(e).SetPrev(nil)
if l.head != nil {
reassemblerElementMapper{}.linkerFor(l.head).SetPrev(e)
} else {
l.tail = e
}
l.head = e
}
// PushBack inserts the element e at the back of list l.
func (l *reassemblerList) PushBack(e *reassembler) {
reassemblerElementMapper{}.linkerFor(e).SetNext(nil)
reassemblerElementMapper{}.linkerFor(e).SetPrev(l.tail)
if l.tail != nil {
reassemblerElementMapper{}.linkerFor(l.tail).SetNext(e)
} else {
l.head = e
}
l.tail = e
}
// PushBackList inserts list m at the end of list l, emptying m.
func (l *reassemblerList) PushBackList(m *reassemblerList) {
if l.head == nil {
l.head = m.head
l.tail = m.tail
} else if m.head != nil {
reassemblerElementMapper{}.linkerFor(l.tail).SetNext(m.head)
reassemblerElementMapper{}.linkerFor(m.head).SetPrev(l.tail)
l.tail = m.tail
}
m.head = nil
m.tail = nil
}
// InsertAfter inserts e after b.
func (l *reassemblerList) InsertAfter(b, e *reassembler) {
a := reassemblerElementMapper{}.linkerFor(b).Next()
reassemblerElementMapper{}.linkerFor(e).SetNext(a)
reassemblerElementMapper{}.linkerFor(e).SetPrev(b)
reassemblerElementMapper{}.linkerFor(b).SetNext(e)
if a != nil {
reassemblerElementMapper{}.linkerFor(a).SetPrev(e)
} else {
l.tail = e
}
}
// InsertBefore inserts e before a.
func (l *reassemblerList) InsertBefore(a, e *reassembler) {
b := reassemblerElementMapper{}.linkerFor(a).Prev()
reassemblerElementMapper{}.linkerFor(e).SetNext(a)
reassemblerElementMapper{}.linkerFor(e).SetPrev(b)
reassemblerElementMapper{}.linkerFor(a).SetPrev(e)
if b != nil {
reassemblerElementMapper{}.linkerFor(b).SetNext(e)
} else {
l.head = e
}
}
// Remove removes e from l.
func (l *reassemblerList) Remove(e *reassembler) {
prev := reassemblerElementMapper{}.linkerFor(e).Prev()
next := reassemblerElementMapper{}.linkerFor(e).Next()
if prev != nil {
reassemblerElementMapper{}.linkerFor(prev).SetNext(next)
} else {
l.head = next
}
if next != nil {
reassemblerElementMapper{}.linkerFor(next).SetPrev(prev)
} else {
l.tail = prev
}
}
// Entry is a default implementation of Linker. Users can add anonymous fields
// of this type to their structs to make them automatically implement the
// methods needed by List.
//
// +stateify savable
type reassemblerEntry struct {
next *reassembler
prev *reassembler
}
// Next returns the entry that follows e in the list.
func (e *reassemblerEntry) Next() *reassembler {
return e.next
}
// Prev returns the entry that precedes e in the list.
func (e *reassemblerEntry) Prev() *reassembler {
return e.prev
}
// SetNext assigns 'entry' as the entry that follows e in the list.
func (e *reassemblerEntry) SetNext(elem *reassembler) {
e.next = elem
}
// SetPrev assigns 'entry' as the entry that precedes e in the list.
func (e *reassemblerEntry) SetPrev(elem *reassembler) {
e.prev = elem
}

View File

@@ -0,0 +1,70 @@
package hash
import (
"crypto/rand"
"encoding/binary"
"netstack/tcpip/header"
)
var hashIV = RandN32(1)[0]
// RandN32 生成 n 个加密随机 32 位数字的切片
func RandN32(n int) []uint32 {
b := make([]byte, 4*n)
if _, err := rand.Read(b); err != nil {
panic("unable to get random numbers: " + err.Error())
}
r := make([]uint32, n)
for i := range r {
r[i] = binary.LittleEndian.Uint32(b[4*i : (4*i + 4)])
}
return r
}
func Hash3Words(a, b, c, initval uint32) uint32 {
const iv = 0xdeadbeef + (3 << 2)
initval += iv
a += initval
b += initval
c += initval
c ^= b
c -= rol32(b, 14)
a ^= c
a -= rol32(c, 11)
b ^= a
b -= rol32(a, 25)
c ^= b
c -= rol32(b, 16)
a ^= c
a -= rol32(c, 4)
b ^= a
b -= rol32(a, 14)
c ^= b
c -= rol32(b, 24)
return c
}
// 根据id源ip目的ip和协议类型得到hash值
func IPv4FragmentHash(h header.IPv4) uint32 {
x := uint32(h.ID())<<16 | uint32(h.Protocol())
t := h.SourceAddress()
y := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
t = h.DestinationAddress()
z := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
return Hash3Words(x, y, z, hashIV)
}
func IPv6FragmentHash(h header.IPv6, f header.IPv6Fragment) uint32 {
t := h.SourceAddress()
y := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
t = h.DestinationAddress()
z := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
return Hash3Words(f.ID(), y, z, hashIV)
}
func rol32(v, shift uint32) uint32 {
return (v << shift) | (v >> ((-shift) & 31))
}

View File

@@ -5,7 +5,10 @@ import (
"netstack/tcpip" "netstack/tcpip"
"netstack/tcpip/buffer" "netstack/tcpip/buffer"
"netstack/tcpip/header" "netstack/tcpip/header"
"netstack/tcpip/network/fragmentation"
"netstack/tcpip/network/hash"
"netstack/tcpip/stack" "netstack/tcpip/stack"
"sync/atomic"
) )
const ( const (
@@ -36,7 +39,7 @@ type endpoint struct {
// ping请求报文接收队列 // ping请求报文接收队列
echoRequests chan echoRequest echoRequests chan echoRequest
// ip报文分片处理器 // ip报文分片处理器
//fragmentation *fragmentation.Fragmentation fragmentation *fragmentation.Fragmentation
} }
// DefaultTTL is the default time-to-live value for this endpoint. // DefaultTTL is the default time-to-live value for this endpoint.
@@ -87,7 +90,7 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload b
if length > header.IPv4MaximumHeaderSize+8 { if length > header.IPv4MaximumHeaderSize+8 {
// Packets of 68 bytes or less are required by RFC 791 to not be // Packets of 68 bytes or less are required by RFC 791 to not be
// fragmented, so we only assign ids to larger packets. // fragmented, so we only assign ids to larger packets.
//id = atomic.AddUint32(&ids[hashRoute(r, protocol)%buckets], 1) id = atomic.AddUint32(&ids[hashRoute(r, protocol)%buckets], 1)
} }
// ip首部编码 // ip首部编码
ip.Encode(&header.IPv4Fields{ ip.Encode(&header.IPv4Fields{
@@ -118,6 +121,7 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload b
func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) { func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
// 得到ip报文 // 得到ip报文
h := header.IPv4(vv.First()) h := header.IPv4(vv.First())
log.Println(h)
// 检查报文是否有效 // 检查报文是否有效
if !h.IsValid(vv.Size()) { if !h.IsValid(vv.Size()) {
return return
@@ -136,9 +140,8 @@ func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
// The packet is a fragment, let's try to reassemble it. // The packet is a fragment, let's try to reassemble it.
last := h.FragmentOffset() + uint16(vv.Size()) - 1 last := h.FragmentOffset() + uint16(vv.Size()) - 1
var ready bool var ready bool
log.Println(last)
// ip分片重组 // ip分片重组
//vv, ready = e.fragmentation.Process(hash.IPv4FragmentHash(h), h.FragmentOffset(), last, more, vv) vv, ready = e.fragmentation.Process(hash.IPv4FragmentHash(h), h.FragmentOffset(), last, more, vv)
if !ready { if !ready {
return return
} }
@@ -159,6 +162,7 @@ func (e *endpoint) HandlePacket(r *stack.Route, vv buffer.VectorisedView) {
// Close cleans up resources associated with the endpoint. // Close cleans up resources associated with the endpoint.
func (e *endpoint) Close() { func (e *endpoint) Close() {
close(e.echoRequests)
} }
// 实现NetworkProtocol接口 // 实现NetworkProtocol接口
@@ -174,6 +178,8 @@ func (p *protocol) NewEndpoint(nicid tcpip.NICID, addr tcpip.Address, linkAddrCa
linkEP: linkEP, linkEP: linkEP,
dispatcher: dispatcher, dispatcher: dispatcher,
echoRequests: make(chan echoRequest, 10), echoRequests: make(chan echoRequest, 10),
fragmentation: fragmentation.NewFragmentation(fragmentation.HighFragThreshold,
fragmentation.LowFragThreshold, fragmentation.DefaultReassembleTimeout),
} }
go e.echoReplier() go e.echoReplier()
@@ -224,7 +230,29 @@ func calculateMTU(mtu uint32) uint32 {
return mtu - header.IPv4MinimumSize return mtu - header.IPv4MinimumSize
} }
// 用 源地址 目标地址 和 传输层协议号 进行一个哈希
func hashRoute(r *stack.Route, protocol tcpip.TransportProtocolNumber) uint32 {
t := r.LocalAddress
a := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
t = r.RemoteAddress
b := uint32(t[0]) | uint32(t[1])<<8 | uint32(t[2])<<16 | uint32(t[3])<<24
return hash.Hash3Words(a, b, uint32(protocol), hashIV)
}
var (
ids []uint32
hashIV uint32
)
func init() { func init() {
ids = make([]uint32, buckets)
r := hash.RandN32(1 + buckets)
for i := range ids {
ids[i] = r[i] // 初始化ids
}
hashIV = r[buckets]
stack.RegisterNetworkProtocolFactory(ProtocolName, func() stack.NetworkProtocol { stack.RegisterNetworkProtocolFactory(ProtocolName, func() stack.NetworkProtocol {
return &protocol{} return &protocol{}
}) })

View File

@@ -382,6 +382,7 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr, localLin
// DeliverTransportPacket delivers packets to the appropriate // DeliverTransportPacket delivers packets to the appropriate
// transport protocol endpoint. // transport protocol endpoint.
func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolNumber, vv buffer.VectorisedView) { func (n *NIC) DeliverTransportPacket(r *Route, protocol tcpip.TransportProtocolNumber, vv buffer.VectorisedView) {
log.Println("准备分发传输层数据报")
} }