summaryrefslogtreecommitdiffstats
path: root/extras/gomemif/memif
diff options
context:
space:
mode:
Diffstat (limited to 'extras/gomemif/memif')
-rw-r--r--extras/gomemif/memif/control_channel.go41
-rw-r--r--extras/gomemif/memif/interface.go26
2 files changed, 62 insertions, 5 deletions
diff --git a/extras/gomemif/memif/control_channel.go b/extras/gomemif/memif/control_channel.go
index 12672e6e2f8..4788fcb5ea5 100644
--- a/extras/gomemif/memif/control_channel.go
+++ b/extras/gomemif/memif/control_channel.go
@@ -67,11 +67,22 @@ type Socket struct {
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 @@ func (socket *Socket) handleEvent(event *syscall.EpollEvent) error {
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 @@ func (socket *Socket) handleEvent(event *syscall.EpollEvent) error {
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 @@ func (cc *controlChannel) parseConnect() (err error) {
if err != nil {
return err
}
-
cc.isConnected = true
return nil
@@ -764,7 +802,6 @@ func (cc *controlChannel) parseConnected() (err error) {
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 15a8e87453c..4a45075ea4f 100644
--- a/extras/gomemif/memif/interface.go
+++ b/extras/gomemif/memif/interface.go
@@ -60,6 +60,8 @@ type ConnectedFunc func(i *Interface) error
// 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 @@ type Arguments struct {
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 @@ type Interface struct {
regions []memoryRegion
txQueues []Queue
rxQueues []Queue
+ onInterrupt InterruptFunc
}
// IsMaster returns true if the interfaces role is master, else returns false
@@ -270,6 +275,10 @@ func RoleToString(isMaster bool) string {
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 @@ func (i *Interface) RequestConnection() error {
}
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 @@ func (socket *Socket) NewInterface(args *Arguments) (*Interface, error) {
// 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 @@ func (i *Interface) initializeQueues() (err error) {
if err != nil {
return err
}
+ i.socket.addInterrupt(q.interruptFd)
q.putRing()
i.txQueues = append(i.txQueues, *q)
@@ -452,11 +466,17 @@ func (i *Interface) initializeQueues() (err error) {
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)