mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Hide all implementation details deeper than Rule abstraction.
PiperOrigin-RevId: 667367125
This commit is contained in:
committed by
gVisor bot
parent
e84d53199f
commit
bc4a23853e
@@ -550,48 +550,48 @@ func validateBaseChainInfo(info *BaseChainInfo, family AddressFamily) error {
|
||||
// Note: Empty rules should be created directly (via &Rule{}).
|
||||
type Rule struct {
|
||||
chain *Chain
|
||||
ops []Operation
|
||||
ops []operation
|
||||
}
|
||||
|
||||
// Operation represents a single operation in a rule.
|
||||
type Operation interface {
|
||||
// operation represents a single operation in a rule.
|
||||
type operation interface {
|
||||
|
||||
// evaluate evaluates the operation on the given packet and register set,
|
||||
// changing the register set and possibly the packet in place.
|
||||
evaluate(regs *RegisterSet, pkt *stack.PacketBuffer)
|
||||
evaluate(regs *registerSet, pkt *stack.PacketBuffer)
|
||||
}
|
||||
|
||||
// Ensures all operations implement the Operation interface at compile time.
|
||||
var (
|
||||
_ Operation = (*Immediate)(nil)
|
||||
_ Operation = (*Comparison)(nil)
|
||||
_ operation = (*immediate)(nil)
|
||||
_ operation = (*comparison)(nil)
|
||||
)
|
||||
|
||||
// Immediate is an operation that sets the data in a register.
|
||||
type Immediate struct {
|
||||
data RegisterData // Data to set the destination register to.
|
||||
// immediate is an operation that sets the data in a register.
|
||||
type immediate struct {
|
||||
data registerData // Data to set the destination register to.
|
||||
dreg uint8 // Number of the destination register.
|
||||
}
|
||||
|
||||
// NewImmediate creates a new Immediate operation.
|
||||
func NewImmediate(dreg uint8, data RegisterData) (*Immediate, error) {
|
||||
if err := data.ValidateRegister(dreg); err != nil {
|
||||
// newImmediate creates a new Immediate operation.
|
||||
func newImmediate(dreg uint8, data registerData) (*immediate, error) {
|
||||
if err := data.validateRegister(dreg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Immediate{dreg: dreg, data: data}, nil
|
||||
return &immediate{dreg: dreg, data: data}, nil
|
||||
}
|
||||
|
||||
// evaluate for Immediate sets the data in the destination register.
|
||||
func (op Immediate) evaluate(regs *RegisterSet, pkt *stack.PacketBuffer) {
|
||||
op.data.StoreData(regs, op.dreg)
|
||||
func (op immediate) evaluate(regs *registerSet, pkt *stack.PacketBuffer) {
|
||||
op.data.storeData(regs, op.dreg)
|
||||
}
|
||||
|
||||
// Comparison is an operation that compares the data in a register to a given
|
||||
// comparison is an operation that compares the data in a register to a given
|
||||
// value and breaks (by setting the verdict register to NFT_BREAK) from the rule
|
||||
// if the comparison is false.
|
||||
// Note: comparison operations are not supported for the verdict register.
|
||||
type Comparison struct {
|
||||
data RegisterData // Data to compare the source register to.
|
||||
type comparison struct {
|
||||
data registerData // Data to compare the source register to.
|
||||
sreg uint8 // Number of the source register.
|
||||
cop cmpOp // Comparison operator.
|
||||
}
|
||||
@@ -632,26 +632,26 @@ func validateComparisonOp(cop cmpOp) error {
|
||||
}
|
||||
}
|
||||
|
||||
// NewComparison creates a new Comparison operation.
|
||||
func NewComparison(sreg uint8, op int, data RegisterData) (*Comparison, error) {
|
||||
// newComparison creates a new Comparison operation.
|
||||
func newComparison(sreg uint8, op int, data registerData) (*comparison, error) {
|
||||
if sreg == linux.NFT_REG_VERDICT {
|
||||
return nil, fmt.Errorf("comparison operation cannot use verdict register as source")
|
||||
}
|
||||
if err := data.ValidateRegister(sreg); err != nil {
|
||||
if err := data.validateRegister(sreg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cop := cmpOp(op)
|
||||
if err := validateComparisonOp(cop); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Comparison{sreg: sreg, cop: cop, data: data}, nil
|
||||
return &comparison{sreg: sreg, cop: cop, data: data}, nil
|
||||
}
|
||||
|
||||
// evaluate for Comparison compares the data in the source register to the given
|
||||
// data and breaks from the rule if the comparison is false.
|
||||
func (op Comparison) evaluate(regs *RegisterSet, pkt *stack.PacketBuffer) {
|
||||
func (op comparison) evaluate(regs *registerSet, pkt *stack.PacketBuffer) {
|
||||
// Gets the data to compare to.
|
||||
bytesData, ok := op.data.(BytesData)
|
||||
bytesData, ok := op.data.(bytesData)
|
||||
if !ok {
|
||||
panic("comparison operation data is not BytesData")
|
||||
}
|
||||
@@ -716,99 +716,99 @@ func isRegister(reg uint8) bool {
|
||||
return isVerdictRegister(reg) || is16ByteRegister(reg) || is4ByteRegister(reg)
|
||||
}
|
||||
|
||||
// RegisterData represents the data to be set in a register.
|
||||
type RegisterData interface {
|
||||
// registerData represents the data to be set in a register.
|
||||
type registerData interface {
|
||||
// String returns a string representation of the register data.
|
||||
String() string
|
||||
|
||||
// Equal compares the register data to another.
|
||||
Equal(other RegisterData) bool
|
||||
// equal compares the register data to another.
|
||||
equal(other registerData) bool
|
||||
|
||||
// ValidateRegister ensures the register is compatible with the data type,
|
||||
// validateRegister ensures the register is compatible with the data type,
|
||||
// returning an error otherwise.
|
||||
ValidateRegister(reg uint8) error
|
||||
validateRegister(reg uint8) error
|
||||
|
||||
// StoreData sets the data in the destination register, panicking if the
|
||||
// storeData sets the data in the destination register, panicking if the
|
||||
// register is not valid for the data type.
|
||||
// Note: assumes data is valid for register. This is used primarily during
|
||||
// operation evaluation and the data type/register compatibility should have
|
||||
// been checked during the operation init.
|
||||
StoreData(regs *RegisterSet, reg uint8)
|
||||
storeData(regs *registerSet, reg uint8)
|
||||
}
|
||||
|
||||
// VerdictData represents a verdict as data to be stored in a register.
|
||||
type VerdictData struct {
|
||||
// verdictData represents a verdict as data to be stored in a register.
|
||||
type verdictData struct {
|
||||
data Verdict
|
||||
}
|
||||
|
||||
// NewVerdictData creates a RegisterData for a verdict.
|
||||
func NewVerdictData(verdict Verdict) RegisterData { return VerdictData{data: verdict} }
|
||||
// newVerdictData creates a RegisterData for a verdict.
|
||||
func newVerdictData(verdict Verdict) registerData { return verdictData{data: verdict} }
|
||||
|
||||
// String returns a string representation of the verdict data.
|
||||
func (rd VerdictData) String() string {
|
||||
func (rd verdictData) String() string {
|
||||
return rd.data.String()
|
||||
}
|
||||
|
||||
// Equal compares the verdict data to another RegisterData object.
|
||||
func (rd VerdictData) Equal(other RegisterData) bool {
|
||||
// equal compares the verdict data to another RegisterData object.
|
||||
func (rd verdictData) equal(other registerData) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
otherVD, ok := other.(VerdictData)
|
||||
otherVD, ok := other.(verdictData)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return rd.data == otherVD.data
|
||||
}
|
||||
|
||||
// ValidateRegister ensures the register is compatible with VerdictData.
|
||||
func (rd VerdictData) ValidateRegister(reg uint8) error {
|
||||
// validateRegister ensures the register is compatible with VerdictData.
|
||||
func (rd verdictData) validateRegister(reg uint8) error {
|
||||
if !isVerdictRegister(reg) {
|
||||
return fmt.Errorf("verdict can only be stored in verdict register")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// StoreData sets the data in the destination register to the verdict.
|
||||
func (rd VerdictData) StoreData(regs *RegisterSet, reg uint8) {
|
||||
if err := rd.ValidateRegister(reg); err != nil {
|
||||
// storeData sets the data in the destination register to the verdict.
|
||||
func (rd verdictData) storeData(regs *registerSet, reg uint8) {
|
||||
if err := rd.validateRegister(reg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
regs.verdict = rd.data
|
||||
}
|
||||
|
||||
// BytesData represents data in 4-byte chunks to be stored in a register.
|
||||
type BytesData struct {
|
||||
// bytesData represents data in 4-byte chunks to be stored in a register.
|
||||
type bytesData struct {
|
||||
data []byte
|
||||
}
|
||||
|
||||
// NewBytesData creates a RegisterData for 4, 8, 12, or 16 bytes of data.
|
||||
func NewBytesData(bytes []byte) RegisterData {
|
||||
// newBytesData creates a RegisterData for 4, 8, 12, or 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)))
|
||||
}
|
||||
return BytesData{data: bytes}
|
||||
return bytesData{data: bytes}
|
||||
}
|
||||
|
||||
// String returns a string representation of the bytes data.
|
||||
func (rd BytesData) String() string {
|
||||
func (rd bytesData) String() string {
|
||||
return fmt.Sprintf("%x", rd.data)
|
||||
}
|
||||
|
||||
// Equal compares the bytes data to another RegisterData object.
|
||||
func (rd BytesData) Equal(other RegisterData) bool {
|
||||
// equal compares the bytes data to another RegisterData object.
|
||||
func (rd bytesData) equal(other registerData) bool {
|
||||
if other == nil {
|
||||
return false
|
||||
}
|
||||
otherBD, ok := other.(BytesData)
|
||||
otherBD, ok := other.(bytesData)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return slices.Equal(rd.data, otherBD.data)
|
||||
}
|
||||
|
||||
// ValidateRegister ensures the register is compatible with this bytes data.
|
||||
func (rd BytesData) ValidateRegister(reg uint8) error {
|
||||
// validateRegister ensures the register is compatible with this bytes data.
|
||||
func (rd bytesData) validateRegister(reg uint8) error {
|
||||
if isVerdictRegister(reg) {
|
||||
return fmt.Errorf("data cannot be stored in verdict register")
|
||||
}
|
||||
@@ -823,7 +823,7 @@ func (rd BytesData) ValidateRegister(reg uint8) error {
|
||||
// register data from the register set.
|
||||
// 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 {
|
||||
func (rd bytesData) getRegisterBuffer(regs *registerSet, reg uint8) []byte {
|
||||
// The entire 4-byte register (data must be exactly 4 bytes)
|
||||
if is4ByteRegister(reg) {
|
||||
start := (reg - linux.NFT_REG32_00) * linux.NFT_REG32_SIZE
|
||||
@@ -835,33 +835,33 @@ func (rd BytesData) getRegisterBuffer(regs *RegisterSet, reg uint8) []byte {
|
||||
return regs.data[end-len(rd.data) : end]
|
||||
}
|
||||
|
||||
// StoreData sets the data in the destination register to the bytes data.
|
||||
func (rd BytesData) StoreData(regs *RegisterSet, reg uint8) {
|
||||
if err := rd.ValidateRegister(reg); err != nil {
|
||||
// storeData sets the data in the destination register to the bytes data.
|
||||
func (rd bytesData) storeData(regs *registerSet, reg uint8) {
|
||||
if err := rd.validateRegister(reg); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
copy(rd.getRegisterBuffer(regs, reg), rd.data)
|
||||
}
|
||||
|
||||
// RegisterSet represents the set of registers supported by the kernel.
|
||||
// registerSet represents the set of registers supported by the kernel.
|
||||
// Use RegisterData.StoreData to set data in the registers.
|
||||
// Note: Corresponds to nft_regs from include/net/netfilter/nf_tables.h.
|
||||
type RegisterSet struct {
|
||||
type registerSet struct {
|
||||
verdict Verdict // 16-byte verdict register
|
||||
data [registersByteSize]byte // 4 16-byte registers or 16 4-byte registers
|
||||
}
|
||||
|
||||
// NewRegisterSet creates a new RegisterSet with the Continue Verdict and all
|
||||
// newRegisterSet creates a new RegisterSet with the Continue Verdict and all
|
||||
// registers set to 0.
|
||||
func NewRegisterSet() RegisterSet {
|
||||
return RegisterSet{
|
||||
func newRegisterSet() registerSet {
|
||||
return registerSet{
|
||||
verdict: Verdict{Code: VC(linux.NFT_CONTINUE)},
|
||||
data: [registersByteSize]byte{0},
|
||||
}
|
||||
}
|
||||
|
||||
// Verdict returns the verdict data.
|
||||
func (regs *RegisterSet) Verdict() Verdict {
|
||||
func (regs *registerSet) Verdict() Verdict {
|
||||
return regs.verdict
|
||||
}
|
||||
|
||||
@@ -966,7 +966,7 @@ func (nf *NFTables) EvaluateHook(family AddressFamily, hook Hook, pkt *stack.Pac
|
||||
return Verdict{Code: VC(linux.NF_ACCEPT)}, nil
|
||||
}
|
||||
|
||||
regs := NewRegisterSet()
|
||||
regs := newRegisterSet()
|
||||
|
||||
// Evaluates packet through all base chains for given hook in priority order.
|
||||
var bc *Chain
|
||||
@@ -1003,7 +1003,7 @@ func (nf *NFTables) EvaluateHook(family AddressFamily, hook Hook, pkt *stack.Pac
|
||||
|
||||
// evaluateFromRule is a helper function for Chain.evaluate that evaluates the
|
||||
// packet through the rules in the chain starting at the specified rule index.
|
||||
func (c *Chain) evaluateFromRule(rIdx int, jumpDepth int, regs *RegisterSet, pkt *stack.PacketBuffer) error {
|
||||
func (c *Chain) evaluateFromRule(rIdx int, jumpDepth int, regs *registerSet, pkt *stack.PacketBuffer) error {
|
||||
if jumpDepth >= nestedJumpLimit {
|
||||
return fmt.Errorf("jump stack limit of %d exceeded", nestedJumpLimit)
|
||||
}
|
||||
@@ -1060,7 +1060,7 @@ evalLoop:
|
||||
|
||||
// evaluate for Chain evaluates the packet through the chain's rules and returns
|
||||
// the verdict and modifies the packet in place.
|
||||
func (c *Chain) evaluate(regs *RegisterSet, pkt *stack.PacketBuffer) error {
|
||||
func (c *Chain) evaluate(regs *registerSet, pkt *stack.PacketBuffer) error {
|
||||
return c.evaluateFromRule(0, 0, regs, pkt)
|
||||
}
|
||||
|
||||
@@ -1068,7 +1068,7 @@ func (c *Chain) evaluate(regs *RegisterSet, pkt *stack.PacketBuffer) error {
|
||||
// the register set and possibly the packet in place.
|
||||
// The verdict in regs.Verdict() may be an nf table internal verdict or a
|
||||
// netfilter terminal verdict.
|
||||
func (r *Rule) evaluate(regs *RegisterSet, pkt *stack.PacketBuffer) error {
|
||||
func (r *Rule) evaluate(regs *registerSet, pkt *stack.PacketBuffer) error {
|
||||
for _, op := range r.ops {
|
||||
op.evaluate(regs, pkt)
|
||||
if regs.Verdict().Code != VC(linux.NFT_CONTINUE) {
|
||||
@@ -1540,12 +1540,12 @@ func (c *Chain) RuleCount() int {
|
||||
// isJumpOrGoto returns whether the operation is an immediate operation that
|
||||
// sets the verdict register to a jump or goto verdict and returns the name of
|
||||
// the target chain to jump or goto if so.
|
||||
func isJumpOrGotoOperation(op Operation) (bool, string) {
|
||||
imm, ok := op.(*Immediate)
|
||||
func isJumpOrGotoOperation(op operation) (bool, string) {
|
||||
imm, ok := op.(*immediate)
|
||||
if !ok {
|
||||
return false, ""
|
||||
}
|
||||
verdictData, ok := imm.data.(VerdictData)
|
||||
verdictData, ok := imm.data.(verdictData)
|
||||
if !ok {
|
||||
return false, ""
|
||||
}
|
||||
@@ -1587,10 +1587,10 @@ func (c *Chain) checkLoops(source *Chain) error {
|
||||
// Rule Functions
|
||||
//
|
||||
|
||||
// AddOperation adds an operation to the rule. Adding operations is only allowed
|
||||
// addOperation adds an operation to the rule. Adding operations is only allowed
|
||||
// before the rule is registered to a chain. Returns an error if the operation
|
||||
// is nil or if the rule is already registered to a chain.
|
||||
func (r *Rule) AddOperation(op Operation) error {
|
||||
func (r *Rule) addOperation(op operation) error {
|
||||
if op == nil {
|
||||
return fmt.Errorf("operation is nil")
|
||||
}
|
||||
|
||||
+262
-262
File diff suppressed because it is too large
Load Diff
@@ -108,7 +108,7 @@ func InterpretRule(ruleString string) (*Rule, error) {
|
||||
return s == ""
|
||||
})
|
||||
|
||||
r := &Rule{ops: make([]Operation, 0, len(lines))}
|
||||
r := &Rule{ops: make([]operation, 0, len(lines))}
|
||||
|
||||
// Interprets all operations in the rule.
|
||||
for lnIdx, line := range lines {
|
||||
@@ -116,7 +116,7 @@ func InterpretRule(ruleString string) (*Rule, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := r.AddOperation(op); err != nil {
|
||||
if err := r.addOperation(op); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func InterpretRule(ruleString string) (*Rule, error) {
|
||||
// assumed to be a single line of text surrounded in square brackets.
|
||||
// Note: the operation string should be generated as output from the official nft
|
||||
// binary (can be accomplished by using flag --debug=netlink).
|
||||
func InterpretOperation(line string, lnIdx int) (Operation, error) {
|
||||
func InterpretOperation(line string, lnIdx int) (operation, error) {
|
||||
tokens := strings.Fields(line)
|
||||
if len(tokens) < 2 {
|
||||
return nil, &SyntaxError{lnIdx, 0, fmt.Sprintf("incorrect number of tokens for operation, should be at least 2, got %d", len(tokens))}
|
||||
@@ -146,7 +146,7 @@ func InterpretOperation(line string, lnIdx int) (Operation, error) {
|
||||
}
|
||||
|
||||
// InterpretImmediate creates a new Immediate operation from the given string.
|
||||
func InterpretImmediate(line string, lnIdx int) (Operation, error) {
|
||||
func InterpretImmediate(line string, lnIdx int) (operation, error) {
|
||||
tokens := strings.Fields(line)
|
||||
|
||||
// Requires at least 6 tokens:
|
||||
@@ -193,7 +193,7 @@ func InterpretImmediate(line string, lnIdx int) (Operation, error) {
|
||||
}
|
||||
|
||||
// Create the operation with the specified arguments.
|
||||
imm, err := NewImmediate(reg, data)
|
||||
imm, err := newImmediate(reg, data)
|
||||
if err != nil {
|
||||
return nil, &LogicError{lnIdx, tkIdx, err}
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func InterpretImmediate(line string, lnIdx int) (Operation, error) {
|
||||
}
|
||||
|
||||
// InterpretComparison creates a new Comparison operation from the given string.
|
||||
func InterpretComparison(line string, lnIdx int) (Operation, error) {
|
||||
func InterpretComparison(line string, lnIdx int) (operation, error) {
|
||||
tokens := strings.Fields(line)
|
||||
|
||||
// Requires at least 7 tokens:
|
||||
@@ -256,7 +256,7 @@ func InterpretComparison(line string, lnIdx int) (Operation, error) {
|
||||
}
|
||||
|
||||
// Create the operation with the specified arguments.
|
||||
cmp, err := NewComparison(reg, cop, data)
|
||||
cmp, err := newComparison(reg, cop, data)
|
||||
if err != nil {
|
||||
return nil, &LogicError{lnIdx, tkIdx, err}
|
||||
}
|
||||
@@ -297,14 +297,14 @@ func parseRegister(regString string, lnIdx int, tkIdx int) (uint8, error) {
|
||||
// parseRegisterData parses the register data from the given token and returns
|
||||
// the index of the next token to process (can consume multiple tokens).
|
||||
// Note: assumes the register index is valid (was checked in parseRegister).
|
||||
func parseRegisterData(reg uint8, tokens []string, lnIdx int, tkIdx int) (int, RegisterData, error) {
|
||||
func parseRegisterData(reg uint8, tokens []string, lnIdx int, tkIdx int) (int, registerData, error) {
|
||||
// Handles verdict data.
|
||||
if isVerdictRegister(reg) {
|
||||
nextIdx, verdict, err := parseVerdict(tokens, lnIdx, tkIdx)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
return nextIdx, NewVerdictData(verdict), nil
|
||||
return nextIdx, newVerdictData(verdict), nil
|
||||
}
|
||||
// Handles hex data (4-, 8-, 12-, or 16-byte).
|
||||
if len(tokens[tkIdx]) > 1 && tokens[tkIdx][:2] == "0x" {
|
||||
@@ -314,7 +314,7 @@ func parseRegisterData(reg uint8, tokens []string, lnIdx int, tkIdx int) (int, R
|
||||
}
|
||||
// 4-byte data is only valid for 4-byte register. Any byte data can be
|
||||
// stored in 16-byte registerValidates the register data type.
|
||||
if err := data.ValidateRegister(reg); err != nil {
|
||||
if err := data.validateRegister(reg); err != nil {
|
||||
return 0, nil, &LogicError{lnIdx, tkIdx, err}
|
||||
}
|
||||
return nextIdx, data, nil
|
||||
@@ -367,7 +367,7 @@ func parseVerdict(tokens []string, lnIdx int, tkIdx int) (int, Verdict, error) {
|
||||
|
||||
// parseHexData parses little endian hexadecimal data from the given token and
|
||||
// returns the index of the next token to process (can consume multiple tokens).
|
||||
func parseHexData(tokens []string, lnIdx int, tkIdx int) (int, RegisterData, error) {
|
||||
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" {
|
||||
@@ -388,7 +388,7 @@ func parseHexData(tokens []string, lnIdx int, tkIdx int) (int, RegisterData, err
|
||||
if len(bytes) > 16 {
|
||||
return 0, nil, &SyntaxError{lnIdx, tkIdx, fmt.Sprintf("cannot have more than 16 bytes of hexadecimal data, got %d", len(bytes))}
|
||||
}
|
||||
return tkIdx, NewBytesData(bytes), nil
|
||||
return tkIdx, newBytesData(bytes), nil
|
||||
}
|
||||
|
||||
// parseCmpOp parses the int representing the cmpOp from the given string.
|
||||
|
||||
@@ -24,12 +24,12 @@ import (
|
||||
type interpretOperationTestAction struct {
|
||||
tname string
|
||||
opStr string
|
||||
expected Operation // will be nil if an error is expected
|
||||
expected operation // will be nil if an error is expected
|
||||
}
|
||||
|
||||
// checkOp is a generic operation validation function used for testing that
|
||||
// the interpretation of an operation matches the expected operation.
|
||||
func checkOp(t *testing.T, test interpretOperationTestAction, checkFunc func(string, Operation, Operation) error) {
|
||||
func checkOp(t *testing.T, test interpretOperationTestAction, checkFunc func(string, operation, operation) error) {
|
||||
rule, err := InterpretRule(test.opStr)
|
||||
if test.expected == nil {
|
||||
if err == nil {
|
||||
@@ -58,32 +58,32 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
{
|
||||
tname: "verdict register with accept verdict",
|
||||
opStr: "[ immediate reg 0 accept ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, NewVerdictData(Verdict{Code: VC(linux.NF_ACCEPT)})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NF_ACCEPT)})),
|
||||
},
|
||||
{
|
||||
tname: "verdict register with drop verdict",
|
||||
opStr: "[ immediate reg 0 drop ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, NewVerdictData(Verdict{Code: VC(linux.NF_DROP)})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NF_DROP)})),
|
||||
},
|
||||
{
|
||||
tname: "verdict register with continue verdict",
|
||||
opStr: "[ immediate reg 0 continue ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, NewVerdictData(Verdict{Code: VC(linux.NFT_CONTINUE)})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NFT_CONTINUE)})),
|
||||
},
|
||||
{
|
||||
tname: "verdict register with return verdict",
|
||||
opStr: "[ immediate reg 0 return ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, NewVerdictData(Verdict{Code: VC(linux.NFT_RETURN)})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NFT_RETURN)})),
|
||||
},
|
||||
{
|
||||
tname: "verdict register with jump verdict",
|
||||
opStr: "[ immediate reg 0 jump -> next_chain ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, NewVerdictData(Verdict{Code: VC(linux.NFT_JUMP), ChainName: "next_chain"})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NFT_JUMP), ChainName: "next_chain"})),
|
||||
},
|
||||
{
|
||||
tname: "verdict register with goto verdict",
|
||||
opStr: "[ immediate reg 0 goto -> next_chain ]",
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, NewVerdictData(Verdict{Code: VC(linux.NFT_GOTO), ChainName: "next_chain"})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_VERDICT, newVerdictData(Verdict{Code: VC(linux.NFT_GOTO), ChainName: "next_chain"})),
|
||||
},
|
||||
{
|
||||
tname: "verdict register with 4-byte data",
|
||||
@@ -113,7 +113,7 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
{
|
||||
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})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG_1, newBytesData([]byte{0x02, 0x01, 0xa8, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register with 6-byte data",
|
||||
@@ -123,17 +123,17 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
{
|
||||
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{0xb8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x00, 0x50})),
|
||||
},
|
||||
{
|
||||
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{0xb8, 0x0d, 0x01, 0x20, 0x00, 0x00, 0x00, 0x50, 0xb8, 0x0d, 0x01, 0x20})),
|
||||
},
|
||||
{
|
||||
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})),
|
||||
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",
|
||||
@@ -158,7 +158,7 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
{
|
||||
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})),
|
||||
expected: mustCreateImmediate(t, linux.NFT_REG32_02, newBytesData([]byte{0x02, 0x01, 0xa8, 0xc0})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with 16-byte data",
|
||||
@@ -172,16 +172,16 @@ func TestInterpretImmediateOps(t *testing.T) {
|
||||
|
||||
// checkImmediateOp checks that the given operation is an immediate operation
|
||||
// and that it matches the expected immediate operation.
|
||||
func checkImmediateOp(tname string, expected Operation, actual Operation) error {
|
||||
expectedImm := expected.(*Immediate)
|
||||
imm, ok := actual.(*Immediate)
|
||||
func checkImmediateOp(tname string, expected operation, actual operation) error {
|
||||
expectedImm := expected.(*immediate)
|
||||
imm, ok := actual.(*immediate)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected operation type to be Immediate for %s, got %T", tname, actual)
|
||||
}
|
||||
if imm.dreg != expectedImm.dreg {
|
||||
return fmt.Errorf("expected register to be %d for %s, got %d", expectedImm.dreg, tname, imm.dreg)
|
||||
}
|
||||
if !imm.data.Equal(expectedImm.data) {
|
||||
if !imm.data.equal(expectedImm.data) {
|
||||
return fmt.Errorf("expected data to be %v for %s, got %v", expectedImm.data, tname, imm.data)
|
||||
}
|
||||
return nil
|
||||
@@ -213,32 +213,32 @@ 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{0x03, 0x02, 0x01, 0x0a})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x00, 0x64})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register < 4-byte data",
|
||||
opStr: "[ cmp lt reg 10 0x00000000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_02, linux.NFT_CMP_LT, NewBytesData([]byte{0x00, 0x00, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG32_02, linux.NFT_CMP_LT, newBytesData([]byte{0x00, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x01, 0x64})),
|
||||
},
|
||||
{
|
||||
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{0xe8, 0x03, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0xc0, 0x2b, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "4-byte register with 8-byte data comparison",
|
||||
@@ -258,122 +258,122 @@ 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{0x03, 0x02, 0x01, 0x0a})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x00, 0x64})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 4-byte data",
|
||||
opStr: "[ cmp lt reg 3 0x00000000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, NewBytesData([]byte{0x00, 0x00, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, newBytesData([]byte{0x00, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x01, 0x64})),
|
||||
},
|
||||
{
|
||||
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{0xe8, 0x03, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0xc0, 0x2b, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x03, 0x02, 0x01, 0x0a, 0x12, 0x34, 0x56, 0x78})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x20})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 8-byte data",
|
||||
opStr: "[ cmp lt reg 3 0x00000000 0x00000000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, NewBytesData([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, newBytesData([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64})),
|
||||
},
|
||||
{
|
||||
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{0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x13})),
|
||||
},
|
||||
{
|
||||
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{0x0a, 0x00, 0x01, 0x20, 0xc0, 0x09, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x03, 0x02, 0x01, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 12-byte data",
|
||||
opStr: "[ cmp lt reg 3 0x00000000 0x00000000 0x00000000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, NewBytesData([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, newBytesData([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64})),
|
||||
},
|
||||
{
|
||||
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{0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x0a, 0x00, 0x01, 0x20, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x03, 0x02, 0x01, 0x0a, 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{0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
tname: "16-byte register < 16-byte data",
|
||||
opStr: "[ cmp lt reg 3 0x00000000 0x00000000 0x00000000 0x00000000 ]",
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, NewBytesData([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
|
||||
expected: mustCreateComparison(t, linux.NFT_REG_3, linux.NFT_CMP_LT, newBytesData([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})),
|
||||
},
|
||||
{
|
||||
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{0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64, 0x00, 0x00, 0x01, 0x64})),
|
||||
},
|
||||
{
|
||||
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{0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00, 0x0b, 0x13, 0x6a, 0x87})),
|
||||
},
|
||||
{
|
||||
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{0x0a, 0x00, 0x01, 0x20, 0x00, 0x00, 0x0f, 0x13, 0xc0, 0x09, 0x00, 0x00, 0x0b, 0x13, 0x6a, 0x87})),
|
||||
},
|
||||
} {
|
||||
t.Run(test.tname, func(t *testing.T) { checkOp(t, test, checkComparisonOp) })
|
||||
@@ -382,9 +382,9 @@ func TestInterpretComparisonOps(t *testing.T) {
|
||||
|
||||
// checkComparisonOp checks that the given operation is an comparison operation
|
||||
// and that it matches the expected comparison operation.
|
||||
func checkComparisonOp(tname string, expected Operation, actual Operation) error {
|
||||
expectedCmp := expected.(*Comparison)
|
||||
cmp, ok := actual.(*Comparison)
|
||||
func checkComparisonOp(tname string, expected operation, actual operation) error {
|
||||
expectedCmp := expected.(*comparison)
|
||||
cmp, ok := actual.(*comparison)
|
||||
if !ok {
|
||||
return fmt.Errorf("expected operation type to be Comparison for %s, got %T", tname, actual)
|
||||
}
|
||||
@@ -394,7 +394,7 @@ func checkComparisonOp(tname string, expected Operation, actual Operation) error
|
||||
if cmp.cop != expectedCmp.cop {
|
||||
return fmt.Errorf("expected comparison operator to be %v for %s, got %v", expectedCmp.cop, tname, cmp.cop)
|
||||
}
|
||||
if !cmp.data.Equal(expectedCmp.data) {
|
||||
if !cmp.data.equal(expectedCmp.data) {
|
||||
return fmt.Errorf("expected data to be %v for %s, got %v", expectedCmp.data, tname, cmp.data)
|
||||
}
|
||||
return nil
|
||||
@@ -442,11 +442,11 @@ func TestInterpretRule(t *testing.T) {
|
||||
for i, op := range rule.ops {
|
||||
testOp := test.expected.ops[i]
|
||||
switch testOp.(type) {
|
||||
case *Immediate:
|
||||
case *immediate:
|
||||
if err := checkImmediateOp(test.tname, testOp, op); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
case *Comparison:
|
||||
case *comparison:
|
||||
if err := checkComparisonOp(test.tname, testOp, op); err != nil {
|
||||
t.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user