分片机制的单元测试 手动创建了两个ip报文分片 IP层从链路层获取这两个报文的时候会把它们合并成一个ip报文 这里我们不会继续分发给传输层

而是直接写回 将这个完整的ip报文整个包装 虽然这样在fdbase测试会触发错误(超过了1518),但在channel中并没有这个限制 测试通过 成功合并
This commit is contained in:
impact-eintr
2022-11-28 15:56:21 +08:00
parent cd0d9492a0
commit c7c7374bbd
6 changed files with 28 additions and 9 deletions

View File

@@ -23,7 +23,7 @@ func (p Prependable) UsedLength() int {
return len(p.buf) - p.usedIdx return len(p.buf) - p.usedIdx
} }
// 从内到外取出报文头的协议 // 从内到外暴露报文头的协议 eth|ipv4|tcp
func (p *Prependable) Prepend(size int) []byte { func (p *Prependable) Prepend(size int) []byte {
if size > p.usedIdx { if size > p.usedIdx {
return nil return nil

View File

@@ -67,11 +67,25 @@ func (f *Fragmentation) Process(id uint32, first, last uint16, more bool, vv buf
} }
f.mu.Unlock() f.mu.Unlock()
//res, done, consumed := r.process(first, last, more, vv) res, done, consumed := r.process(first, last, more, vv)
log.Printf("[%d]的分片 [%d,%d) 合并中\n", id, first, last)
r.process(first, last, more, vv)
return buffer.VectorisedView{}, false f.mu.Lock()
f.size += consumed
log.Printf("[%d]的分片 [%d,%d] 合并中\n", id, first, last)
if done {
f.release(r)
}
// Evict reassemblers if we are consuming more memory than highLimit until
// we reach lowLimit.
if f.size > f.highLimit {
tail := f.rList.Back()
for f.size > f.lowLimit && tail != nil {
f.release(tail)
tail = tail.Prev()
}
}
f.mu.Unlock()
return res, done
} }
func (f *Fragmentation) release(r *reassembler) { func (f *Fragmentation) release(r *reassembler) {

View File

@@ -162,8 +162,10 @@ func TestFragmentationBase(t *testing.T) {
ip.SetChecksum(^ip.CalculateChecksum()) ip.SetChecksum(^ip.CalculateChecksum())
copy(v, ip) copy(v, ip)
copy(v[header.IPv4MinimumSize:], payload.First()) copy(v[header.IPv4MinimumSize:], payload.First())
log.Println(ip.FragmentOffset())
inject(stackAddr1) inject(stackAddr1)
msg := <-c.linkEP.C
log.Println(msg.Header)
} }

View File

@@ -36,7 +36,7 @@ type reassembler struct {
id uint32 id uint32
size int size int
mu sync.Mutex mu sync.Mutex
holes []hole holes []hole // 每个临时ip报文的缓冲区 最大是65535
deleted int deleted int
heap fragHeap // 小根堆用来自动排序 heap fragHeap // 小根堆用来自动排序
done bool done bool
@@ -68,7 +68,7 @@ func (r *reassembler) updateHoles(first, last uint16, more bool) bool {
} }
used = true used = true
r.deleted++ r.deleted++
r.holes[i].deleted = true r.holes[i].deleted = true // 当前位置被占用
if first > r.holes[i].first { if first > r.holes[i].first {
r.holes = append(r.holes, hole{r.holes[i].first, first - 1, false}) r.holes = append(r.holes, hole{r.holes[i].first, first - 1, false})
} }

View File

@@ -110,7 +110,8 @@ func (e *endpoint) WritePacket(r *stack.Route, hdr buffer.Prependable, payload b
if protocol == header.ICMPv4ProtocolNumber { if protocol == header.ICMPv4ProtocolNumber {
log.Printf("IP 写回ICMP报文 长度: %d\n", hdr.UsedLength()+payload.Size()) log.Printf("IP 写回ICMP报文 长度: %d\n", hdr.UsedLength()+payload.Size())
} else { } else {
log.Printf("send ipv4 packet %d bytes, proto: 0x%x", hdr.UsedLength()+payload.Size(), protocol) //log.Printf("send ipv4 packet %d bytes, proto: 0x%x", hdr.UsedLength()+payload.Size(), protocol)
log.Println(header.IPv4(append(ip, payload.ToView()...)))
} }
return e.linkEP.WritePacket(r, hdr, payload, ProtocolNumber) return e.linkEP.WritePacket(r, hdr, payload, ProtocolNumber)
} }

View File

@@ -388,6 +388,8 @@ func (n *NIC) DeliverNetworkPacket(linkEP LinkEndpoint, remoteLinkAddr, localLin
// 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("准备分发传输层数据报") log.Println("准备分发传输层数据报")
hdr := buffer.NewPrependable(header.EthernetMinimumSize + header.IPv4MinimumSize)
r.ref.ep.WritePacket(r, hdr, vv, protocol, 255)
} }