gomemif: update to libmemif version 4.0

Type: improvement

This patch provides:
1. interrupt mode support,
2. abstract socket support,
3. overriding responder example and divides it to two examples:
	-icmp_responder_cb
	-icmp_responder_poll

Signed-off-by: Daniel Béreš <dberes@cisco.com>
Change-Id: I99c86d053521760c457541fc596ed554f4077608
diff --git a/extras/gomemif/memif/control_channel.go b/extras/gomemif/memif/control_channel.go
index 12672e6..4788fcb 100644
--- a/extras/gomemif/memif/control_channel.go
+++ b/extras/gomemif/memif/control_channel.go
@@ -67,11 +67,22 @@
 	interfaceList *list.List
 	ccList        *list.List
 	epfd          int
+	interruptfd   int
 	wakeEvent     syscall.EpollEvent
 	stopPollChan  chan struct{}
 	wg            sync.WaitGroup
 }
 
+type interrupt struct {
+	socket *Socket
+	event  syscall.EpollEvent
+}
+
+type memifInterrupt struct {
+	connection *Socket
+	qid        uint16
+}
+
 // StopPolling stops polling events on the socket
 func (socket *Socket) StopPolling() error {
 	if socket.stopPollChan != nil {
@@ -220,6 +231,15 @@
 	if socket.listener != nil && socket.listener.event.Fd == event.Fd {
 		return socket.listener.handleEvent(event)
 	}
+	intf := socket.interfaceList.Back().Value.(*Interface)
+	if intf.args.InterruptFunc != nil {
+		if int(event.Fd) == int(intf.args.InterruptFd) {
+			b := make([]byte, 8)
+			syscall.Read(int(event.Fd), b)
+			intf.onInterrupt(intf)
+			return nil
+		}
+	}
 
 	for elt := socket.ccList.Front(); elt != nil; elt = elt.Next() {
 		cc, ok := elt.Value.(*controlChannel)
@@ -233,6 +253,25 @@
 	return fmt.Errorf(errorFdNotFound)
 }
 
+func (socket *Socket) addInterrupt(fd int) (err error) {
+	l := &interrupt{
+		// we will need this to look up master interface by id
+		socket: socket,
+	}
+
+	l.event = syscall.EpollEvent{
+		Events: syscall.EPOLLIN,
+		Fd:     int32(fd),
+	}
+	err = socket.addEvent(&l.event)
+	if err != nil {
+		return fmt.Errorf("Failed to add event: ", err)
+	}
+
+	return nil
+
+}
+
 // handleEvent handles epoll event for listener
 func (l *listener) handleEvent(event *syscall.EpollEvent) error {
 	// hang up
@@ -725,7 +764,6 @@
 	if err != nil {
 		return err
 	}
-
 	cc.isConnected = true
 
 	return nil
@@ -764,7 +802,6 @@
 	if err != nil {
 		return err
 	}
-
 	cc.isConnected = true
 
 	return nil
diff --git a/extras/gomemif/memif/interface.go b/extras/gomemif/memif/interface.go
index 15a8e87..4a45075 100644
--- a/extras/gomemif/memif/interface.go
+++ b/extras/gomemif/memif/interface.go
@@ -60,6 +60,8 @@
 // DisconnectedFunc is a callback called when an interface is disconnected
 type DisconnectedFunc func(i *Interface) error
 
+type InterruptFunc func(i *Interface) error
+
 // MemoryConfig represents shared memory configuration
 type MemoryConfig struct {
 	NumQueuePairs    uint16 // number of queue pairs
@@ -77,7 +79,9 @@
 	MemoryConfig     MemoryConfig
 	ConnectedFunc    ConnectedFunc    // callback called when interface changes status to connected
 	DisconnectedFunc DisconnectedFunc // callback called when interface changes status to disconnected
-	PrivateData      interface{}      // private data used by client program
+	InterruptFunc    InterruptFunc
+	PrivateData      interface{} // private data used by client program
+	InterruptFd      uint16
 }
 
 // memoryRegion represents a shared memory mapped file
@@ -110,6 +114,7 @@
 	regions     []memoryRegion
 	txQueues    []Queue
 	rxQueues    []Queue
+	onInterrupt InterruptFunc
 }
 
 // IsMaster returns true if the interfaces role is master, else returns false
@@ -270,6 +275,10 @@
 	return "Slave"
 }
 
+func memifPathIsAbstract(filename string) bool {
+	return (filename[0] == '@')
+}
+
 // RequestConnection is used by slave interface to connect to a socket and
 // create a control channel
 func (i *Interface) RequestConnection() error {
@@ -283,6 +292,9 @@
 	}
 	usa := &syscall.SockaddrUnix{Name: i.socket.filename}
 
+	if memifPathIsAbstract(i.socket.GetFilename()) {
+		usa.Name = "\000" + usa.Name[1:]
+	}
 	// Connect to listener socket
 	err = syscall.Connect(fd, usa)
 	if err != nil {
@@ -315,7 +327,8 @@
 
 	// copy interface configuration
 	i := Interface{
-		args: *args,
+		args:        *args,
+		onInterrupt: args.InterruptFunc,
 	}
 	// set default values
 	if i.args.MemoryConfig.NumQueuePairs == 0 {
@@ -434,6 +447,7 @@
 		if err != nil {
 			return err
 		}
+		i.socket.addInterrupt(q.interruptFd)
 		q.putRing()
 		i.txQueues = append(i.txQueues, *q)
 
@@ -452,11 +466,17 @@
 			i:        i,
 		}
 		q.ring.setCookie(cookie)
-		q.ring.setFlags(1)
+		if i.args.InterruptFunc == nil {
+			q.ring.setFlags(1)
+		} else {
+			q.ring.setFlags(0)
+		}
 		q.interruptFd, err = eventFd()
 		if err != nil {
 			return err
 		}
+		i.args.InterruptFd = uint16(q.interruptFd)
+		i.socket.addInterrupt(q.interruptFd)
 		q.putRing()
 		i.rxQueues = append(i.rxQueues, *q)