mirror of
https://github.com/podman-container-tools/podman.git
synced 2026-10-18 03:47:33 +00:00
This was implemented by containers/netavark #1369; this commit completes the process by wiring it into Podman. We now respect the CLI order for configured networks - if a user passes `--net net1,net2` we guarantee that net1 will be configured before net2. For containers created before this patch, we don't retain enough information to configure networks in CLI order, so we use alphabetical order instead to still guarantee consistency. No breaking API changes have been made, but we do add a new field to supplement the existing map to (optionally) provide ordering information. The Podman CLI will always pass this. Existing applications that do not will, again, receive] deterministic ordering based on an alphabetical sort of network names. This requires the latest version of Netavark to work properly. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
387 lines
11 KiB
Go
387 lines
11 KiB
Go
//go:build amd64 && !appengine && !noasm && gc
|
|
|
|
package zstd
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/klauspost/compress/internal/cpuinfo"
|
|
)
|
|
|
|
type decodeSyncAsmContext struct {
|
|
llTable []decSymbol
|
|
mlTable []decSymbol
|
|
ofTable []decSymbol
|
|
llState uint64
|
|
mlState uint64
|
|
ofState uint64
|
|
iteration int
|
|
litRemain int
|
|
out []byte
|
|
outPosition int
|
|
literals []byte
|
|
litPosition int
|
|
history []byte
|
|
windowSize int
|
|
ll int // set on error (not for all errors, please refer to _generate/gen.go)
|
|
ml int // set on error (not for all errors, please refer to _generate/gen.go)
|
|
mo int // set on error (not for all errors, please refer to _generate/gen.go)
|
|
}
|
|
|
|
// sequenceDecs_decodeSync_amd64 implements the main loop of sequenceDecs.decodeSync in x86 asm.
|
|
//
|
|
// Please refer to seqdec_generic.go for the reference implementation.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decodeSync_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
|
|
|
// sequenceDecs_decodeSync_bmi2 implements the main loop of sequenceDecs.decodeSync in x86 asm with BMI2 extensions.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decodeSync_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
|
|
|
// sequenceDecs_decodeSync_safe_amd64 does the same as above, but does not write more than output buffer.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decodeSync_safe_amd64(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
|
|
|
// sequenceDecs_decodeSync_safe_bmi2 does the same as above, but does not write more than output buffer.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decodeSync_safe_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeSyncAsmContext) int
|
|
|
|
// decode sequences from the stream with the provided history but without a dictionary.
|
|
func (s *sequenceDecs) decodeSyncSimple(hist []byte) (bool, error) {
|
|
if len(s.dict) > 0 {
|
|
return false, nil
|
|
}
|
|
if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSize {
|
|
return false, nil
|
|
}
|
|
|
|
// FIXME: Using unsafe memory copies leads to rare, random crashes
|
|
// with fuzz testing. It is therefore disabled for now.
|
|
const useSafe = true
|
|
/*
|
|
useSafe := false
|
|
if s.maxSyncLen == 0 && cap(s.out)-len(s.out) < maxCompressedBlockSizeAlloc {
|
|
useSafe = true
|
|
}
|
|
if s.maxSyncLen > 0 && cap(s.out)-len(s.out)-compressedBlockOverAlloc < int(s.maxSyncLen) {
|
|
useSafe = true
|
|
}
|
|
if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc {
|
|
useSafe = true
|
|
}
|
|
*/
|
|
|
|
br := s.br
|
|
|
|
maxBlockSize := min(s.windowSize, maxCompressedBlockSize)
|
|
|
|
ctx := decodeSyncAsmContext{
|
|
llTable: s.litLengths.fse.dt[:maxTablesize],
|
|
mlTable: s.matchLengths.fse.dt[:maxTablesize],
|
|
ofTable: s.offsets.fse.dt[:maxTablesize],
|
|
llState: uint64(s.litLengths.state.state),
|
|
mlState: uint64(s.matchLengths.state.state),
|
|
ofState: uint64(s.offsets.state.state),
|
|
iteration: s.nSeqs - 1,
|
|
litRemain: len(s.literals),
|
|
out: s.out,
|
|
outPosition: len(s.out),
|
|
literals: s.literals,
|
|
windowSize: s.windowSize,
|
|
history: hist,
|
|
}
|
|
|
|
s.seqSize = 0
|
|
startSize := len(s.out)
|
|
|
|
var errCode int
|
|
if cpuinfo.HasBMI2() {
|
|
if useSafe {
|
|
errCode = sequenceDecs_decodeSync_safe_bmi2(s, br, &ctx)
|
|
} else {
|
|
errCode = sequenceDecs_decodeSync_bmi2(s, br, &ctx)
|
|
}
|
|
} else {
|
|
if useSafe {
|
|
errCode = sequenceDecs_decodeSync_safe_amd64(s, br, &ctx)
|
|
} else {
|
|
errCode = sequenceDecs_decodeSync_amd64(s, br, &ctx)
|
|
}
|
|
}
|
|
switch errCode {
|
|
case noError:
|
|
break
|
|
|
|
case errorMatchLenOfsMismatch:
|
|
return true, fmt.Errorf("zero matchoff and matchlen (%d) > 0", ctx.ml)
|
|
|
|
case errorMatchLenTooBig:
|
|
return true, fmt.Errorf("match len (%d) bigger than max allowed length", ctx.ml)
|
|
|
|
case errorMatchOffTooBig:
|
|
return true, fmt.Errorf("match offset (%d) bigger than current history (%d)",
|
|
ctx.mo, ctx.outPosition+len(hist)-startSize)
|
|
|
|
case errorNotEnoughLiterals:
|
|
return true, fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available",
|
|
ctx.ll, ctx.litRemain+ctx.ll)
|
|
|
|
case errorOverread:
|
|
return true, io.ErrUnexpectedEOF
|
|
|
|
case errorNotEnoughSpace:
|
|
size := ctx.outPosition + ctx.ll + ctx.ml
|
|
if debugDecoder {
|
|
println("msl:", s.maxSyncLen, "cap", cap(s.out), "bef:", startSize, "sz:", size-startSize, "mbs:", maxBlockSize, "outsz:", cap(s.out)-startSize)
|
|
}
|
|
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
|
|
|
default:
|
|
return true, fmt.Errorf("sequenceDecs_decode returned erroneous code %d", errCode)
|
|
}
|
|
|
|
s.seqSize += ctx.litRemain
|
|
if s.seqSize > maxBlockSize {
|
|
return true, fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
|
}
|
|
err := br.close()
|
|
if err != nil {
|
|
printf("Closing sequences: %v, %+v\n", err, *br)
|
|
return true, err
|
|
}
|
|
|
|
s.literals = s.literals[ctx.litPosition:]
|
|
t := ctx.outPosition
|
|
s.out = s.out[:t]
|
|
|
|
// Add final literals
|
|
s.out = append(s.out, s.literals...)
|
|
if debugDecoder {
|
|
t += len(s.literals)
|
|
if t != len(s.out) {
|
|
panic(fmt.Errorf("length mismatch, want %d, got %d", len(s.out), t))
|
|
}
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
type decodeAsmContext struct {
|
|
llTable []decSymbol
|
|
mlTable []decSymbol
|
|
ofTable []decSymbol
|
|
llState uint64
|
|
mlState uint64
|
|
ofState uint64
|
|
iteration int
|
|
seqs []seqVals
|
|
litRemain int
|
|
}
|
|
|
|
const noError = 0
|
|
|
|
// error reported when mo == 0 && ml > 0
|
|
const errorMatchLenOfsMismatch = 1
|
|
|
|
// error reported when ml > maxMatchLen
|
|
const errorMatchLenTooBig = 2
|
|
|
|
// error reported when mo > available history or mo > s.windowSize
|
|
const errorMatchOffTooBig = 3
|
|
|
|
// error reported when the sum of literal lengths exeeceds the literal buffer size
|
|
const errorNotEnoughLiterals = 4
|
|
|
|
// error reported when capacity of `out` is too small
|
|
const errorNotEnoughSpace = 5
|
|
|
|
// error reported when bits are overread.
|
|
const errorOverread = 6
|
|
|
|
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
|
|
//
|
|
// Please refer to seqdec_generic.go for the reference implementation.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decode_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
|
|
|
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm.
|
|
//
|
|
// Please refer to seqdec_generic.go for the reference implementation.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decode_56_amd64(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
|
|
|
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decode_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
|
|
|
// sequenceDecs_decode implements the main loop of sequenceDecs in x86 asm with BMI2 extensions.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_decode_56_bmi2(s *sequenceDecs, br *bitReader, ctx *decodeAsmContext) int
|
|
|
|
// decode sequences from the stream without the provided history.
|
|
func (s *sequenceDecs) decode(seqs []seqVals) error {
|
|
br := s.br
|
|
|
|
maxBlockSize := min(s.windowSize, maxCompressedBlockSize)
|
|
|
|
ctx := decodeAsmContext{
|
|
llTable: s.litLengths.fse.dt[:maxTablesize],
|
|
mlTable: s.matchLengths.fse.dt[:maxTablesize],
|
|
ofTable: s.offsets.fse.dt[:maxTablesize],
|
|
llState: uint64(s.litLengths.state.state),
|
|
mlState: uint64(s.matchLengths.state.state),
|
|
ofState: uint64(s.offsets.state.state),
|
|
seqs: seqs,
|
|
iteration: len(seqs) - 1,
|
|
litRemain: len(s.literals),
|
|
}
|
|
|
|
if debugDecoder {
|
|
println("decode: decoding", len(seqs), "sequences", br.remain(), "bits remain on stream")
|
|
}
|
|
|
|
s.seqSize = 0
|
|
lte56bits := s.maxBits+s.offsets.fse.actualTableLog+s.matchLengths.fse.actualTableLog+s.litLengths.fse.actualTableLog <= 56
|
|
var errCode int
|
|
if cpuinfo.HasBMI2() {
|
|
if lte56bits {
|
|
errCode = sequenceDecs_decode_56_bmi2(s, br, &ctx)
|
|
} else {
|
|
errCode = sequenceDecs_decode_bmi2(s, br, &ctx)
|
|
}
|
|
} else {
|
|
if lte56bits {
|
|
errCode = sequenceDecs_decode_56_amd64(s, br, &ctx)
|
|
} else {
|
|
errCode = sequenceDecs_decode_amd64(s, br, &ctx)
|
|
}
|
|
}
|
|
if errCode != 0 {
|
|
i := len(seqs) - ctx.iteration - 1
|
|
switch errCode {
|
|
case errorMatchLenOfsMismatch:
|
|
ml := ctx.seqs[i].ml
|
|
return fmt.Errorf("zero matchoff and matchlen (%d) > 0", ml)
|
|
|
|
case errorMatchLenTooBig:
|
|
ml := ctx.seqs[i].ml
|
|
return fmt.Errorf("match len (%d) bigger than max allowed length", ml)
|
|
|
|
case errorNotEnoughLiterals:
|
|
ll := ctx.seqs[i].ll
|
|
return fmt.Errorf("unexpected literal count, want %d bytes, but only %d is available", ll, ctx.litRemain+ll)
|
|
case errorOverread:
|
|
return io.ErrUnexpectedEOF
|
|
}
|
|
|
|
return fmt.Errorf("sequenceDecs_decode_amd64 returned erroneous code %d", errCode)
|
|
}
|
|
|
|
if ctx.litRemain < 0 {
|
|
return fmt.Errorf("literal count is too big: total available %d, total requested %d",
|
|
len(s.literals), len(s.literals)-ctx.litRemain)
|
|
}
|
|
|
|
s.seqSize += ctx.litRemain
|
|
if s.seqSize > maxBlockSize {
|
|
return fmt.Errorf("output bigger than max block size (%d)", maxBlockSize)
|
|
}
|
|
if debugDecoder {
|
|
println("decode: ", br.remain(), "bits remain on stream. code:", errCode)
|
|
}
|
|
err := br.close()
|
|
if err != nil {
|
|
printf("Closing sequences: %v, %+v\n", err, *br)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
|
|
type executeAsmContext struct {
|
|
seqs []seqVals
|
|
seqIndex int
|
|
out []byte
|
|
history []byte
|
|
literals []byte
|
|
outPosition int
|
|
litPosition int
|
|
windowSize int
|
|
}
|
|
|
|
// sequenceDecs_executeSimple_amd64 implements the main loop of sequenceDecs.executeSimple in x86 asm.
|
|
//
|
|
// Returns false if a match offset is too big.
|
|
//
|
|
// Please refer to seqdec_generic.go for the reference implementation.
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_executeSimple_amd64(ctx *executeAsmContext) bool
|
|
|
|
// Same as above, but with safe memcopies
|
|
//
|
|
//go:noescape
|
|
func sequenceDecs_executeSimple_safe_amd64(ctx *executeAsmContext) bool
|
|
|
|
// executeSimple handles cases when dictionary is not used.
|
|
func (s *sequenceDecs) executeSimple(seqs []seqVals, hist []byte) error {
|
|
// Ensure we have enough output size...
|
|
if len(s.out)+s.seqSize+compressedBlockOverAlloc > cap(s.out) {
|
|
addBytes := s.seqSize + len(s.out) + compressedBlockOverAlloc
|
|
s.out = append(s.out, make([]byte, addBytes)...)
|
|
s.out = s.out[:len(s.out)-addBytes]
|
|
}
|
|
|
|
if debugDecoder {
|
|
printf("Execute %d seqs with literals: %d into %d bytes\n", len(seqs), len(s.literals), s.seqSize)
|
|
}
|
|
|
|
var t = len(s.out)
|
|
out := s.out[:t+s.seqSize]
|
|
|
|
ctx := executeAsmContext{
|
|
seqs: seqs,
|
|
seqIndex: 0,
|
|
out: out,
|
|
history: hist,
|
|
outPosition: t,
|
|
litPosition: 0,
|
|
literals: s.literals,
|
|
windowSize: s.windowSize,
|
|
}
|
|
var ok bool
|
|
if cap(s.literals) < len(s.literals)+compressedBlockOverAlloc {
|
|
ok = sequenceDecs_executeSimple_safe_amd64(&ctx)
|
|
} else {
|
|
ok = sequenceDecs_executeSimple_amd64(&ctx)
|
|
}
|
|
if !ok {
|
|
return fmt.Errorf("match offset (%d) bigger than current history (%d)",
|
|
seqs[ctx.seqIndex].mo, ctx.outPosition+len(hist))
|
|
}
|
|
s.literals = s.literals[ctx.litPosition:]
|
|
t = ctx.outPosition
|
|
|
|
// Add final literals
|
|
copy(out[t:], s.literals)
|
|
if debugDecoder {
|
|
t += len(s.literals)
|
|
if t != len(out) {
|
|
panic(fmt.Errorf("length mismatch, want %d, got %d, ss: %d", len(out), t, s.seqSize))
|
|
}
|
|
}
|
|
s.out = out
|
|
|
|
return nil
|
|
}
|