diff --git a/conn/conn.go b/conn/conn.go index 9ef44ee..5b0b06b 100644 --- a/conn/conn.go +++ b/conn/conn.go @@ -150,22 +150,47 @@ func parseEndpoint(s string) (*net.UDPAddr, error) { return addr, err } -func LookupIP(host_port string, af int) (net.Addr, string, error) { - network := "udp" - if af == 4 { - network = "udp4" - } else if af == 6 { - network = "udp6" - } +func LookupIP(host_port string, Af int, AfPrefer int) (string, string, error) { if host_port == "" { - return nil, "", fmt.Errorf("error lookup ip from empty string") + return "", "", fmt.Errorf("error lookup ip from empty string") } - conn, err := net.Dial(network, host_port) + var conn net.Conn + var err error + var af_try_order []string + + var NetStr string + switch Af { + case 4: + af_try_order = []string{"udp4"} + case 6: + af_try_order = []string{"udp6"} + case 0: + switch AfPrefer { + case 0: + af_try_order = []string{"udp"} + case 4: + af_try_order = []string{"udp4", "udp6", "udp"} + case 6: + af_try_order = []string{"udp6", "udp4", "udp"} + default: + return "", "", fmt.Errorf("unknown address family:%v", AfPrefer) + } + default: + return "", "", fmt.Errorf("unknown address family:%v", Af) + } + for _, af := range af_try_order { + conn, err = net.Dial(af, host_port) + if err == nil { + NetStr = af + break + } + } + if err != nil { - return nil, "", err + return "", "", err } defer conn.Close() - return conn.RemoteAddr(), conn.RemoteAddr().String(), nil + return NetStr, conn.RemoteAddr().String(), nil } func ValidIP(ip net.IP) bool { diff --git a/device/peer.go b/device/peer.go index 61d0922..d089da3 100644 --- a/device/peer.go +++ b/device/peer.go @@ -21,6 +21,8 @@ import ( "gopkg.in/yaml.v2" ) +const AfPerferVal = 10000 + type endpoint_tryitem struct { URL string lastTry time.Time @@ -44,7 +46,7 @@ func NewEndpoint_trylist(peer *Peer, timeout time.Duration) *endpoint_trylist { } } -func (et *endpoint_trylist) UpdateSuper(urls mtypes.API_connurl, UseLocalIP bool) { +func (et *endpoint_trylist) UpdateSuper(urls mtypes.API_connurl, UseLocalIP bool, AfPerfer int) { et.Lock() defer et.Unlock() newmap_super := make(map[string]*endpoint_tryitem) @@ -57,7 +59,17 @@ func (et *endpoint_trylist) UpdateSuper(urls mtypes.API_connurl, UseLocalIP bool if url == "" { continue } - _, _, err := conn.LookupIP(url, 0) + addr, _, err := conn.LookupIP(url, 0, AfPerfer) + switch AfPerfer { + case 4: + if addr == "udp4" { + it = it - AfPerferVal + } + case 6: + if addr == "udp6" { + it = it - AfPerferVal + } + } if err != nil { if et.peer.device.LogLevel.LogInternal { fmt.Printf("Internal: Peer %v : Update trylist(super) %v error: %v\n", et.peer.ID.ToString(), url, err) @@ -75,7 +87,7 @@ func (et *endpoint_trylist) UpdateSuper(urls mtypes.API_connurl, UseLocalIP bool } newmap_super[url] = &endpoint_tryitem{ URL: url, - lastTry: time.Time{}.Add(mtypes.S2TD(it)), + lastTry: time.Time{}.Add(mtypes.S2TD(AfPerferVal)).Add(mtypes.S2TD(it)), firstTry: time.Time{}, } } @@ -84,7 +96,7 @@ func (et *endpoint_trylist) UpdateSuper(urls mtypes.API_connurl, UseLocalIP bool } func (et *endpoint_trylist) UpdateP2P(url string) { - _, _, err := conn.LookupIP(url, 0) + _, _, err := conn.LookupIP(url, 0, 0) if err != nil { return } @@ -462,12 +474,12 @@ func (peer *Peer) SetPSK(psk NoisePresharedKey) { peer.handshake.mutex.Unlock() } -func (peer *Peer) SetEndpointFromConnURL(connurl string, af int, static bool) error { +func (peer *Peer) SetEndpointFromConnURL(connurl string, af int, af_perfer int, static bool) error { if peer.device.LogLevel.LogInternal { fmt.Println("Internal: Set endpoint to " + connurl + " for NodeID:" + peer.ID.ToString()) } var err error - _, connurl, err = conn.LookupIP(connurl, af) + _, connurl, err = conn.LookupIP(connurl, af, af_perfer) if err != nil { return err } diff --git a/device/receivesendproc.go b/device/receivesendproc.go index cf58f45..8754d0f 100644 --- a/device/receivesendproc.go +++ b/device/receivesendproc.go @@ -492,7 +492,7 @@ func (device *Device) process_UpdatePeerMsg(peer *Peer, State_hash string) error thepeer.SetPSK(pk) } - thepeer.endpoint_trylist.UpdateSuper(*peerinfo.Connurl, !device.EdgeConfig.DynamicRoute.SuperNode.SkipLocalIP) + thepeer.endpoint_trylist.UpdateSuper(*peerinfo.Connurl, !device.EdgeConfig.DynamicRoute.SuperNode.SkipLocalIP, device.EdgeConfig.AfPrefer) if !thepeer.IsPeerAlive() { //Peer died, try to switch to this new endpoint send_signal = true @@ -765,7 +765,7 @@ func (device *Device) RoutineTryReceivedEndpoint() { if connurl == "" { continue } - err := thepeer.SetEndpointFromConnURL(connurl, thepeer.ConnAF, thepeer.StaticConn) //trying to bind first url in the list and wait ConnNextTry seconds + err := thepeer.SetEndpointFromConnURL(connurl, thepeer.ConnAF, device.EdgeConfig.AfPrefer, thepeer.StaticConn) //trying to bind first url in the list and wait ConnNextTry seconds if err != nil { device.log.Errorf("Bind " + connurl + " failed!") thepeer.endpoint_trylist.Delete(connurl) @@ -947,12 +947,12 @@ func (device *Device) RoutinePostPeerInfo(startchan <-chan struct{}) { } for _, AIP := range device.EdgeConfig.DynamicRoute.SuperNode.AdditionalLocalIP { success := false - _, ipstr, err := conn.LookupIP(AIP, 4) + _, ipstr, err := conn.LookupIP(AIP, 4, 0) if err == nil { success = true LocalV4s[ipstr] = 50 } - _, ipstr, err = conn.LookupIP(AIP, 6) + _, ipstr, err = conn.LookupIP(AIP, 6, 0) if err == nil { success = true LocalV6s[ipstr] = 50 @@ -1064,7 +1064,7 @@ func (device *Device) RoutineResetEndpoint() { if peer.IsPeerAlive() { continue } - err := peer.SetEndpointFromConnURL(peer.ConnURL, peer.ConnAF, peer.StaticConn) + err := peer.SetEndpointFromConnURL(peer.ConnURL, peer.ConnAF, device.EdgeConfig.AfPrefer, peer.StaticConn) if err != nil { device.log.Errorf("Failed to bind "+peer.ConnURL, err) continue diff --git a/example_config/super_mode/EgNet_edge001.yaml b/example_config/super_mode/EgNet_edge001.yaml index 65488c6..c6b5886 100644 --- a/example_config/super_mode/EgNet_edge001.yaml +++ b/example_config/super_mode/EgNet_edge001.yaml @@ -3,7 +3,7 @@ Interface: Name: EgNet001 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: F6:C6:D6:39 + MacAddrPrefix: FA:A7:11:D6 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -16,8 +16,9 @@ NodeName: EgNet001 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: nFleKaROzsjbtWtClWEhSXtU/chEyftua3RYEFtJmrk= +PrivKey: +KAYwkRgacUbxc52t04z8fTJBgvrkPLsisr0qJOhIUE= ListenPort: 0 +AfPrefer: 4 LogLevel: LogLevel: error LogTransit: true @@ -36,11 +37,11 @@ DynamicRoute: SaveNewPeers: true SuperNode: UseSuperNode: true - PSKey: aqGxI+K8SAV5U+v1ig4TN9JjI0FGlJgPEbB1juVIbr0= + PSKey: yl/4SNFee7+kNekajVCrK0toqXJ4mlT4IN0klyAgyqU= EndpointV4: 127.0.0.1:3456 - PubKeyV4: k90vb67heqcN2GHwY5X9kbn6owjJbbVuVB+P1DD4AEU= + PubKeyV4: 1NS6MxL2LUIlMsppJ5JfHnlofQfCxDUzaItBGwz+jBo= EndpointV6: "" - PubKeyV6: z26JJATeF3jqcjsoY+82WkrSj6xvEBGFEth5v/u3Eiw= + PubKeyV6: gSBwlJH4aUPRfSP4ZHKAnXIkPZuVaEhsLBispLYFiwo= EndpointEdgeAPIUrl: http://127.0.0.1:3456/eg_net/eg_api SkipLocalIP: false AdditionalLocalIP: [] diff --git a/example_config/super_mode/EgNet_edge002.yaml b/example_config/super_mode/EgNet_edge002.yaml index b8b0944..9d4464e 100644 --- a/example_config/super_mode/EgNet_edge002.yaml +++ b/example_config/super_mode/EgNet_edge002.yaml @@ -3,7 +3,7 @@ Interface: Name: EgNet002 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: F6:C6:D6:39 + MacAddrPrefix: FA:A7:11:D6 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -16,8 +16,9 @@ NodeName: EgNet002 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: DbtUTgAt0363z1wAAbQrQ+qd6rUf2Gw7AOlPWVBYwjw= +PrivKey: jDAolOiiRj/ju1xpVagZTtsxJSJba2rjp7J2XMc3yoM= ListenPort: 0 +AfPrefer: 4 LogLevel: LogLevel: error LogTransit: true @@ -36,11 +37,11 @@ DynamicRoute: SaveNewPeers: true SuperNode: UseSuperNode: true - PSKey: HuhEMcywAlFzvdNCGdBvNFxXMxTHE5nf1qS7njLS9o0= + PSKey: FJfjc+wRfk0FSuUkHlXl6D8xPzOKYdy3bxeYr5cpevQ= EndpointV4: 127.0.0.1:3456 - PubKeyV4: k90vb67heqcN2GHwY5X9kbn6owjJbbVuVB+P1DD4AEU= + PubKeyV4: 1NS6MxL2LUIlMsppJ5JfHnlofQfCxDUzaItBGwz+jBo= EndpointV6: "" - PubKeyV6: z26JJATeF3jqcjsoY+82WkrSj6xvEBGFEth5v/u3Eiw= + PubKeyV6: gSBwlJH4aUPRfSP4ZHKAnXIkPZuVaEhsLBispLYFiwo= EndpointEdgeAPIUrl: http://127.0.0.1:3456/eg_net/eg_api SkipLocalIP: false AdditionalLocalIP: [] diff --git a/example_config/super_mode/EgNet_edge100.yaml b/example_config/super_mode/EgNet_edge100.yaml index f6f4b2b..e5dd1e7 100644 --- a/example_config/super_mode/EgNet_edge100.yaml +++ b/example_config/super_mode/EgNet_edge100.yaml @@ -3,7 +3,7 @@ Interface: Name: EgNet100 VPPIFaceID: 1 VPPBridgeID: 4242 - MacAddrPrefix: F6:C6:D6:39 + MacAddrPrefix: FA:A7:11:D6 IPv4CIDR: 192.168.76.0/24 IPv6CIDR: fd95:71cb:a3df:e586::/64 IPv6LLPrefix: fe80::a3df:0/112 @@ -16,8 +16,9 @@ NodeName: EgNet100 PostScript: "" DefaultTTL: 200 L2FIBTimeout: 3600 -PrivKey: szziqqL7hZcd5uw4hpPdhhYtDajuuJYJIKowwCBr3Mo= +PrivKey: yNf1SkvwV8c59GmesfTNxSut6gFjYKEg9uIsE05XQUI= ListenPort: 0 +AfPrefer: 4 LogLevel: LogLevel: error LogTransit: true @@ -36,11 +37,11 @@ DynamicRoute: SaveNewPeers: true SuperNode: UseSuperNode: true - PSKey: 201zPcenuIVoQtCQHPjjw7RRjzVHSGTcgBIDeqZV1Ss= + PSKey: 5BPLK4IX3oUd4ILQct2Xc690kkKeUd4jlyeFBkO6pHA= EndpointV4: 127.0.0.1:3456 - PubKeyV4: k90vb67heqcN2GHwY5X9kbn6owjJbbVuVB+P1DD4AEU= + PubKeyV4: 1NS6MxL2LUIlMsppJ5JfHnlofQfCxDUzaItBGwz+jBo= EndpointV6: "" - PubKeyV6: z26JJATeF3jqcjsoY+82WkrSj6xvEBGFEth5v/u3Eiw= + PubKeyV6: gSBwlJH4aUPRfSP4ZHKAnXIkPZuVaEhsLBispLYFiwo= EndpointEdgeAPIUrl: http://127.0.0.1:3456/eg_net/eg_api SkipLocalIP: false AdditionalLocalIP: [] diff --git a/example_config/super_mode/EgNet_super.yaml b/example_config/super_mode/EgNet_super.yaml index 12166cd..cf14c24 100644 --- a/example_config/super_mode/EgNet_super.yaml +++ b/example_config/super_mode/EgNet_super.yaml @@ -1,7 +1,7 @@ NodeName: EgNetSP PostScript: "" -PrivKeyV4: qbvcWSMxBpXaaluU8hS4jTqPnDCD29Ndticp4GgrmfI= -PrivKeyV6: CfzKBRoBkY5qd8OnizhRCYqx1bJSU7Ql9US09bUq1UY= +PrivKeyV4: W4hrtkH+htbU3/zAbKLdFeflMSUoKLf741DONjnLk18= +PrivKeyV6: y47AY2xGs4uiUTHfMLhxooMPu/mFOezSFQ1iZ9giW7E= ListenPort: 3456 ListenPort_EdgeAPI: "3456" ListenPort_ManageAPI: "3456" @@ -38,24 +38,24 @@ ResetEndPointInterval: 600 Peers: - NodeID: 1 Name: EgNet001 - PubKey: dkjawveX+UGqcCEgThjLcgowWTY1fA89eY+mQicD3AI= - PSKey: aqGxI+K8SAV5U+v1ig4TN9JjI0FGlJgPEbB1juVIbr0= + PubKey: 6mdRv+McDgxWIq6bVB1ekxnMMWqhktzHc3JIq5bCSHI= + PSKey: yl/4SNFee7+kNekajVCrK0toqXJ4mlT4IN0klyAgyqU= AdditionalCost: 10 SkipLocalIP: false EndPoint: "" - ExternalIP: "google.com" + ExternalIP: "" - NodeID: 2 Name: EgNet002 - PubKey: iKWT8Sk+uQHB6KOSEBF7oILhkl78x1KKlE8scg4k3jc= - PSKey: HuhEMcywAlFzvdNCGdBvNFxXMxTHE5nf1qS7njLS9o0= + PubKey: Xb6eYSf4fTkFRLGVqf1sAPBXMKlWsRAbajs1mYABT0w= + PSKey: FJfjc+wRfk0FSuUkHlXl6D8xPzOKYdy3bxeYr5cpevQ= AdditionalCost: 10 SkipLocalIP: false EndPoint: "" ExternalIP: "" - NodeID: 100 Name: EgNet100 - PubKey: 7HTSE5ofjFbicCmFay8Xn5THlI9yrBLhT0gXL4t+Rws= - PSKey: 201zPcenuIVoQtCQHPjjw7RRjzVHSGTcgBIDeqZV1Ss= + PubKey: cZb8NNE1FBLy6kIUGXjdXCprUHuqzfpyXTwUxHJobnM= + PSKey: 5BPLK4IX3oUd4ILQct2Xc690kkKeUd4jlyeFBkO6pHA= AdditionalCost: 10 SkipLocalIP: false EndPoint: "" diff --git a/example_config/super_mode/gensuper.yaml b/example_config/super_mode/gensuper.yaml index c0d2da9..bb3c5f8 100644 --- a/example_config/super_mode/gensuper.yaml +++ b/example_config/super_mode/gensuper.yaml @@ -1,6 +1,6 @@ Config output dir: /tmp/eg_gen_super -ConfigTemplate for super node: "EgNet_super.yaml" -ConfigTemplate for edge node: "EgNet_edge001.yaml" +ConfigTemplate for super node: "" # "EgNet_super.yaml" +ConfigTemplate for edge node: "" # "EgNet_edge001.yaml" Network name: EgNet Super Node: Listen port: 3456 diff --git a/gencfg/example_conf.go b/gencfg/example_conf.go index d952666..64018d0 100644 --- a/gencfg/example_conf.go +++ b/gencfg/example_conf.go @@ -44,6 +44,7 @@ func GetExampleEdgeConf(templatePath string, getDemo bool) (mtypes.EdgeConfig, e L2FIBTimeout: 3600, PrivKey: "6GyDagZKhbm5WNqMiRHhkf43RlbMJ34IieTlIuvfJ1M=", ListenPort: 0, + AfPrefer: 4, LogLevel: mtypes.LoggerInfo{ LogLevel: "error", LogTransit: false, diff --git a/gencfg/gencfgNM.go b/gencfg/gencfgNM.go index a5812c0..22a6dcb 100644 --- a/gencfg/gencfgNM.go +++ b/gencfg/gencfgNM.go @@ -114,7 +114,7 @@ func GenNMCfg(NMCinfigPath string, enableP2P bool, printExample bool) (err error return fmt.Errorf("duplicate definition: NodeID %v ", NodeID) } if endpoint != "" { - _, _, err = conn.LookupIP(endpoint, 0) + _, _, err = conn.LookupIP(endpoint, 0, 0) if err != nil { return err } diff --git a/gencfg/gencfgSM.go b/gencfg/gencfgSM.go index aebbd71..1254796 100644 --- a/gencfg/gencfgSM.go +++ b/gencfg/gencfgSM.go @@ -176,7 +176,7 @@ func GenSuperCfg(SMCinfigPath string, printExample bool) (err error) { API_Prefix := SMCfg.Supernode.EdgeAPI_Prefix EndpointV4 := SMCfg.Supernode.EndpointV4 if EndpointV4 != "" { - _, _, err = conn.LookupIP(EndpointV4+":"+ListenPort, 4) + _, _, err = conn.LookupIP(EndpointV4+":"+ListenPort, 4, 0) if err != nil { return err } @@ -188,7 +188,7 @@ func GenSuperCfg(SMCinfigPath string, printExample bool) (err error) { if strings.Contains(EndpointV6, ":") && (EndpointV6[0] != '[' || EndpointV6[len(EndpointV6)-1] != ']') { return fmt.Errorf("Invalid IPv6 format, please use [%v] instead", EndpointV6) } - _, _, err = conn.LookupIP(EndpointV6+":"+ListenPort, 6) + _, _, err = conn.LookupIP(EndpointV6+":"+ListenPort, 6, 0) if err != nil { return } diff --git a/main_edge.go b/main_edge.go index f71bb48..d3ab62b 100644 --- a/main_edge.go +++ b/main_edge.go @@ -142,7 +142,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( the_device.NewPeer(pk, peerconf.NodeID, false, peerconf.PersistentKeepalive) if peerconf.EndPoint != "" { peer := the_device.LookupPeer(pk) - err = peer.SetEndpointFromConnURL(peerconf.EndPoint, 0, peerconf.Static) + err = peer.SetEndpointFromConnURL(peerconf.EndPoint, 0, econfig.AfPrefer, peerconf.Static) if err != nil { logger.Errorf("Failed to set endpoint %v: %w", peerconf.EndPoint, err) return err @@ -169,7 +169,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( return err } peer.SetPSK(psk) - err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV4, 4, true) + err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV4, 4, 0, true) if err != nil { logger.Errorf("Failed to set endpoint for supernode v4 %v: %v", econfig.DynamicRoute.SuperNode.EndpointV4, err) S4 = false @@ -190,7 +190,7 @@ func Edge(configPath string, useUAPI bool, printExample bool, bindmode string) ( return err } peer.SetPSK(psk) - err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV6, 6, true) + err = peer.SetEndpointFromConnURL(econfig.DynamicRoute.SuperNode.EndpointV6, 6, 0, true) if err != nil { logger.Errorf("Failed to set endpoint for supernode v6 %v: %v", econfig.DynamicRoute.SuperNode.EndpointV6, err) S6 = false diff --git a/main_httpserver.go b/main_httpserver.go index 4511a1c..8a3b8c0 100644 --- a/main_httpserver.go +++ b/main_httpserver.go @@ -162,7 +162,7 @@ func get_api_peers(old_State_hash string) (api_peerinfo mtypes.API_Peers, StateH if strings.Contains(connV4, ":") { hostport := strings.Split(connV4, ":") ExternalIP = ExternalIP + ":" + hostport[len(hostport)-1] - _, ExternalEndPoint_v4, err := conn.LookupIP(ExternalIP, 4) + _, ExternalEndPoint_v4, err := conn.LookupIP(ExternalIP, 4, 0) if err == nil { connV4 = ExternalEndPoint_v4 } @@ -170,7 +170,7 @@ func get_api_peers(old_State_hash string) (api_peerinfo mtypes.API_Peers, StateH if strings.Contains(connV6, ":") { hostport := strings.Split(connV6, ":") ExternalIP = ExternalIP + ":" + hostport[len(hostport)-1] - _, ExternalEndPoint_v6, err := conn.LookupIP(ExternalIP, 6) + _, ExternalEndPoint_v6, err := conn.LookupIP(ExternalIP, 6, 0) if err == nil { connV6 = ExternalEndPoint_v6 } diff --git a/main_super.go b/main_super.go index 9212573..86f69ff 100644 --- a/main_super.go +++ b/main_super.go @@ -267,7 +267,7 @@ func super_peeradd(peerconf mtypes.SuperPeerInfo) error { peer4.SetPSK(psk) } if peerconf.EndPoint != "" { - err = peer4.SetEndpointFromConnURL(peerconf.EndPoint, 4, true) + err = peer4.SetEndpointFromConnURL(peerconf.EndPoint, 4, 0, true) if err != nil { if httpobj.http_sconfig.LogLevel.LogInternal { fmt.Printf("Internal: Set endpoint failed:%v\n", err) @@ -292,7 +292,7 @@ func super_peeradd(peerconf mtypes.SuperPeerInfo) error { peer6.SetPSK(psk) } if peerconf.EndPoint != "" { - err = peer6.SetEndpointFromConnURL(peerconf.EndPoint, 6, true) + err = peer6.SetEndpointFromConnURL(peerconf.EndPoint, 6, 0, true) if err != nil { if httpobj.http_sconfig.LogLevel.LogInternal { fmt.Printf("Internal: Set endpoint failed:%v\n", err) diff --git a/mtypes/config.go b/mtypes/config.go index f4752ec..7294d1b 100644 --- a/mtypes/config.go +++ b/mtypes/config.go @@ -26,6 +26,7 @@ type EdgeConfig struct { L2FIBTimeout float64 `yaml:"L2FIBTimeout"` PrivKey string `yaml:"PrivKey"` ListenPort int `yaml:"ListenPort"` + AfPrefer int `yaml:"AfPrefer"` LogLevel LoggerInfo `yaml:"LogLevel"` DynamicRoute DynamicRouteInfo `yaml:"DynamicRoute"` NextHopTable NextHopTable `yaml:"NextHopTable"`