code: func (e *endpoint) WritePacket(r *stack.Route, gso *stack.GSO, hdr buffer.Prependable, payload buffer.VectorisedView, protocol tcpip.TransportProtocolNumber, ttl uint8, loop stack.PacketLooping) *tcpip.Error {
  	ip := header.IPv4(hdr.Prepend(header.IPv4MinimumSize))
  	length := uint16(hdr.UsedLength() + payload.Size())
  	id := uint32(0)
  	if length > header.IPv4MaximumHeaderSize+8 {
  		// Packets of 68 bytes or less are required by RFC 791 to not be
  		// fragmented, so we only assign ids to larger packets.
  		id = atomic.AddUint32(&ids[hashRoute(r, protocol)%buckets], 1)
  	}
  	ip.Encode(&header.IPv4Fields{
  		IHL:         header.IPv4MinimumSize,
  		TotalLength: length,
  		ID:          uint16(id),
  		TTL:         ttl,
  		Protocol:    uint8(protocol),
  		SrcAddr:     r.LocalAddress,
  		DstAddr:     r.RemoteAddress,
  	})
  	ip.SetChecksum(^ip.CalculateChecksum())
  
  	if loop&stack.PacketLoop != 0 {
  		views := make([]buffer.View, 1, 1+len(payload.Views()))
  		views[0] = hdr.View()
  		views = append(views, payload.Views()...)
  		vv := buffer.NewVectorisedView(len(views[0])+payload.Size(), views)
  		e.HandlePacket(r, vv)
  	}
  	if loop&stack.PacketOut == 0 {
  		return nil
  	}
  
  	r.Stats().IP.PacketsSent.Increment()
  	return e.linkEP.WritePacket(r, gso, hdr, payload, ProtocolNumber)
  }
docs: // WritePacket writes a packet to the given destination address and protocol.