fix: ipv6 compatibility issues fixes 20250809 (#23061)

Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
Jian Qiu
2025-08-10 10:07:50 +08:00
committed by GitHub
co-authored by Qiu Jian
parent 4eb90fc442
commit b7870e0453
18 changed files with 135 additions and 52 deletions
+2 -2
View File
@@ -96,12 +96,12 @@ require (
k8s.io/cri-api v0.22.17
k8s.io/klog/v2 v2.20.0
moul.io/http2curl/v2 v2.3.0
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806100640-5372b7ebd1a4
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250807082423-7edaa2517e8e
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0
yunion.io/x/jsonutils v1.0.1-0.20250507052344-1abcf4f443b1
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9
yunion.io/x/pkg v1.10.4-0.20250810004221-0a408931e156
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0
yunion.io/x/structarg v0.0.0-20231017124457-df4d5009457c
+4 -4
View File
@@ -1408,8 +1408,8 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806100640-5372b7ebd1a4 h1:4/tNKXpaHh0CHG3jt/vFIGIlbHMZ0ceK1iPMvSzwYCU=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806100640-5372b7ebd1a4/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250807082423-7edaa2517e8e h1:ShOTidpZjZKTiIeFEXi0TXA/7j7FB95FiiF09nM1tQ8=
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250807082423-7edaa2517e8e/go.mod h1:FXxAEbdNfWXX9gjME3K2nJhkydHY5EKEUZb+RLEzVwQ=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0 h1:msG4SiDSVU7CrXH06WuHlNEZXIooTcmNbfrIGHuIHBU=
yunion.io/x/executor v0.0.0-20250518005516-5402e9e0bed0/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
@@ -1423,8 +1423,8 @@ yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900 h1:Hu/4ERvoWaN6aiFs4h4/yvVB
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900/go.mod h1:0vLkNEhlmA64HViPBAnSTUMrx5QP1CLsxXmxDKQ80tc=
yunion.io/x/pkg v0.0.0-20190620104149-945c25821dbf/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v0.0.0-20190628082551-f4033ba2ea30/go.mod h1:t6rEGG2sQ4J7DhFxSZVOTjNd0YO/KlfWQyK1W4tog+E=
yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9 h1:8NuoKUPb3sHigChE6Mz6Nf9aZvM/TvORueIZAMYfPK0=
yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/pkg v1.10.4-0.20250810004221-0a408931e156 h1:ONxzK7UJhLKrDUM7vH6EQPNhwkCXaWDtmC67fF12/RE=
yunion.io/x/pkg v1.10.4-0.20250810004221-0a408931e156/go.mod h1:0Bwxqd9MA3ACi119/l02FprY/o9gHahmYC2bsSbnVpM=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1 h1:1KJ3YYinydPHpDEQRXdr/T8SYcKZ5Er+m489H+PnaQ4=
yunion.io/x/s3cli v0.0.0-20241221171442-1c11599d28e1/go.mod h1:0iFKpOs1y4lbCxeOmq3Xx/0AcQoewVPwj62eRluioEo=
yunion.io/x/sqlchemy v1.1.3-0.20250806073422-e37f5197cec0 h1:Eha/ywh4foMJm7VJ8ibFOi+WPHacuTWtosAGpOld5vo=
+10
View File
@@ -36,6 +36,14 @@ type GuestnetworkDetails struct {
EipAddr string `json:"eip_addr"`
NetworkAddresses []NetworkAddrConf `json:"network_addresses"`
GuestIpMask int8 `json:"guest_ip_mask"`
// 网关地址
GuestGateway string `json:"guest_gateway"`
GuestIp6Mask uint8 `json:"guest_ip6_mask"`
// 网关地址
GuestGateway6 string `json:"guest_gateway6"`
}
type GuestnetworkShortDesc struct {
@@ -58,6 +66,8 @@ type GuestnetworkShortDesc struct {
SubIps string `json:"sub_ips"`
// 端口映射
PortMappings GuestPortMappings `json:"port_mappings"`
IsDefault bool `json:"is_default"`
}
type GuestnetworkListInput struct {
+1 -1
View File
@@ -120,7 +120,7 @@ func (w *Worker) initProxyAgent_(ctx context.Context) error {
)
if agentDetail.BindAddr == "" || !bindAddrExist(bindAddr) {
var err error
bindAddr, err = netutils2.MyIP()
bindAddr, err = netutils2.MyIPSmart()
if err != nil {
return errors.Wrap(err, "find bind Addr")
}
+2
View File
@@ -571,6 +571,8 @@ func fetchGuestNICs(ctx context.Context, guestIds []string, virtual tristate.Tri
gnwq.Field("port_mappings"),
gnwq.Field("is_default"),
wirq.Field("vpc_id"),
subIP.Field("sub_ips"),
)
+5 -1
View File
@@ -175,6 +175,10 @@ func (manager *SGuestnetworkManager) FetchCustomizeColumns(
if net, ok := netMap[netIds[i]]; ok {
rows[i].Network = net.Name
rows[i].WireId = net.WireId
rows[i].GuestIpMask = net.GuestIpMask
rows[i].GuestGateway = net.GuestGateway
rows[i].GuestIp6Mask = net.GuestIp6Mask
rows[i].GuestGateway6 = net.GuestGateway6
}
}
@@ -408,7 +412,7 @@ func (manager *SGuestnetworkManager) newGuestNetwork(
}
}
if vpc.Id != api.DEFAULT_VPC_ID && provider == api.CLOUD_PROVIDER_ONECLOUD && len(gn.IpAddr) > 0 || len(gn.Ip6Addr) > 0 {
if vpc.Id != api.DEFAULT_VPC_ID && provider == api.CLOUD_PROVIDER_ONECLOUD && (len(gn.IpAddr) > 0 || len(gn.Ip6Addr) > 0) {
var err error
GuestnetworkManager.lockAllocMappedAddr(ctx)
defer GuestnetworkManager.unlockAllocMappedAddr(ctx)
+69 -21
View File
@@ -3294,13 +3294,37 @@ func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, use
if len(input.Ip) == 0 {
return nil, httperrors.NewMissingParameterError("ip")
}
ipV4, err := netutils.NewIPV4Addr(input.Ip)
if err != nil {
return nil, httperrors.NewInputParameterError("ip")
}
var ipV4, ipV4NetAddr netutils.IPV4Addr
var ipV6, ipV6NetAddr netutils.IPV6Addr
var err error
if input.Mask == 0 {
return nil, httperrors.NewMissingParameterError("mask")
}
if regutils.MatchIP4Addr(input.Ip) {
ipV4, err = netutils.NewIPV4Addr(input.Ip)
if err != nil {
return nil, errors.Wrapf(err, "invalid ipv4 address %s", input.Ip)
}
if ipV4.IsZero() {
return nil, errors.Wrapf(errors.ErrInvalidFormat, "invalid ipv4 address %s", input.Ip)
}
ipV4NetAddr = ipV4.NetAddr(int8(input.Mask))
} else if regutils.MatchIP6Addr(input.Ip) {
ipV6, err = netutils.NewIPV6Addr(input.Ip)
if err != nil {
return nil, errors.Wrapf(err, "invalid ipv6 address %s", input.Ip)
}
if ipV6.IsZero() {
return nil, errors.Wrapf(errors.ErrInvalidFormat, "invalid ipv6 address %s", input.Ip)
}
ipV6NetAddr = ipV6.NetAddr(uint8(input.Mask))
} else {
return nil, errors.Wrapf(errors.ErrInvalidFormat, "invalid ip address %s", input.Ip)
}
if len(input.ServerType) == 0 {
return nil, httperrors.NewMissingParameterError("server_type")
}
@@ -3312,12 +3336,16 @@ func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, use
}
var (
ipV4NetAddr = ipV4.NetAddr(int8(input.Mask))
nm *SNetwork
matched bool
nm *SNetwork
matched bool
)
q := NetworkManager.Query().Equals("server_type", input.ServerType).Equals("guest_ip_mask", input.Mask)
q := NetworkManager.Query().Equals("server_type", input.ServerType)
if !ipV4.IsZero() {
q = q.Equals("guest_ip_mask", input.Mask)
} else if !ipV6.IsZero() {
q = q.Equals("guest_ip6_mask", input.Mask)
}
listQuery := api.NetworkListInput{}
err = query.Unmarshal(&listQuery)
@@ -3350,14 +3378,27 @@ func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, use
return nil, err
}
n := item.(*SNetwork)
if n.GetIPRange().Contains(ipV4) {
nm = n
matched = true
break
} else if nIpV4, _ := netutils.NewIPV4Addr(n.GuestIpStart); nIpV4.NetAddr(n.GuestIpMask) == ipV4NetAddr {
nm = n
matched = false
break
if !ipV4.IsZero() {
if n.getIPRange().Contains(ipV4) {
nm = n
matched = true
break
} else if nIpV4, _ := netutils.NewIPV4Addr(n.GuestIpStart); nIpV4.NetAddr(n.GuestIpMask) == ipV4NetAddr {
nm = n
matched = false
break
}
} else if !ipV6.IsZero() {
if n.getIPRange6().Contains(ipV6) {
nm = n
matched = true
break
} else if nIpV6, _ := netutils.NewIPV6Addr(n.GuestIp6Start); nIpV6.NetAddr(n.GuestIp6Mask) == ipV6NetAddr {
nm = n
matched = false
break
}
}
}
@@ -3369,13 +3410,20 @@ func (manager *SNetworkManager) PerformTryCreateNetwork(ctx context.Context, use
ret.Set("find_matched", jsonutils.JSONTrue)
ret.Set("wire_id", jsonutils.NewString(nm.WireId))
if !matched {
log.Infof("Find same subnet network %s %s/%d", nm.Name, nm.GuestGateway, nm.GuestIpMask)
log.Infof("Find same subnet network %s %s/%d %s/%d", nm.Name, nm.GuestGateway, nm.GuestIpMask, nm.GuestGateway6, nm.GuestIp6Mask)
newNetwork := new(SNetwork)
newNetwork.SetModelManager(NetworkManager, newNetwork)
newNetwork.GuestIpStart = input.Ip
newNetwork.GuestIpEnd = input.Ip
newNetwork.GuestGateway = nm.GuestGateway
newNetwork.GuestIpMask = int8(input.Mask)
if !ipV4.IsZero() {
newNetwork.GuestIpStart = ipV4.String()
newNetwork.GuestIpEnd = ipV4.String()
newNetwork.GuestGateway = nm.GuestGateway
newNetwork.GuestIpMask = int8(input.Mask)
} else if !ipV6.IsZero() {
newNetwork.GuestIp6Start = ipV6.String()
newNetwork.GuestIp6End = ipV6.String()
newNetwork.GuestGateway6 = nm.GuestGateway6
newNetwork.GuestIp6Mask = uint8(input.Mask)
}
newNetwork.GuestDns = nm.GuestDns
newNetwork.GuestDhcp = nm.GuestDhcp
newNetwork.GuestNtp = nm.GuestNtp
+2 -2
View File
@@ -997,8 +997,8 @@ func (manager *SVpcManager) ValidateCreateData(
return input, err
}
if region.GetDriver().IsVpcCreateNeedInputCidr() && len(input.CidrBlock) == 0 {
return input, httperrors.NewMissingParameterError("cidr")
if region.GetDriver().IsVpcCreateNeedInputCidr() && len(input.CidrBlock) == 0 && len(input.CidrBlock6) == 0 {
return input, httperrors.NewMissingParameterError("cidr_block or cidr_block6")
}
keys := GetVpcQuotaKeysFromCreateInput(ownerId, input)
+8 -1
View File
@@ -20,6 +20,7 @@ import (
"fmt"
"sort"
"strconv"
"strings"
"yunion.io/x/cloudmux/pkg/cloudprovider"
"yunion.io/x/jsonutils"
@@ -517,9 +518,15 @@ func (self *SKVMRegionDriver) RequestDeleteLoadbalancerListenerRule(ctx context.
}
func (self *SKVMRegionDriver) ValidateCreateVpcData(ctx context.Context, userCred mcclient.TokenCredential, input api.VpcCreateInput) (api.VpcCreateInput, error) {
if !utils.IsInStringArray(input.CidrBlock, []string{"192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12"}) {
if len(input.CidrBlock) > 0 && !utils.IsInStringArray(input.CidrBlock, []string{"192.168.0.0/16", "10.0.0.0/8", "172.16.0.0/12"}) {
return input, httperrors.NewInputParameterError("Invalid cidr_block, want 192.168.0.0/16|10.0.0.0/8|172.16.0.0/12, got %s", input.CidrBlock)
}
if len(input.CidrBlock6) > 0 {
input.CidrBlock6 = strings.ToLower(input.CidrBlock6)
if !strings.HasPrefix(input.CidrBlock6, "fd") {
return input, httperrors.NewInputParameterError("Invalid ipv6 cidr_block, %s outside of IPv6 private unicast address range fd00::/8", input.CidrBlock6)
}
}
return input, nil
}
@@ -344,12 +344,12 @@ func (d *SBaseBridgeDriver) ConfirmToConfig() (bool, string, error) {
if d.bridge.Addr != d.ip {
return false, "", fmt.Errorf("bridge %s IP %s is not expected IP %s, mismatch", d.bridge, d.bridge.Addr, d.ip)
}
} else if len(d.ip6) == 0 {
} else {
if d.inter != nil && len(d.inter.Addr) > 0 {
return false, "", fmt.Errorf("interface %s should have no address", d.inter)
}
if len(d.bridge.Addr) == 0 {
return false, "", fmt.Errorf("bridge %s should have 169.254.0.0/16 address", d.bridge)
if len(d.bridge.Addr) > 0 {
return false, "", fmt.Errorf("bridge %s (%s) should have no ipv4 address", d.bridge, d.bridge.Addr)
}
if !d.bridge.IsSecretInterface() {
return false, "", fmt.Errorf("%s should have address in 169.254.0.0/16", d.bridge)
@@ -113,9 +113,9 @@ func (s *SGuestDHCP6Server) sendRouterAdvertisement(solicitation *icmp6.SRouterS
gwMac := gwMacObj.(net.HardwareAddr)
pref := icmp6.PreferenceMedium
//if conf.IsDefaultGW {
// pref = icmp6.PreferenceHigh
//}
if conf.IsDefaultGW {
pref = icmp6.PreferenceHigh
}
_, ipnet, err := net.ParseCIDR(fmt.Sprintf("%s/%d", conf.ClientIP6, conf.PrefixLen6))
if err != nil {
+1 -1
View File
@@ -308,7 +308,7 @@ func (h *ApiHelper) agentUpdateSeen(ctx context.Context) *computemodels.SLoadbal
}
func (h *ApiHelper) newAgentHbParams(ctx context.Context) (*jsonutils.JSONDict, error) {
ip, err := netutils2.MyIP()
ip, err := netutils2.MyIPSmart()
if err != nil {
return nil, err
}
+7 -8
View File
@@ -18,7 +18,6 @@ import (
"bytes"
"fmt"
"net"
"reflect"
"strconv"
"strings"
"time"
@@ -447,6 +446,7 @@ type SNetInterface struct {
Addr6 string
Mask6 net.IPMask
Addr4LinkLocal string
Addr6LinkLocal string
Mtu int
@@ -520,10 +520,9 @@ func (n *SNetInterface) FetchConfig2(expectIp string, expectIp6 string) {
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
if len(expectIp) == 0 && n.Addr == "" && strings.HasPrefix(ipnet.IP.To4().String(), SECRET_PREFIX) {
continue
}
if (len(expectIp) > 0 && ipnet.IP.String() == expectIp) || (len(expectIp) == 0 && n.Addr == "") {
if strings.HasPrefix(ipnet.IP.To4().String(), SECRET_PREFIX) {
n.Addr4LinkLocal = ipnet.IP.String()
} else if (len(expectIp) > 0 && ipnet.IP.String() == expectIp) || (len(expectIp) == 0 && n.Addr == "") {
n.Addr = ipnet.IP.String()
n.Mask = ipnet.Mask
}
@@ -603,21 +602,21 @@ func (n *SNetInterface) SetupGso(on bool) {
}
func (n *SNetInterface) IsSecretInterface() bool {
return n.IsSecretAddress(n.Addr, n.Mask)
return n.Addr4LinkLocal != "" && n.Addr == ""
}
func (n *SNetInterface) IsSecretInterface6() bool {
return n.Addr6LinkLocal != "" && n.Addr6 == ""
}
func (n *SNetInterface) IsSecretAddress(addr string, mask []byte) bool {
/*func (n *SNetInterface) IsSecretAddress(addr string, mask []byte) bool {
log.Infof("MASK --- %s", mask)
if reflect.DeepEqual(mask, SECRET_MASK) && strings.HasPrefix(addr, SECRET_PREFIX) {
return true
} else {
return false
}
}
}*/
func GetSecretInterfaceAddress() (string, int) {
addr := fmt.Sprintf("%s.%d.1", SECRET_PREFIX, secretInterfaceIndex)
+1
View File
@@ -122,6 +122,7 @@ func (w *Worker) run(ctx context.Context, mss *agentmodels.ModelSets) (err error
} else {
dbUrl = db
}
log.Infof("ovn: connect to ovn north database %s", dbUrl)
ovnnbctl := ovnutil.NewOvnNbCtl(dbUrl)
ovndb, err := DumpOVNNorthbound(ctx, ovnnbctl)
+2 -2
View File
@@ -1852,7 +1852,7 @@ sigs.k8s.io/structured-merge-diff/v4/value
# sigs.k8s.io/yaml v1.2.0
## explicit; go 1.12
sigs.k8s.io/yaml
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250806100640-5372b7ebd1a4
# yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20250807082423-7edaa2517e8e
## explicit; go 1.21
yunion.io/x/cloudmux/pkg/apis
yunion.io/x/cloudmux/pkg/apis/billing
@@ -1949,7 +1949,7 @@ yunion.io/x/log/hooks
yunion.io/x/ovsdb/cli_util
yunion.io/x/ovsdb/schema/ovn_nb
yunion.io/x/ovsdb/types
# yunion.io/x/pkg v1.10.4-0.20250805171825-2431e10f90a9
# yunion.io/x/pkg v1.10.4-0.20250810004221-0a408931e156
## explicit; go 1.18
yunion.io/x/pkg/appctx
yunion.io/x/pkg/errors
+2 -3
View File
@@ -682,12 +682,11 @@ func (svm *SVirtualMachine) doUnregister(ctx context.Context) error {
}
func (svm *SVirtualMachine) DeleteVM(ctx context.Context) error {
err := svm.CheckFileInfo(ctx)
err := svm.doDestroy(ctx)
if err != nil {
log.Errorf("CheckFileInfo %s error: %v", svm.GetName(), err)
return svm.doUnregister(ctx)
}
return svm.doDestroy(ctx)
return nil
}
func (svm *SVirtualMachine) doDetachAndDeleteDisk(ctx context.Context, vdisk *SVirtualDisk) error {
+9
View File
@@ -363,6 +363,15 @@ func (addr IPV6Addr) Ge(addr2 IPV6Addr) bool {
return !addr.Lt(addr2)
}
func (addr IPV6Addr) IsZero() bool {
for _, v := range addr {
if v != 0 {
return false
}
}
return true
}
type IPV6AddrRange struct {
start IPV6Addr
end IPV6Addr
+4
View File
@@ -139,6 +139,10 @@ func (addr IPV4Addr) ToMac(prefix string) string {
return fmt.Sprintf("%s%02x:%02x:%02x:%02x", prefix, bytes[0], bytes[1], bytes[2], bytes[3])
}
func (addr IPV4Addr) IsZero() bool {
return addr == 0
}
type IPV4AddrRange struct {
start IPV4Addr
end IPV4Addr