func (ms MapSorter) SortInDescendingOrder() {
	eniLog.Debugf("before sorting, slice = %+v", ms)
	sort.Slice(ms, func(i, j int) bool {
		return ms[i].Val > ms[j].Val
	})
	eniLog.Debugf("after sorting, slice = %+v", ms)
}
SortInDescendingOrder is a bubble sort per element's value
package daemon
import (
	"context"
	"fmt"
	"math/rand"
	"sort"
	"strings"
	"sync"
	"time"
	"github.com/AliyunContainerService/terway/deviceplugin"
	"github.com/AliyunContainerService/terway/pkg/aliyun"
	"github.com/AliyunContainerService/terway/pkg/ipam"
	"github.com/AliyunContainerService/terway/pkg/logger"
	"github.com/AliyunContainerService/terway/pkg/pool"
	"github.com/AliyunContainerService/terway/pkg/tracing"
	"github.com/AliyunContainerService/terway/types"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/vpc"
	"github.com/pkg/errors"
	corev1 "k8s.io/api/core/v1"
)
var eniLog = logger.DefaultLogger
const (
	vSwitchIPCntTimeout = 10 * time.Minute
	typeNameENI    = "eni"
	poolNameENI    = "eni"
	factoryNameENI = "eni"
	tracingKeyVSwitches              = "vswitches"
	tracingKeyVSwitchSelectionPolicy = "vswitch_selection_policy"
	tracingKeyCacheExpireAt          = "cache_expire_at"
)
type eniResourceManager struct {
	pool pool.ObjectPool
	ecs  ipam.API
}
func newENIResourceManager(poolConfig *types.PoolConfig, ecs ipam.API, allocatedResources map[string]resourceManagerInitItem, ipFamily *types.IPFamily) (ResourceManager, error) {
	eniLog.Debugf("new ENI Resource Manager, pool config: %+v, allocated resources: %+v", poolConfig, allocatedResources)
	factory, err := newENIFactory(poolConfig, ecs)
	if err != nil {
		return nil, errors.Wrapf(err, "error create ENI factory")
	}
	_ = tracing.Register(tracing.ResourceTypeFactory, factoryNameENI, factory)
	limit, ok := aliyun.GetLimit(aliyun.GetInstanceMeta().InstanceType)
	if !ok {
		return nil, errors.Wrapf(err, "error get max eni for eni factory")
	}
	capacity := limit.Adapters
	capacity = int(float64(capacity)*poolConfig.EniCapRatio) + poolConfig.EniCapShift - 1
	if poolConfig.MaxENI != 0 && poolConfig.MaxENI < capacity {
		capacity = poolConfig.MaxENI
	}
	if poolConfig.MaxPoolSize > capacity {
		poolConfig.MaxPoolSize = capacity
	}
	if poolConfig.MinENI != 0 {
		poolConfig.MinPoolSize = poolConfig.MinENI
	}
	poolCfg := pool.Config{
		Name:     poolNameENI,
		Type:     typeNameENI,
		MaxIdle:  poolConfig.MaxPoolSize,
		MinIdle:  poolConfig.MinPoolSize,
		Capacity: capacity,
		Factory:  factory,
		Initializer: func(holder pool.ResourceHolder) error {
			ctx := context.Background()
			enis, err := ecs.GetAttachedENIs(ctx, false)
			if err != nil {
				return fmt.Errorf("error get attach ENI on pool init, %w", err)
			}
			for _, e := range enis {
				if ipFamily.IPv6 {
					_, ipv6, err := ecs.GetENIIPs(ctx, e.MAC)
					if err != nil || len(ipv6) == 0 {
						return errors.Wrapf(err, "error get eni ip")
					}
					e.PrimaryIP.IPv6 = ipv6[0]
				}
				if item, ok := allocatedResources[e.GetResourceID()]; ok {
					holder.AddInuse(e, podInfoKey(item.podInfo.Namespace, item.podInfo.Name))
				} else {
					holder.AddIdle(e)
				}
			}
			return nil
		},
	}
	dp := deviceplugin.NewENIDevicePlugin(capacity, deviceplugin.ENITypeENI)
	err = dp.Serve()
	if err != nil {
		return nil, errors.Wrapf(err, "error set deviceplugin on node")
	}
	p, err := pool.NewSimpleObjectPool(poolCfg)
	if err != nil {
		return nil, err
	}
	mgr := &eniResourceManager{
		pool: p,
		ecs:  ecs,
	}
	return mgr, nil
}
func (m *eniResourceManager) Allocate(ctx *networkContext, prefer string) (types.NetworkResource, error) {
	return m.pool.Acquire(ctx, prefer, podInfoKey(ctx.pod.Namespace, ctx.pod.Name))
}
func (m *eniResourceManager) Release(context *networkContext, resItem types.ResourceItem) error {
	if context != nil && context.pod != nil {
		return m.pool.ReleaseWithReservation(resItem.ID, context.pod.IPStickTime)
	}
	return m.pool.Release(resItem.ID)
}
func (m *eniResourceManager) GarbageCollection(inUseResSet map[string]types.ResourceItem, expireResSet map[string]types.ResourceItem) error {
	for expireRes, expireItem := range expireResSet {
		if _, err := m.pool.Stat(expireRes); err == nil {
			err = m.Release(nil, expireItem)
			if err != nil {
				return err
			}
		}
	}
	return nil
}
func (m *eniResourceManager) Stat(context *networkContext, resID string) (types.NetworkResource, error) {
	return m.pool.Stat(resID)
}
func (m *eniResourceManager) GetResourceMapping() (tracing.ResourcePoolStats, error) {
	return m.pool.GetResourceMapping()
}
type MapSorter []Item
type Item struct {
	Key string
	Val int
}
func newMapSorter(m map[string]int) MapSorter {
	ms := make(MapSorter, 0, len(m))
	for k, v := range m {
		ms = append(ms, Item{k, v})
	}
	return ms
}