func FoundRoutes(expected *netlink.Route) ([]netlink.Route, error) {
	family := NetlinkFamily(expected.Dst.IP)
	routeFilter := netlink.RT_FILTER_DST
	if expected.Dst == nil {
		return nil, fmt.Errorf("dst in route expect not nil")
	}
	find := *expected
	if find.Dst.String() == "::/0" || find.Dst.String() == "0.0.0.0/0" {
		find.Dst = nil
	}
	if find.LinkIndex > 0 {
		routeFilter = routeFilter | netlink.RT_FILTER_OIF
	}
	if find.Scope > 0 {
		routeFilter = routeFilter | netlink.RT_FILTER_SCOPE
	}
	if find.Gw != nil {
		routeFilter = routeFilter | netlink.RT_FILTER_GW
	}
	if find.Table > 0 {
		routeFilter = routeFilter | netlink.RT_FILTER_TABLE
	}
	return netlink.RouteListFiltered(family, &find, routeFilter)
}
FoundRoutes look up routes
package driver
import (
	"bytes"
	"encoding/json"
	"fmt"
	"net"
	"os"
	"syscall"
	"time"
	"github.com/pkg/errors"
	terwayIP "github.com/AliyunContainerService/terway/pkg/ip"
	terwaySysctl "github.com/AliyunContainerService/terway/pkg/sysctl"
	terwayTypes "github.com/AliyunContainerService/terway/types"
	"github.com/sirupsen/logrus"
	"github.com/vishvananda/netlink"
	"golang.org/x/sys/unix"
	k8snet "k8s.io/apimachinery/pkg/util/net"
	"k8s.io/apimachinery/pkg/util/wait"
)
const (
	fileLockTimeOut = 11 * time.Second
)
var Log = DefaultLogger.WithField("subSys", "terway-cni")
var DefaultLogger = NewDefaultLogger()
var Hook = &PodInfoHook{ExtraInfo: make(map[string]string)}
func NewDefaultLogger() *logrus.Logger {
	logger := logrus.New()
	logger.Formatter = &logrus.TextFormatter{
		DisableTimestamp: true,
		DisableColors:    true,
		DisableQuote:     true,
	}
	logger.SetLevel(logrus.InfoLevel)
	logger.AddHook(Hook)
	return logger
}
type PodInfoHook struct {
	ExtraInfo map[string]string
}
func (p *PodInfoHook) Levels() []logrus.Level {
	return logrus.AllLevels
}
func (p *PodInfoHook) Fire(e *logrus.Entry) error {
	for k, v := range p.ExtraInfo {
		e.Data[k] = v
	}
	return nil
}
func (p *PodInfoHook) AddExtraInfo(k, v string) {
	p.ExtraInfo[k] = v
}
func (p *PodInfoHook) AddExtraInfos(e map[string]string) {
	for k, v := range e {
		p.ExtraInfo[k] = v
	}
}
func SetLogDebug() {
	DefaultLogger.SetLevel(logrus.DebugLevel)
	logrus.SetOutput(os.Stderr)
}
func JSONStr(v interface{}) string {
	b, err := json.Marshal(v)
	if err != nil {
		return ""
	}
	return string(b)
}
type Locker struct {
	FD *os.File
}
func (l *Locker) Close() error {
	if l.FD != nil {
		return l.FD.Close()
	}
	return nil
}
func GrabFileLock(lockfilePath string) (*Locker, error) {
	var success bool
	var err error
	l := &Locker{}
	defer func(l *Locker) {
		if !success {
			_ = l.Close()
		}
	}(l)
	l.FD, err = os.OpenFile(lockfilePath, os.O_CREATE, 0600)
	if err != nil {
		return nil, fmt.Errorf("failed to open lock %s: %v", lockfilePath, err)
	}
	if err := wait.PollImmediate(200*time.Millisecond, fileLockTimeOut, func() (bool, error) {
		if err := grabFileLock(l.FD); err != nil {
			return false, nil
		}
		return true, nil
	}); err != nil {
		return nil, fmt.Errorf("failed to acquire new iptables lock: %v", err)
	}
	success = true
	return l, nil
}
func grabFileLock(f *os.File) error {
	return unix.Flock(int(f.Fd()), unix.LOCK_EX|unix.LOCK_NB)
}
func getRouteTableID(linkIndex int) int {
	return 1000 + linkIndex
}
func EnsureHostNsConfig(ipv4, ipv6 bool) error {
	for _, key := range []string{"default", "all"} {
		for _, cfg := range ipv4NetConfig {
			err := terwaySysctl.EnsureConf(fmt.Sprintf(cfg[0], key), cfg[1])
			if err != nil {
				return err
			}
		}
	}
	return EnsureNetConfSet(ipv4, ipv6)
}
func EnsureLinkUp(link netlink.Link) (bool, error) {
	if link.Attrs().Flags&net.FlagUp != 0 {
		return false, nil
	}
	return true, LinkSetUp(link)
}
func EnsureLinkMTU(link netlink.Link, mtu int) (bool, error) {
	if link.Attrs().MTU == mtu {
		return false, nil
	}
	return true, LinkSetMTU(link, mtu)
}
func EnsureLinkName(link netlink.Link, name string) (bool, error) {
	if link.Attrs().Name == name {
		return false, nil
	}
	return true, LinkSetName(link, name)
}
func EnsureAddrWithPrefix(link netlink.Link, ipNetSet *terwayTypes.IPNetSet, prefixRoute bool) (bool, error) {
	var changed bool
	if ipNetSet.IPv4 != nil {
		newAddr := &netlink.Addr{IPNet: ipNetSet.IPv4}
		if !prefixRoute {
			newAddr.Flags = unix.IFA_F_NOPREFIXROUTE
		}
		c, err := EnsureAddr(link, newAddr)
		if err != nil {
			return c, err
		}
		if c {
			changed = true
		}
	}
	if ipNetSet.IPv6 != nil {
		newAddr := &netlink.Addr{IPNet: ipNetSet.IPv6}
		if !prefixRoute {
			newAddr.Flags = unix.IFA_F_NOPREFIXROUTE
		}
		c, err := EnsureAddr(link, newAddr)
		if err != nil {
			return c, err
		}
		if c {
			changed = true
		}
	}
	return changed, nil
}
func EnsureAddr(link netlink.Link, expect *netlink.Addr) (bool, error) {
	var changed bool
	addrList, err := netlink.AddrList(link, NetlinkFamily(expect.IP))
	if err != nil {
		return false, fmt.Errorf("error list address from if %s, %w", link.Attrs().Name, err)
	}
	found := false
	for _, addr := range addrList {
		if !addr.IP.IsGlobalUnicast() {
			continue
		}
		if (addr.IPNet.String() == expect.IPNet.String()) && (addr.Scope == expect.Scope) {
			found = true
			continue
		}
		err := AddrDel(link, &addr)
		if err != nil {
			return false, err
		}
		changed = true
	}
	if found {
		return changed, nil
	}
	return true, AddrReplace(link, expect)
}