func (mae *MockACLEngine) GetNumOfACLChanges() int {
	return mae.aclConfig.changes
}
GetNumOfACLChanges returns the number of ACL changes (Put+Delete).
package aclengine
import (
	"errors"
	"fmt"
	"net"
	"strings"
	"sync"
	"go.ligato.io/cn-infra/v2/logging"
	"github.com/contiv/vpp/mock/localclient"
	"github.com/contiv/vpp/plugins/ipnet"
	podmodel "github.com/contiv/vpp/plugins/ksr/model/pod"
	"github.com/contiv/vpp/plugins/policy/renderer"
	"go.ligato.io/cn-infra/v2/datasync/syncbase"
	vpp_acl "go.ligato.io/vpp-agent/v3/proto/ligato/vpp/acl"
)
const maxPortNum = uint32(^uint16(0))
type ConnectionAction int
const (
	ConnActionDenySyn ConnectionAction = iota
	ConnActionDenySynAck
	ConnActionAllow
	ConnActionFailure
)
type ACLAction int
const (
	ACLActionDeny ACLAction = iota
	ACLActionPermit
	ACLActionReflect
	ACLActionFailure
)
const aclPrefix = "config/vpp/acls/v2/acl/"
type MockACLEngine struct {
	sync.Mutex
	Log        logging.Logger
	IPNet      ipnet.API      
	ContivConf ContivConfAPI  
	pods      map[podmodel.ID]*PodConfig
	aclConfig *ACLConfig
}
type PodConfig struct {
	podIP       net.IP
	anotherNode bool
}
type ACLConfig struct {
	byName  map[string]*vpp_acl.ACL
	byIf    map[string]*InterfaceACLs
	changes int
}
type InterfaceACLs struct {
	inbound  *vpp_acl.ACL
	outbound *vpp_acl.ACL
}
func NewMockACLEngine(log logging.Logger, ipNet ipnet.API, contivConf ContivConfAPI) *MockACLEngine {
	return &MockACLEngine{
		Log:        log,
		IPNet:      ipNet,
		ContivConf: contivConf,
		pods:       make(map[podmodel.ID]*PodConfig),
		aclConfig:  NewACLConfig(),
	}
}
func NewACLConfig() *ACLConfig {
	return &ACLConfig{
		byName: make(map[string]*vpp_acl.ACL),
		byIf:   make(map[string]*InterfaceACLs),
	}
}
type ContivConfAPI interface {
	GetMainInterfaceName() string
}
func (mae *MockACLEngine) ClearACLs() {
	changes := mae.aclConfig.changes
	mae.aclConfig = NewACLConfig()
	mae.aclConfig.changes = changes
}
func (mae *MockACLEngine) RegisterPod(pod podmodel.ID, podIP string, anotherNode bool) {
	mae.Lock()
	defer mae.Unlock()
	mae.pods[pod] = &PodConfig{podIP: net.ParseIP(podIP), anotherNode: anotherNode}
}
func (mae *MockACLEngine) ApplyTxn(txn *localclient.Txn, latestRevs *syncbase.PrevRevisions) error {
	mae.Lock()
	defer mae.Unlock()
	if txn == nil {
		return errors.New("txn is nil")
	}
	if txn.VPPDataChangeTxn != nil || txn.VPPDataResyncTxn != nil {
		return errors.New("vpp txn is not supported")
	}
	if txn.LinuxDataResyncTxn != nil {
		mae.ClearACLs()
		for key, value := range txn.LinuxDataResyncTxn.Values {
			if !strings.HasPrefix(key, aclPrefix) {
				return errors.New("non-ACL changed in txn")
			}
			acl, isACL := value.(*vpp_acl.ACL)
			if !isACL {
				return errors.New("failed to cast ACL value")
			}
			err := mae.aclConfig.PutACL(acl)
			if err != nil {
				return err
			}
		}
		return nil
	}
	if txn.LinuxDataChangeTxn == nil {
		return errors.New("linux data change txn is nil")
	}
	dataChange := txn.LinuxDataChangeTxn
	for key, value := range dataChange.Values {
		if !strings.HasPrefix(key, aclPrefix) {
			return errors.New("non-ACL changed in txn")
		}
		aclName := strings.TrimPrefix(key, aclPrefix)
		if value != nil {
			acl, isACL := value.(*vpp_acl.ACL)
			if !isACL {
				return errors.New("failed to cast ACL value")
			}
			err := mae.aclConfig.PutACL(acl)
			if err != nil {
				return err
			}
		} else {
			err := mae.aclConfig.DelACL(aclName)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
func (mae *MockACLEngine) DumpACLs() (acls []*vpp_acl.ACL) {
	for _, acl := range mae.aclConfig.byName {
		acls = append(acls, acl)
	}
	return acls
}
func (mae *MockACLEngine) GetNumOfACLs() int {
	return len(mae.aclConfig.byName)
}
func (mae *MockACLEngine) GetInboundACL(ifName string) *vpp_acl.ACL {
	acls := mae.aclConfig.GetACLs(ifName)
	return acls.inbound
}
func (mae *MockACLEngine) GetOutboundACL(ifName string) *vpp_acl.ACL {
	acls := mae.aclConfig.GetACLs(ifName)
	return acls.outbound
}
func (mae *MockACLEngine) GetACLByName(aclName string) *vpp_acl.ACL {
	acl, has := mae.aclConfig.byName[aclName]
	if !has {
		return nil
	}
	return acl
}