Add listener bind interface check to wait for interface to become available in the event that the system has just booted and the bind is to a virtual interface. Also added better service signal loop break handling.
This commit is contained in:
parent
1ba1460b67
commit
5dd0717085
57
listener.go
57
listener.go
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/gopacket"
|
"github.com/google/gopacket"
|
||||||
"github.com/google/gopacket/layers"
|
"github.com/google/gopacket/layers"
|
||||||
@ -68,13 +69,55 @@ func NewListener(name, address string, maxMessageSize int, perm bool) (l *Listen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// On Windows, there is no public way to configure hardware vxlan offloading.
|
llog := log.WithFields(log.Fields{
|
||||||
// This in term filters packets that are destined to non-broadcast MAC addresses
|
"listener": addr.String(),
|
||||||
// in vxlan packets. Which prevents us from receiving the packets, so we set the
|
})
|
||||||
// interface to promiscuous mode to allow us to receive packets. We can only do
|
|
||||||
// this if the IP address provided is an absolute address.
|
// Check if we're binding to an interface.
|
||||||
var promisc *Promiscuous
|
var promisc *Promiscuous
|
||||||
if !isZeroAddr(addr.IP) {
|
if !isZeroAddr(addr.IP) {
|
||||||
|
// Check that the interface exists, on Windows it may be a bit before the interface
|
||||||
|
// becomes available.
|
||||||
|
tries := 0
|
||||||
|
tryLoop:
|
||||||
|
for {
|
||||||
|
// Get interface list.
|
||||||
|
ifaces, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to get interface list %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the IP list of each interface for a matching IP to bind addr.
|
||||||
|
for _, iface := range ifaces {
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this address has the bind address, we can stop here.
|
||||||
|
for _, address := range addrs {
|
||||||
|
ipAddr, _, _ := net.ParseCIDR(address.String())
|
||||||
|
if addr.IP.Equal(ipAddr) {
|
||||||
|
break tryLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the bind address wasn't found on an interface, try again for 5 minutes.
|
||||||
|
tries++
|
||||||
|
if tries < 5 {
|
||||||
|
llog.Print("Unable to find interface, will check again in 1 minute...")
|
||||||
|
time.Sleep(time.Minute)
|
||||||
|
} else {
|
||||||
|
// If we passed 5 minutes, we should stop...
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Windows, there is no public way to configure hardware vxlan offloading.
|
||||||
|
// This in term filters packets that are destined to non-broadcast MAC addresses
|
||||||
|
// in vxlan packets. Which prevents us from receiving the packets, so we set the
|
||||||
|
// interface to promiscuous mode to allow us to receive packets.
|
||||||
promisc, err = SetInterfacePromiscuous(addr.IP)
|
promisc, err = SetInterfacePromiscuous(addr.IP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -96,9 +139,7 @@ func NewListener(name, address string, maxMessageSize int, perm bool) (l *Listen
|
|||||||
l.net.maxMessageSizeC = make(chan int)
|
l.net.maxMessageSizeC = make(chan int)
|
||||||
l.net.conn = conn
|
l.net.conn = conn
|
||||||
l.net.promisc = promisc
|
l.net.promisc = promisc
|
||||||
l.log = log.WithFields(log.Fields{
|
l.log = llog
|
||||||
"listener": addr.String(),
|
|
||||||
})
|
|
||||||
l.closed = make(chan struct{})
|
l.closed = make(chan struct{})
|
||||||
l.Permanent = perm
|
l.Permanent = perm
|
||||||
app.Net.Listeners = append(app.Net.Listeners, l)
|
app.Net.Listeners = append(app.Net.Listeners, l)
|
||||||
|
2
main.go
2
main.go
@ -6,7 +6,7 @@ const (
|
|||||||
serviceDisplayName = "Virtual VXLAN"
|
serviceDisplayName = "Virtual VXLAN"
|
||||||
serviceVendor = "com.mrgeckosmedia"
|
serviceVendor = "com.mrgeckosmedia"
|
||||||
serviceDescription = "Virtual VXLAN using TUN interfaces"
|
serviceDescription = "Virtual VXLAN using TUN interfaces"
|
||||||
serviceVersion = "0.1.2"
|
serviceVersion = "0.1.3"
|
||||||
defaultConfigFile = "config.yaml"
|
defaultConfigFile = "config.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -79,10 +79,8 @@ func (a *ServerCmd) Run() error {
|
|||||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
|
||||||
|
|
||||||
// Run program signal handler.
|
// Run program signal handler.
|
||||||
|
sigLoop:
|
||||||
for {
|
for {
|
||||||
// If this service is stopped by signal, this flag will be changed.
|
|
||||||
done := false
|
|
||||||
|
|
||||||
// Check for a signal.
|
// Check for a signal.
|
||||||
select {
|
select {
|
||||||
case sig := <-c:
|
case sig := <-c:
|
||||||
@ -104,15 +102,11 @@ func (a *ServerCmd) Run() error {
|
|||||||
// The default signal is either termination or interruption,
|
// The default signal is either termination or interruption,
|
||||||
// so we should stop the loop.
|
// so we should stop the loop.
|
||||||
default:
|
default:
|
||||||
done = true
|
break sigLoop
|
||||||
}
|
}
|
||||||
// If the app stops itself, mark as done.
|
// If the app stops itself, mark as done.
|
||||||
case <-app.Stop:
|
case <-app.Stop:
|
||||||
done = true
|
break sigLoop
|
||||||
}
|
|
||||||
if done {
|
|
||||||
close(app.Stop)
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user