mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Changes interpreter data representation from Little to Big Endian.
Previously, it was thought that the interpreter stored data and did evaluations in Little Endian. The confusion originated from the nft binary's debug output, which is the primary artifact guiding the interpreter's implementation. The debug output of the nft binary prints data in Little Endian although the data is actually being stored in Big Endian. Since this is the only reference we have to implement the interpreter, other than the Linux kernel, we thought the data matched the debug output directly such that the interpreter's host representation was Little Endian. The mistake became clear when looking at the Linux kernel code for the byteorder operation and realizing the apparent inconsistencies. This also came with a few other changes as a result of switching endianness. Allows data of any number of bytes (0,16] Converts data in nftinterp from Little to Big Endian to account for the debug output's transformation. PiperOrigin-RevId: 668151185
This commit is contained in:
committed by
gVisor bot
parent
218f52a9f5
commit
99745eb79e
@@ -42,8 +42,6 @@ import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"encoding/binary"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/tcpip/stack"
|
||||
)
|
||||
@@ -658,22 +656,17 @@ func (op comparison) evaluate(regs *registerSet, pkt *stack.PacketBuffer) {
|
||||
// Gets the data from the source register.
|
||||
regBuf := bytesData.getRegisterBuffer(regs, op.sreg)
|
||||
|
||||
// Compares from left to right in 4-byte chunks starting with the rightmost
|
||||
// byte of every 4-byte chunk since the data is little endian.
|
||||
// For example, 16-byte IPv6 address 2001:000a:130f:0000:0000:09c0:876a:130b
|
||||
// is represented as 0x0a000120 0x00000f13 0xc0090000 0x0b136a87 in operations
|
||||
// and as [0a|00|01|20|00|00|0f|13|c0|09|00|00|0b|13|6a|87] in the byte slice,
|
||||
// so we compare right to left in the first 4 bytes and then go to the next 4.
|
||||
// Compares bytes from left to right for all bytes in the comparison data.
|
||||
dif := 0
|
||||
for i := 0; i < len(bytesData.data) && dif == 0; i += 4 {
|
||||
regVal := binary.LittleEndian.Uint32(regBuf[i : i+4])
|
||||
opVal := binary.LittleEndian.Uint32(bytesData.data[i : i+4])
|
||||
if regVal < opVal {
|
||||
for i := 0; i < len(bytesData.data) && dif == 0; i++ {
|
||||
if regBuf[i] < bytesData.data[i] {
|
||||
dif = -1
|
||||
} else if regVal > opVal {
|
||||
} else if regBuf[i] > bytesData.data[i] {
|
||||
dif = 1
|
||||
}
|
||||
}
|
||||
|
||||
// Determines the comparison result depending on the operator.
|
||||
var result bool
|
||||
switch op.cop {
|
||||
case linux.NFT_CMP_EQ:
|
||||
@@ -777,22 +770,25 @@ func (rd verdictData) storeData(regs *registerSet, reg uint8) {
|
||||
regs.verdict = rd.data
|
||||
}
|
||||
|
||||
// bytesData represents data in 4-byte chunks to be stored in a register.
|
||||
// bytesData represents <= 16 bytes of data to be stored in a register.
|
||||
type bytesData struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
// newBytesData creates a RegisterData for 4, 8, 12, or 16 bytes of data.
|
||||
// newBytesData creates a RegisterData for <= 16 bytes of data.
|
||||
func newBytesData(bytes []byte) registerData {
|
||||
if len(bytes)%4 != 0 || len(bytes) > 16 {
|
||||
panic(fmt.Errorf("invalid byte data length: %d", len(bytes)))
|
||||
if len(bytes) == 0 {
|
||||
panic("bytes data cannot be empty")
|
||||
}
|
||||
if len(bytes) > 16 {
|
||||
panic(fmt.Errorf("bytes data cannot be more than 16 bytes: %d", len(bytes)))
|
||||
}
|
||||
return bytesData{data: bytes}
|
||||
}
|
||||
|
||||
// String returns a string representation of the bytes data.
|
||||
// String returns a string representation of the big endian bytes data.
|
||||
func (rd bytesData) String() string {
|
||||
return fmt.Sprintf("%x", rd.data)
|
||||
return fmt.Sprintf("be %x", rd.data)
|
||||
}
|
||||
|
||||
// equal compares the bytes data to another RegisterData object.
|
||||
@@ -812,7 +808,7 @@ func (rd bytesData) validateRegister(reg uint8) error {
|
||||
if isVerdictRegister(reg) {
|
||||
return fmt.Errorf("data cannot be stored in verdict register")
|
||||
}
|
||||
if is4ByteRegister(reg) && len(rd.data) != 4 {
|
||||
if is4ByteRegister(reg) && len(rd.data) > 4 {
|
||||
return fmt.Errorf("%d-byte data cannot be stored in 4-byte register", len(rd.data))
|
||||
}
|
||||
// 16-byte register can be used for any data (guaranteed to be <= 16 bytes)
|
||||
@@ -824,15 +820,14 @@ func (rd bytesData) validateRegister(reg uint8) error {
|
||||
// Note: does not support verdict data and assumes the register is valid for the
|
||||
// given data type.
|
||||
func (rd bytesData) getRegisterBuffer(regs *registerSet, reg uint8) []byte {
|
||||
// The entire 4-byte register (data must be exactly 4 bytes)
|
||||
// Returns the entire 4-byte register
|
||||
if is4ByteRegister(reg) {
|
||||
start := (reg - linux.NFT_REG32_00) * linux.NFT_REG32_SIZE
|
||||
return regs.data[start : start+linux.NFT_REG32_SIZE]
|
||||
}
|
||||
// The appropriate (mod 4)-byte data in a 16-byte register
|
||||
// Leaves excess space on the left (bc the data is little endian).
|
||||
end := (int(reg)-linux.NFT_REG_1)*linux.NFT_REG_SIZE + linux.NFT_REG_SIZE
|
||||
return regs.data[end-len(rd.data) : end]
|
||||
// Returns the entire 16-byte register
|
||||
start := (reg - linux.NFT_REG_1) * linux.NFT_REG_SIZE
|
||||
return regs.data[start : start+linux.NFT_REG_SIZE]
|
||||
}
|
||||
|
||||
// storeData sets the data in the destination register to the bytes data.
|
||||
|
||||
@@ -106,9 +106,9 @@ func TestAcceptAllForSupportedHooks(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestEvaluateImmediate tests that the Immediate operation correctly sets the
|
||||
// TestEvaluateImmediateVerdict tests that the Immediate operation correctly sets the
|
||||
// register value and behaves as expected during evaluation.
|
||||
func TestEvaluateImmediate(t *testing.T) {
|
||||
func TestEvaluateImmediateVerdict(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
tname string
|
||||
baseOp1 operation // will be nil if unused
|
||||
@@ -234,6 +234,12 @@ func TestEvaluateImmediate(t *testing.T) {
|
||||
baseOp2: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NF_ACCEPT)})),
|
||||
verdict: Verdict{Code: VC(linux.NF_DROP)},
|
||||
},
|
||||
{
|
||||
tname: "immediate load register",
|
||||
baseOp1: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NF_DROP)})),
|
||||
baseOp2: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NF_ACCEPT)})),
|
||||
verdict: Verdict{Code: VC(linux.NF_DROP)},
|
||||
},
|
||||
} {
|
||||
t.Run(test.tname, func(t *testing.T) {
|
||||
// Sets up an NFTables object with a base chain (for 2 rules) and another
|
||||
@@ -290,6 +296,62 @@ func TestEvaluateImmediate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestEvaluateImmediateVerdict tests that the Immediate operation correctly
|
||||
// loads bytes data of all lengths into all supported registers.
|
||||
func TestEvaluateImmediateBytesData(t *testing.T) {
|
||||
bytes := []byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10}
|
||||
for blen := 1; blen <= len(bytes); blen++ {
|
||||
for _, registerSize := range []int{linux.NFT_REG32_SIZE, linux.NFT_REG_SIZE} {
|
||||
if blen > registerSize {
|
||||
continue
|
||||
}
|
||||
tname := fmt.Sprintf("immediately load %d bytes into %d-byte registers", blen, registerSize)
|
||||
t.Run(tname, func(t *testing.T) {
|
||||
// Sets up an NFTables object with a base chain with policy accept.
|
||||
nf := NewNFTables()
|
||||
tab, err := nf.AddTable(arbitraryFamily, "test", "test table", false)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error for AddTable: %v", err)
|
||||
}
|
||||
bc, err := tab.AddChain("base_chain", nil, "test chain", false)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error for AddChain: %v", err)
|
||||
}
|
||||
bc.SetBaseChainInfo(arbitraryInfoPolicyAccept)
|
||||
|
||||
// Adds a rule and immediate operation per register of registerSize.
|
||||
switch registerSize {
|
||||
case linux.NFT_REG32_SIZE:
|
||||
for reg := linux.NFT_REG32_00; reg <= linux.NFT_REG32_15; reg++ {
|
||||
rule := &Rule{}
|
||||
rule.addOperation(mustCreateImmediate(t, uint8(reg), newBytesData(bytes[:blen])))
|
||||
if err := bc.RegisterRule(rule, -1); err != nil {
|
||||
t.Fatalf("unexpected error for RegisterRule for rule %d: %v", reg-linux.NFT_REG32_00, err)
|
||||
}
|
||||
}
|
||||
case linux.NFT_REG_SIZE:
|
||||
for reg := linux.NFT_REG_1; reg <= linux.NFT_REG_4; reg++ {
|
||||
rule := &Rule{}
|
||||
rule.addOperation(mustCreateImmediate(t, uint8(reg), newBytesData(bytes[:blen])))
|
||||
if err := bc.RegisterRule(rule, -1); err != nil {
|
||||
t.Fatalf("unexpected error for RegisterRule for rule %d: %v", reg-linux.NFT_REG_1, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Runs evaluation and checks for default policy verdict accept
|
||||
pkt := makeTestingPacket()
|
||||
v, err := nf.EvaluateHook(arbitraryFamily, arbitraryHook, pkt)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error for EvaluateHook: %v", err)
|
||||
}
|
||||
if v.Code != linux.NF_ACCEPT {
|
||||
t.Fatalf("expected default policy verdict accept, got %v", v)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestEvaluateComparison tests that the Comparison operation correctly compares
|
||||
// the data in the source register to the given data.
|
||||
// Note: Relies on expected behavior of the Immediate operation.
|
||||
@@ -345,8 +407,8 @@ func TestEvaluateComparison(t *testing.T) {
|
||||
},
|
||||
{
|
||||
tname: "compare register > 4-byte data, true",
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG32_15, newBytesData([]byte{0, 0, 0, 1})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG32_15, linux.NFT_CMP_GT, newBytesData([]byte{29, 76, 230, 0})),
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG32_15, newBytesData([]byte{29, 76, 230, 0})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG32_15, linux.NFT_CMP_GT, newBytesData([]byte{0, 0, 0, 1})),
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
@@ -381,8 +443,8 @@ func TestEvaluateComparison(t *testing.T) {
|
||||
},
|
||||
{
|
||||
tname: "compare register >= 4-byte data, true gt",
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG32_12, newBytesData([]byte{0, 0, 0, 1})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG32_12, linux.NFT_CMP_GTE, newBytesData([]byte{29, 76, 230, 0})),
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG32_12, newBytesData([]byte{29, 76, 230, 0})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG32_12, linux.NFT_CMP_GTE, newBytesData([]byte{0, 0, 0, 1})),
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
@@ -442,8 +504,8 @@ func TestEvaluateComparison(t *testing.T) {
|
||||
},
|
||||
{
|
||||
tname: "compare register > 8-byte data, true",
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG_4, newBytesData([]byte{0, 0, 0, 1, 0, 0, 0, 0})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_GT, newBytesData([]byte{29, 76, 230, 0, 0, 0, 0, 0})),
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG_4, newBytesData([]byte{29, 76, 230, 0, 0, 0, 0, 0})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_GT, newBytesData([]byte{0, 0, 0, 1, 0, 0, 0, 0})),
|
||||
res: true,
|
||||
},
|
||||
{
|
||||
@@ -478,7 +540,7 @@ func TestEvaluateComparison(t *testing.T) {
|
||||
},
|
||||
{
|
||||
tname: "compare register >= 8-byte data, true gt",
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG_2, newBytesData([]byte{0, 0, 0, 1, 0, 0, 0, 0})),
|
||||
op1: mustCreateImmediate(t, linux.NFT_REG_2, newBytesData([]byte{30, 0, 0, 1, 0, 0, 0, 0})),
|
||||
op2: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GTE, newBytesData([]byte{29, 76, 230, 0, 0, 0, 0, 0})),
|
||||
res: true,
|
||||
},
|
||||
|
||||
@@ -365,17 +365,18 @@ func parseVerdict(tokens []string, lnIdx int, tkIdx int) (int, Verdict, error) {
|
||||
return tkIdx, v, nil
|
||||
}
|
||||
|
||||
// parseHexData parses little endian hexadecimal data from the given token and
|
||||
// returns the index of the next token to process (can consume multiple tokens).
|
||||
// parseHexData parses little endian hexadecimal data from the given token,
|
||||
// converts to big endian, and returns the index of the next token to process.
|
||||
func parseHexData(tokens []string, lnIdx int, tkIdx int) (int, registerData, error) {
|
||||
var bytes []byte
|
||||
for ; tkIdx < len(tokens); tkIdx++ {
|
||||
if len(tokens[tkIdx]) < 2 || tokens[tkIdx][:2] != "0x" {
|
||||
if len(tokens[tkIdx]) <= 2 || tokens[tkIdx][:2] != "0x" {
|
||||
break
|
||||
}
|
||||
|
||||
if len(tokens[tkIdx]) != 10 {
|
||||
return 0, nil, &SyntaxError{lnIdx, tkIdx, fmt.Sprintf("hexadecimal data must be exactly 8 digits long (excluding 0x): '%s'", tokens[tkIdx])}
|
||||
// Hexadecimal data must have 2 digits per byte (even number of characters).
|
||||
if len(tokens[tkIdx])%2 != 0 {
|
||||
return 0, nil, &SyntaxError{lnIdx, tkIdx, fmt.Sprintf("invalid hexadecimal data: '%s'", tokens[tkIdx])}
|
||||
}
|
||||
|
||||
// Decodes the little endian hex string into bytes
|
||||
@@ -383,6 +384,8 @@ func parseHexData(tokens []string, lnIdx int, tkIdx int) (int, registerData, err
|
||||
if err != nil {
|
||||
return 0, nil, &SyntaxError{lnIdx, tkIdx, fmt.Sprintf("could not decode hexadecimal data: '%s'", tokens[tkIdx])}
|
||||
}
|
||||
// Converts the bytes to big endian and appends to the bytes slice.
|
||||
slices.Reverse(bytes4)
|
||||
bytes = append(bytes, bytes4...)
|
||||
}
|
||||
if len(bytes) > 16 {
|
||||
|
||||
@@ -105,40 +105,25 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
opStr: "[ immediate reg 2 jump -> next_chain ]",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 2-byte data",
|
||||
opStr: "[ immediate reg 2 0xb80d ]",
|
||||
expected: nil, // can handle 2-byte data but must be padded to 4-bytes
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 4-byte data",
|
||||
opStr: "[ immediate reg 1 0x0201a8c0 ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_1, newBytesData([]byte{0x02, 0x01, 0xa8, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 6-byte data",
|
||||
opStr: "[ immediate reg 2 0xb80d0120 0x0050 ]",
|
||||
expected: nil, // can handle 6-byte data but must be padded to 8-bytes
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_1, newBytesData([]byte{0xc0, 0xa8, 0x01, 0x02})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 8-byte data",
|
||||
opStr: "[ immediate reg 2 0xb80d0120 0x00000050 ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_2, newBytesData([]byte{0xb8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x00, 0x50})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_2, newBytesData([]byte{0x20, 0x01, 0x0d, 0xb8, 0x50, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 12-byte data",
|
||||
opStr: "[ immediate reg 3 0xb80d0120 0x00000050 0xb80d0120 ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_3, newBytesData([]byte{0xb8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x00, 0x50, 0xb8, 0x0d, 0x01, 0x20})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_3, newBytesData([]byte{0x20, 0x01, 0x0d, 0xb8, 0x50, 0x00, 0x00, 0x00, 0x20, 0x01, 0x0d, 0xb8})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 16-byte data",
|
||||
opStr: "[ immediate reg 4 0xb80d0120 0x00000000 0x00000000 0x02000000 ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_4, newBytesData([]byte{0xb8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with uneven bytes data",
|
||||
opStr: "[ immediate reg 2 0xb80d0120 0x0f60a0 ]",
|
||||
expected: nil, // can handle uneven but must be padded to 4-byte multiple
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_4, newBytesData([]byte{0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with verdict data",
|
||||
@@ -150,16 +135,6 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
opStr: "[ immediate reg 9 goto -> next_chain ]",
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with 2-byte data",
|
||||
opStr: "[ immediate reg 8 0xb80d ]",
|
||||
expected: nil, // can handle 2-byte data but must be padded to 4-bytes
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with 4-byte data",
|
||||
opStr: "[ immediate reg 10 0x0201a8c0 ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG32_02, newBytesData([]byte{0x02, 0x01, 0xa8, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with 16-byte data",
|
||||
opStr: "[ immediate reg 9 0xb80d0120 0x00000000 0x00000000 0x02000000 ]",
|
||||
@@ -213,12 +188,12 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "4-byte register == 4-byte data",
|
||||
opStr: "[ cmp eq reg 8 0x0302010a ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_00, linux.NFT_CMP_EQ, newBytesData([]byte{0x03, 0x02, 0x01, 0x0a})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_00, linux.NFT_CMP_EQ, newBytesData([]byte{0x0a, 0x01, 0x02, 0x03})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register != 4-byte data",
|
||||
opStr: "[ cmp neq reg 9 0x00000064 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_01, linux.NFT_CMP_NEQ, newBytesData([]byte{0x00, 0x00, 0x00, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_01, linux.NFT_CMP_NEQ, newBytesData([]byte{0x64, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register < 4-byte data",
|
||||
@@ -228,17 +203,17 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "4-byte register <= 4-byte data",
|
||||
opStr: "[ cmp lte reg 11 0x00000164 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_03, linux.NFT_CMP_LTE, newBytesData([]byte{0x00, 0x00, 0x01, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_03, linux.NFT_CMP_LTE, newBytesData([]byte{0x64, 0x01, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register > 4-byte data",
|
||||
opStr: "[ cmp gt reg 12 0xe8030000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_04, linux.NFT_CMP_GT, newBytesData([]byte{0xe8, 0x03, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_04, linux.NFT_CMP_GT, newBytesData([]byte{0x00, 0x00, 0x03, 0xe8})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register >= 4-byte data",
|
||||
opStr: "[ cmp gte reg 13 0xc02b0000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_05, linux.NFT_CMP_GTE, newBytesData([]byte{0xc0, 0x2b, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_05, linux.NFT_CMP_GTE, newBytesData([]byte{0x00, 0x00, 0x2b, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with 8-byte data comparison",
|
||||
@@ -258,12 +233,12 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "16-byte register == 4-byte data",
|
||||
opStr: "[ cmp eq reg 1 0x0302010a ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x03, 0x02, 0x01, 0x0a})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x0a, 0x01, 0x02, 0x03})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register != 4-byte data",
|
||||
opStr: "[ cmp neq reg 2 0x00000064 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x00, 0x00, 0x00, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x64, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 4-byte data",
|
||||
@@ -273,27 +248,27 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "16-byte register <= 4-byte data",
|
||||
opStr: "[ cmp lte reg 4 0x00000164 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x00, 0x00, 0x01, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x64, 0x01, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register > 4-byte data",
|
||||
opStr: "[ cmp gt reg 1 0xe8030000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_GT, newBytesData([]byte{0xe8, 0x03, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_GT, newBytesData([]byte{0x00, 0x00, 0x03, 0xe8})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register >= 4-byte data",
|
||||
opStr: "[ cmp gte reg 2 0xc02b0000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GTE, newBytesData([]byte{0xc0, 0x2b, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GTE, newBytesData([]byte{0x00, 0x00, 0x2b, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register == 8-byte data",
|
||||
opStr: "[ cmp eq reg 1 0x0302010a 0x12345678 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x03, 0x02, 0x01, 0x0a, 0x12, 0x34, 0x56, 0x78})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x0a, 0x01, 0x02, 0x03, 0x78, 0x56, 0x34, 0x12})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register != 8-byte data",
|
||||
opStr: "[ cmp neq reg 2 0x00000064 0x00000020 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x20})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x64, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 8-byte data",
|
||||
@@ -303,27 +278,27 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "16-byte register <= 8-byte data",
|
||||
opStr: "[ cmp lte reg 4 0x00000164 0x00000164 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x64, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register > 8-byte data",
|
||||
opStr: "[ cmp gt reg 2 0xe8030000 0x00000f13 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GT, newBytesData([]byte{0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x13})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GT, newBytesData([]byte{0x00, 0x00, 0x03, 0xe8, 0x13, 0x0f, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register >= 8-byte data",
|
||||
opStr: "[ cmp gte reg 3 0x0a000120 0xc0090000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_GTE, newBytesData([]byte{0x0a, 0x00, 0x01, 0x20, 0xc0, 0x09, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_GTE, newBytesData([]byte{0x20, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x09, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register == 12-byte data",
|
||||
opStr: "[ cmp eq reg 1 0x0302010a 0x00000000 0x12345678 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x03, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x0a, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register != 12-byte data",
|
||||
opStr: "[ cmp neq reg 2 0x00000064 0x00000000 0x00000020 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 12-byte data",
|
||||
@@ -333,27 +308,27 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "16-byte register <= 12-byte data",
|
||||
opStr: "[ cmp lte reg 4 0x00000164 0x00000164 0x00000164 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x64, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register > 12-byte data",
|
||||
opStr: "[ cmp gt reg 2 0xe8030000 0x00000f13 0xc0090000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GT, newBytesData([]byte{0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GT, newBytesData([]byte{0x00, 0x00, 0x03, 0xe8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register >= 12-byte data",
|
||||
opStr: "[ cmp gte reg 3 0x0a000120 0x00000f13 0xc0090000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_GTE, newBytesData([]byte{0x0a, 0x00, 0x01, 0x20, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_GTE, newBytesData([]byte{0x20, 0x01, 0x00, 0x0a, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register == 16-byte data",
|
||||
opStr: "[ cmp eq reg 1 0x0302010a 0x00000000 0x00000000 0x02000002 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x03, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_1, linux.NFT_CMP_EQ, newBytesData([]byte{0x0a, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register != 16-byte data",
|
||||
opStr: "[ cmp neq reg 2 0x00000064 0x00000000 0x00000000 0x02000000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_NEQ, newBytesData([]byte{0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 16-byte data",
|
||||
@@ -363,17 +338,17 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
{
|
||||
tname: "16-byte register <= 16-byte data",
|
||||
opStr: "[ cmp lte reg 4 0x00000164 0x00000164 0x00000164 0x00000164 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_4, linux.NFT_CMP_LTE, newBytesData([]byte{0x64, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00, 0x64, 0x01, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register > 16-byte data",
|
||||
opStr: "[ cmp gt reg 2 0xe8030000 0x00000f13 0xc0090000 0x0b136a87 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GT, newBytesData([]byte{0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00, 0x0b, 0x13, 0x6a, 0x87})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_2, linux.NFT_CMP_GT, newBytesData([]byte{0x00, 0x00, 0x03, 0xe8, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register >= 16-byte data",
|
||||
opStr: "[ cmp gte reg 3 0x0a000120 0x00000f13 0xc0090000 0x0b136a87 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_GTE, newBytesData([]byte{0x0a, 0x00, 0x01, 0x20, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00, 0x0b, 0x13, 0x6a, 0x87})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_GTE, newBytesData([]byte{0x20, 0x01, 0x00, 0x0a, 0x13, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x09, 0xc0, 0x87, 0x6a, 0x13, 0x0b})),
|
||||
},
|
||||
} {
|
||||
t.Run(test.tname, func(t *testing.T) { checkOp(t, test, checkComparisonOp) })
|
||||
|
||||
Reference in New Issue
Block a user