Use new default binapi socket with fallback to legacy
[govpp.git] / adapter / socketclient / socketclient.go
index 96f23e6..1c425ba 100644 (file)
@@ -38,6 +38,7 @@ import (
 const (
        // DefaultSocketName is default VPP API socket file path.
        DefaultSocketName = adapter.DefaultBinapiSocket
+       legacySocketName  = "/run/vpp-api.sock"
 )
 
 var (
@@ -71,6 +72,27 @@ func init() {
        }
 }
 
+const socketMissing = `
+------------------------------------------------------------
+ No socket file found at: %s
+ VPP binary API socket file is missing!
+
+  - is VPP running with socket for binapi enabled?
+  - is the correct socket name configured?
+
+ To enable it add following section to your VPP config:
+   socksvr {
+     default
+   }
+------------------------------------------------------------
+`
+
+var warnOnce sync.Once
+
+func (c *vppClient) printMissingSocketMsg() {
+       fmt.Fprintf(os.Stderr, socketMissing, c.sockAddr)
+}
+
 type vppClient struct {
        sockAddr string
 
@@ -115,6 +137,32 @@ func (c *vppClient) SetDisconnectTimeout(t time.Duration) {
        c.disconnectTimeout = t
 }
 
+func (c *vppClient) SetMsgCallback(cb adapter.MsgCallback) {
+       Log.Debug("SetMsgCallback")
+       c.cb = cb
+}
+
+func (c *vppClient) checkLegacySocket() bool {
+       if c.sockAddr == legacySocketName {
+               return false
+       }
+       Log.Debugf("checking legacy socket: %s", legacySocketName)
+       // check if socket exists
+       if _, err := os.Stat(c.sockAddr); err == nil {
+               return false // socket exists
+       } else if !os.IsNotExist(err) {
+               return false // some other error occurred
+       }
+       // check if legacy socket exists
+       if _, err := os.Stat(legacySocketName); err == nil {
+               // legacy socket exists, update sockAddr
+               c.sockAddr = legacySocketName
+               return true
+       }
+       // no socket socket found
+       return false
+}
+
 // WaitReady checks socket file existence and waits for it if necessary
 func (c *vppClient) WaitReady() error {
        // check if socket already exists
@@ -124,6 +172,10 @@ func (c *vppClient) WaitReady() error {
                return err // some other error occurred
        }
 
+       if c.checkLegacySocket() {
+               return nil
+       }
+
        // socket does not exist, watch for it
        watcher, err := fsnotify.NewWatcher()
        if err != nil {
@@ -144,6 +196,9 @@ func (c *vppClient) WaitReady() error {
        for {
                select {
                case <-timeout.C:
+                       if c.checkLegacySocket() {
+                               return nil
+                       }
                        return fmt.Errorf("timeout waiting (%s) for socket file: %s", MaxWaitReady, c.sockAddr)
 
                case e := <-watcher.Errors:
@@ -159,13 +214,16 @@ func (c *vppClient) WaitReady() error {
        }
 }
 
-func (c *vppClient) SetMsgCallback(cb adapter.MsgCallback) {
-       Log.Debug("SetMsgCallback")
-       c.cb = cb
-}
-
 func (c *vppClient) Connect() error {
-       Log.Debugf("Connecting to: %v", c.sockAddr)
+       c.checkLegacySocket()
+
+       // check if socket exists
+       if _, err := os.Stat(c.sockAddr); os.IsNotExist(err) {
+               warnOnce.Do(c.printMissingSocketMsg)
+               return fmt.Errorf("VPP API socket file %s does not exist", c.sockAddr)
+       } else if err != nil {
+               return fmt.Errorf("VPP API socket error: %v", err)
+       }
 
        if err := c.connect(c.sockAddr); err != nil {
                return err
@@ -212,12 +270,14 @@ func (c *vppClient) Disconnect() error {
 func (c *vppClient) connect(sockAddr string) error {
        addr := &net.UnixAddr{Name: sockAddr, Net: "unix"}
 
+       Log.Debugf("Connecting to: %v", c.sockAddr)
+
        conn, err := net.DialUnix("unix", nil, addr)
        if err != nil {
                // we try different type of socket for backwards compatbility with VPP<=19.04
                if strings.Contains(err.Error(), "wrong type for socket") {
                        addr.Net = "unixpacket"
-                       Log.Warnf("%s, retrying connect with type unixpacket", err)
+                       Log.Debugf("%s, retrying connect with type unixpacket", err)
                        conn, err = net.DialUnix("unixpacket", nil, addr)
                }
                if err != nil {