From d95a63721599ecc42bb19b21e07688f09f0eec41 Mon Sep 17 00:00:00 2001 From: Vladimir Popov Date: Tue, 7 Sep 2021 11:47:09 +0700 Subject: [PATCH] Rework memif to abstract sockets Signed-off-by: Vladimir Popov --- go.mod | 3 + go.sum | 5 +- pkg/networkservice/mechanisms/memif/client.go | 32 ++++++-- .../mechanisms/memif/client_test.go | 2 +- pkg/networkservice/mechanisms/memif/common.go | 66 ++++++++++------ .../mechanisms/memif/memifproxy/client.go | 78 ++++++------------- .../memif/memifproxy/proxy_connection.go | 5 ++ .../memif/memifproxy/proxy_listener.go | 38 ++++----- .../memif/{metatdata.go => metadata.go} | 29 +++++-- pkg/networkservice/mechanisms/memif/option.go | 2 + pkg/networkservice/mechanisms/memif/server.go | 29 +++---- 11 files changed, 158 insertions(+), 131 deletions(-) rename pkg/networkservice/mechanisms/memif/{metatdata.go => metadata.go} (66%) diff --git a/go.mod b/go.mod index e87bf323..14ec3259 100644 --- a/go.mod +++ b/go.mod @@ -14,8 +14,11 @@ require ( github.com/stretchr/testify v1.7.0 github.com/thanhpk/randstr v1.0.4 github.com/vishvananda/netlink v1.1.0 + golang.org/x/sys v0.0.0-20210603125802-9665404d3644 golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200609130330-bd2cb7843e1b google.golang.org/grpc v1.35.0 google.golang.org/protobuf v1.25.0 gopkg.in/yaml.v2 v2.2.4 // indirect ) + +replace github.com/edwarnicke/govpp => github.com/Bolodya1997/govpp v0.0.0-20210906092737-6cdcb637b31f diff --git a/go.sum b/go.sum index 5d546193..1fdb111b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,9 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +git.fd.io/govpp.git v0.3.6-0.20210202134006-4c1cccf48cd1/go.mod h1:OCVd4W8SH+666KRQoMj6PM+oipLDZAHhqMz9B1TGbgI= git.fd.io/govpp.git v0.3.6-0.20210615121054-5de7f6b85458 h1:6I9Hu2Tfg8qYtjKrdD9aRhIvMnNHQhh6MEoDC0hd8zc= git.fd.io/govpp.git v0.3.6-0.20210615121054-5de7f6b85458/go.mod h1:OCVd4W8SH+666KRQoMj6PM+oipLDZAHhqMz9B1TGbgI= +github.com/Bolodya1997/govpp v0.0.0-20210906092737-6cdcb637b31f h1:pY/NN/l3S4eeDDUA+VJMa41zt+hcSMcr2p67L26yoM0= +github.com/Bolodya1997/govpp v0.0.0-20210906092737-6cdcb637b31f/go.mod h1:mIwCBOyMP3Mzfk+ZQShN+aZ24Le8zl+J0dyRI8qcI+o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/HdrHistogram/hdrhistogram-go v1.0.1 h1:GX8GAYDuhlFQnI2fRDHQhTlkHMz8bEn0jTI6LJU0mpw= @@ -28,8 +31,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/edwarnicke/exechelper v1.0.2/go.mod h1:/T271jtNX/ND4De6pa2aRy2+8sNtyCDB1A2pp4M+fUs= -github.com/edwarnicke/govpp v0.0.0-20210817123650-e0e3b4843cf5 h1:G9dEjCjU24jMtuWnWEgZ9eO2x5BPlyrmPLOK9nkfKnU= -github.com/edwarnicke/govpp v0.0.0-20210817123650-e0e3b4843cf5/go.mod h1:qCZYvdwFh5TJepc7DwDmOQ9olgfLjjX90JlyRE4SpYw= github.com/edwarnicke/grpcfd v0.1.0 h1:f0lmmNDYawQaW+dMNoF8d4DxwPxxczNSFuvu5C7ptRk= github.com/edwarnicke/grpcfd v0.1.0/go.mod h1:rHihB9YvNMixz8rS+ZbwosI2kj65VLkeyYAI2M+/cGA= github.com/edwarnicke/serialize v0.0.0-20200705214914-ebc43080eecf/go.mod h1:XvbCO/QGsl3X8RzjBMoRpkm54FIAZH5ChK2j+aox7pw= diff --git a/pkg/networkservice/mechanisms/memif/client.go b/pkg/networkservice/mechanisms/memif/client.go index 27524f8f..aa8a5ce2 100644 --- a/pkg/networkservice/mechanisms/memif/client.go +++ b/pkg/networkservice/mechanisms/memif/client.go @@ -16,7 +16,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +// +build linux package memif @@ -29,8 +29,9 @@ import ( "google.golang.org/grpc" "github.com/networkservicemesh/api/pkg/api/networkservice" - "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/cls" + "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/common" "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/memif" + "github.com/networkservicemesh/sdk/pkg/networkservice/common/switchcase" "github.com/networkservicemesh/sdk/pkg/networkservice/core/chain" "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" "github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata" @@ -49,7 +50,13 @@ func NewClient(vppConn api.Connection) networkservice.NetworkServiceClient { &memifClient{ vppConn: vppConn, }, - memifproxy.New(), + switchcase.NewClient(&switchcase.ClientCase{ + Condition: func(ctx context.Context, conn *networkservice.Connection) bool { + _, ok := loadDirectMemifInfo(ctx) + return !ok + }, + Client: memifproxy.New(), + }), ) } @@ -64,11 +71,13 @@ func mechanismsContain(list []*networkservice.Mechanism, t string) bool { func (m *memifClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { if !mechanismsContain(request.MechanismPreferences, memif.MECHANISM) { - request.MechanismPreferences = append(request.MechanismPreferences, &networkservice.Mechanism{ - Cls: cls.LOCAL, - Type: memif.MECHANISM, - Parameters: make(map[string]string), - }) + mechanism := memif.New("") + if info, ok := loadDirectMemifInfo(ctx); ok { + mechanism.GetParameters()[common.InodeURL] = info.namespace + } else { + mechanism.GetParameters()[common.InodeURL] = netNSURL + } + request.MechanismPreferences = append(request.MechanismPreferences, mechanism) } postponeCtxFunc := postpone.ContextWithValues(ctx) @@ -78,6 +87,13 @@ func (m *memifClient) Request(ctx context.Context, request *networkservice.Netwo return nil, err } + if mechanism := memif.ToMechanism(conn.GetMechanism()); mechanism != nil { + if info, ok := loadDirectMemifInfo(ctx); ok { + info.filename = mechanism.GetParameters()[memif.SocketFilename] + return conn, nil + } + } + if err := create(ctx, conn, m.vppConn, metadata.IsClient(m)); err != nil { closeCtx, cancelClose := postponeCtxFunc() defer cancelClose() diff --git a/pkg/networkservice/mechanisms/memif/client_test.go b/pkg/networkservice/mechanisms/memif/client_test.go index 8d77586b..27def46c 100644 --- a/pkg/networkservice/mechanisms/memif/client_test.go +++ b/pkg/networkservice/mechanisms/memif/client_test.go @@ -14,7 +14,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +// +build linux package memif_test diff --git a/pkg/networkservice/mechanisms/memif/common.go b/pkg/networkservice/mechanisms/memif/common.go index f3331fe7..fb02b343 100644 --- a/pkg/networkservice/mechanisms/memif/common.go +++ b/pkg/networkservice/mechanisms/memif/common.go @@ -14,14 +14,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package memif import ( "context" + "fmt" "net/url" "os" "path/filepath" - "sync/atomic" + "runtime" "time" "git.fd.io/govpp.git/api" @@ -33,15 +36,31 @@ import ( "github.com/networkservicemesh/api/pkg/api/networkservice/payload" "github.com/networkservicemesh/sdk/pkg/tools/log" "github.com/pkg/errors" + "golang.org/x/sys/unix" "github.com/networkservicemesh/sdk-vpp/pkg/networkservice/up" "github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex" ) -var lastSocketID uint32 +var netNSURL string + +// nolint:gochecknoinits +func init() { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + fd, err := unix.Open("/proc/thread-self/ns/net", unix.O_RDONLY|unix.O_CLOEXEC, 0) + if err != nil { + panic("failed to open '/proc/thread-self/ns/net': " + err.Error()) + } + + netNSURL = (&url.URL{ + Scheme: memifMech.SocketFileScheme, + Path: fmt.Sprintf("/proc/%d/fd/%d", os.Getpid(), fd), + }).String() +} func createMemifSocket(ctx context.Context, mechanism *memifMech.Mechanism, vppConn api.Connection, isClient bool) (socketID uint32, err error) { - // Extract the socket filename u, err := url.Parse(mechanism.GetSocketFileURL()) if err != nil { return 0, errors.Wrapf(err, "not a valid url %q", mechanism.GetSocketFileURL()) @@ -50,25 +69,31 @@ func createMemifSocket(ctx context.Context, mechanism *memifMech.Mechanism, vppC return 0, errors.Errorf("socket file url must have scheme %q, actual %q", memifMech.SocketFileScheme, u.Scheme) } - // Create the socketID - socketID = atomic.AddUint32(&lastSocketID, 1) // TODO - work out a solution that works long term - now := time.Now() - memifSocketAddDel := &memif.MemifSocketFilenameAddDel{ + memifSocketAddDel := &memif.MemifSocketFilenameAddDelV2{ IsAdd: true, - SocketID: socketID, - SocketFilename: u.Path, + SocketID: ^uint32(0), + SocketFilename: mechanism.GetSocketFilename(), + Namespace: u.Path, } - if _, err := memif.NewServiceClient(vppConn).MemifSocketFilenameAddDel(ctx, memifSocketAddDel); err != nil { + + now := time.Now() + + reply, err := memif.NewServiceClient(vppConn).MemifSocketFilenameAddDelV2(ctx, memifSocketAddDel) + if err != nil { return 0, errors.WithStack(err) } + memifSocketAddDel.SocketID = reply.SocketID + log.FromContext(ctx). WithField("SocketID", memifSocketAddDel.SocketID). WithField("SocketFilename", memifSocketAddDel.SocketFilename). WithField("IsAdd", memifSocketAddDel.IsAdd). WithField("duration", time.Since(now)). WithField("vppapi", "MemifSocketFilenameAddDel").Debug("completed") + store(ctx, isClient, memifSocketAddDel) - return socketID, nil + + return memifSocketAddDel.SocketID, nil } func deleteMemifSocket(ctx context.Context, vppConn api.Connection, isClient bool) error { @@ -76,17 +101,22 @@ func deleteMemifSocket(ctx context.Context, vppConn api.Connection, isClient boo if !ok { return nil } + memifSocketAddDel.IsAdd = false + now := time.Now() - if _, err := memif.NewServiceClient(vppConn).MemifSocketFilenameAddDel(ctx, memifSocketAddDel); err != nil { + + if _, err := memif.NewServiceClient(vppConn).MemifSocketFilenameAddDelV2(ctx, memifSocketAddDel); err != nil { return errors.WithStack(err) } + log.FromContext(ctx). WithField("SocketID", memifSocketAddDel.SocketID). WithField("SocketFilename", memifSocketAddDel.SocketFilename). WithField("IsAdd", memifSocketAddDel.IsAdd). WithField("duration", time.Since(now)). WithField("vppapi", "MemifSocketFilenameAddDel").Debug("completed") + return nil } @@ -159,10 +189,7 @@ func create(ctx context.Context, conn *networkservice.Connection, vppConn api.Co return nil } if !isClient { - if err := os.MkdirAll(filepath.Dir(socketFile(conn)), 0700); err != nil { - return errors.Wrapf(err, "failed to create memif socket directory %s", socketFile(conn)) - } - mechanism.SetSocketFileURL((&url.URL{Scheme: memifMech.SocketFileScheme, Path: socketFile(conn)}).String()) + mechanism.GetParameters()[memifMech.SocketFilename] = socketFile(conn) } mode := memif.MEMIF_MODE_API_IP if conn.GetPayload() == payload.Ethernet { @@ -187,15 +214,10 @@ func del(ctx context.Context, conn *networkservice.Connection, vppConn api.Conne if err := deleteMemifSocket(ctx, vppConn, isClient); err != nil { return err } - if !isClient { - if err := os.RemoveAll(filepath.Dir(socketFile(conn))); err != nil { - return errors.Wrapf(err, "failed to delete %s", filepath.Dir(socketFile(conn))) - } - } } return nil } func socketFile(conn *networkservice.Connection) string { - return filepath.Join(os.TempDir(), "memif", conn.GetId(), "memif.socket") + return "@" + filepath.Join(os.TempDir(), "memif", conn.GetId(), "memif.socket") } diff --git a/pkg/networkservice/mechanisms/memif/memifproxy/client.go b/pkg/networkservice/mechanisms/memif/memifproxy/client.go index 2ebb31df..5c4474ce 100644 --- a/pkg/networkservice/mechanisms/memif/memifproxy/client.go +++ b/pkg/networkservice/mechanisms/memif/memifproxy/client.go @@ -14,13 +14,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -// +build !windows +// +build linux package memifproxy import ( "context" - "net/url" "os" "path/filepath" @@ -35,12 +34,6 @@ import ( "github.com/networkservicemesh/sdk/pkg/tools/postpone" ) -const ( - memifNetwork = "unixpacket" - maxFDCount = 1 - bufferSize = 128 -) - type memifProxyClient struct{} // New - create a new memifProxy client chain element @@ -49,74 +42,49 @@ func New() networkservice.NetworkServiceClient { } func (m *memifProxyClient) Request(ctx context.Context, request *networkservice.NetworkServiceRequest, opts ...grpc.CallOption) (*networkservice.Connection, error) { - postponeCtxFunc := postpone.ContextWithValues(ctx) - if mechanism := memifMech.ToMechanism(request.GetConnection().GetMechanism()); mechanism != nil { if listener, ok := load(ctx, metadata.IsClient(m)); ok { - mechanism.SetSocketFileURL((&url.URL{Scheme: memifMech.SocketFileScheme, Path: listener.socketFilename}).String()) + mechanism.GetParameters()[memifMech.SocketFilename] = listener.socketFilename } } + postponeCtxFunc := postpone.ContextWithValues(ctx) + conn, err := next.Client(ctx).Request(ctx, request, opts...) if err != nil { return nil, err } - mechanism := memifMech.ToMechanism(conn.GetMechanism()) - if mechanism == nil { - return conn, nil - } - - // If we are already running a proxy... just keep running it - if _, ok := load(ctx, true); ok { - return conn, nil - } - - if err = os.MkdirAll(filepath.Dir(listenSocketFilename(conn)), 0700); err != nil { - err = errors.Wrapf(err, "unable to mkdir %s", filepath.Dir(listenSocketFilename(conn))) - if closeErr := m.closeOnFailure(postponeCtxFunc, conn, opts); closeErr != nil { - err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error()) - } - return nil, err - } - - listener, err := newProxyListener(mechanism, listenSocketFilename(conn)) - if err != nil { - if closeErr := m.closeOnFailure(postponeCtxFunc, conn, opts); closeErr != nil { - err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error()) + if mechanism := memifMech.ToMechanism(conn.GetMechanism()); mechanism != nil { + if _, ok := load(ctx, metadata.IsClient(m)); !ok { + var listener *proxyListener + if listener, err = newProxyListener(mechanism, listenSocketFilename(conn)); err != nil { + closeCtx, cancelClose := postponeCtxFunc() + defer cancelClose() + + if _, closeErr := m.Close(closeCtx, conn, opts...); closeErr != nil { + err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error()) + } + return nil, err + } + store(ctx, metadata.IsClient(m), listener) } - return nil, err + mechanism.GetParameters()[memifMech.SocketFilename] = listenSocketFilename(conn) } - store(ctx, metadata.IsClient(m), listener) - return conn, nil } -func (m *memifProxyClient) closeOnFailure(postponeCtxFunc func() (context.Context, context.CancelFunc), conn *networkservice.Connection, opts []grpc.CallOption) error { - closeCtx, cancelClose := postponeCtxFunc() - defer cancelClose() - - _, err := m.Close(closeCtx, conn, opts...) - - return err -} - func (m *memifProxyClient) Close(ctx context.Context, conn *networkservice.Connection, opts ...grpc.CallOption) (*empty.Empty, error) { if mechanism := memifMech.ToMechanism(conn.GetMechanism()); mechanism != nil { - if listener, ok := load(ctx, metadata.IsClient(m)); ok { - mechanism.SetSocketFileURL((&url.URL{Scheme: memifMech.SocketFileScheme, Path: listener.socketFilename}).String()) + if listener, ok := loadAndDelete(ctx, metadata.IsClient(m)); ok { + mechanism.GetParameters()[memifMech.SocketFilename] = listener.socketFilename + defer func() { _ = listener.Close() }() } } - - rv, err := next.Client(ctx).Close(ctx, conn) - if listener, ok := loadAndDelete(ctx, metadata.IsClient(m)); ok { - _ = listener.Close() - } - _ = os.RemoveAll(filepath.Dir(listenSocketFilename(conn))) - return rv, err + return next.Client(ctx).Close(ctx, conn, opts...) } func listenSocketFilename(conn *networkservice.Connection) string { - return filepath.Join(os.TempDir(), "memifproxy", conn.GetId(), "memif.socket") + return "@" + filepath.Join(os.TempDir(), "memifproxy", conn.GetId(), "memif.socket") } diff --git a/pkg/networkservice/mechanisms/memif/memifproxy/proxy_connection.go b/pkg/networkservice/mechanisms/memif/memifproxy/proxy_connection.go index fa4a1dc9..c5c306a5 100644 --- a/pkg/networkservice/mechanisms/memif/memifproxy/proxy_connection.go +++ b/pkg/networkservice/mechanisms/memif/memifproxy/proxy_connection.go @@ -26,6 +26,11 @@ import ( "github.com/pkg/errors" ) +const ( + maxFDCount = 1 + bufferSize = 128 +) + type proxyConnection struct { in net.Conn out net.Conn diff --git a/pkg/networkservice/mechanisms/memif/memifproxy/proxy_listener.go b/pkg/networkservice/mechanisms/memif/memifproxy/proxy_listener.go index 0d9c5e15..a8ef0c7f 100644 --- a/pkg/networkservice/mechanisms/memif/memifproxy/proxy_listener.go +++ b/pkg/networkservice/mechanisms/memif/memifproxy/proxy_listener.go @@ -20,13 +20,16 @@ package memifproxy import ( "net" - "net/url" "github.com/hashicorp/go-multierror" - memifMech "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/memif" "github.com/pkg/errors" + + memifMech "github.com/networkservicemesh/api/pkg/api/networkservice/mechanisms/memif" + "github.com/networkservicemesh/sdk/pkg/tools/log" ) +const memifNetwork = "unixpacket" + type proxyListener struct { listener net.Listener socketFilename string @@ -34,20 +37,12 @@ type proxyListener struct { } func newProxyListener(mechanism *memifMech.Mechanism, listenSocketFilename string) (*proxyListener, error) { - // Extract the socket filename - u, err := url.Parse(mechanism.GetSocketFileURL()) - if err != nil { - return nil, errors.Wrapf(err, "not a valid url %q", mechanism.GetSocketFileURL()) - } - if u.Scheme != memifMech.SocketFileScheme { - return nil, errors.Errorf("socket file url must have scheme %q, actual %q", memifMech.SocketFileScheme, u.Scheme) - } p := &proxyListener{ - socketFilename: u.Path, + socketFilename: mechanism.GetSocketFilename(), } // Do a trial dial to ensure we can actually proxy - trialConn, err := net.Dial(memifNetwork, u.Path) + trialConn, err := net.Dial(memifNetwork, p.socketFilename) if err != nil { return nil, errors.Wrapf(err, "proxyListener unable to dial %s", p.socketFilename) } @@ -57,32 +52,39 @@ func newProxyListener(mechanism *memifMech.Mechanism, listenSocketFilename strin if err != nil { return nil, errors.Wrapf(err, "proxyListener unable to listen on %s", listenSocketFilename) } - go p.accept() - mechanism.SetSocketFileURL((&url.URL{Scheme: memifMech.SocketFileScheme, Path: listenSocketFilename}).String()) + go p.accept(log.Default().WithField("proxy", listenSocketFilename)) + return p, nil } -func (p *proxyListener) accept() { +func (p *proxyListener) accept(logger log.Logger) { defer func() { _ = p.Close() }() for { in, err := p.listener.Accept() if optErr, ok := err.(*net.OpError); ok && !optErr.Temporary() { - // TODO - perhaps log this? + logger.Errorf("accept failed: %s", optErr.Error()) return } + + logger.Infof("received accept: %s", in.LocalAddr()) + out, err := net.Dial(memifNetwork, p.socketFilename) if optErr, ok := err.(*net.OpError); ok && !optErr.Temporary() { _ = in.Close() - // TODO - perhaps log this? + logger.Errorf("dial failed: %s", optErr.Error()) return } + + logger.Infof("connection dialed: %s", out.RemoteAddr()) + proxyConn, err := newProxyConnection(in, out) if err != nil { _ = in.Close() _ = out.Close() - // TODO - perhaps log this? + logger.Errorf("failed to create connection: %s", err.Error()) return } + // TODO - clean up - while 99% of the time this won't be an issue because we will have exactly one thing // in this list... in principle it could leak memory p.proxyConnections = append(p.proxyConnections, proxyConn) diff --git a/pkg/networkservice/mechanisms/memif/metatdata.go b/pkg/networkservice/mechanisms/memif/metadata.go similarity index 66% rename from pkg/networkservice/mechanisms/memif/metatdata.go rename to pkg/networkservice/mechanisms/memif/metadata.go index 10b3b4f2..be68d441 100644 --- a/pkg/networkservice/mechanisms/memif/metatdata.go +++ b/pkg/networkservice/mechanisms/memif/metadata.go @@ -26,19 +26,34 @@ import ( type key struct{} -func store(ctx context.Context, isClient bool, socket *memif.MemifSocketFilenameAddDel) { +func store(ctx context.Context, isClient bool, socket *memif.MemifSocketFilenameAddDelV2) { metadata.Map(ctx, isClient).Store(key{}, socket) } -func delete(ctx context.Context, isClient bool) { - metadata.Map(ctx, isClient).Delete(key{}) -} - -func load(ctx context.Context, isClient bool) (value *memif.MemifSocketFilenameAddDel, ok bool) { +func load(ctx context.Context, isClient bool) (value *memif.MemifSocketFilenameAddDelV2, ok bool) { rawValue, ok := metadata.Map(ctx, isClient).Load(key{}) if !ok { return } - value, ok = rawValue.(*memif.MemifSocketFilenameAddDel) + value, ok = rawValue.(*memif.MemifSocketFilenameAddDelV2) return value, ok } + +type directMemifKey struct{} + +type directMemifInfo struct { + namespace, filename string +} + +func storeDirectMemifInfo(ctx context.Context, info *directMemifInfo) { + metadata.Map(ctx, false).Store(directMemifKey{}, info) +} + +func loadDirectMemifInfo(ctx context.Context) (*directMemifInfo, bool) { + rv, ok := metadata.Map(ctx, false).Load(directMemifKey{}) + if !ok { + return nil, false + } + info, ok := rv.(*directMemifInfo) + return info, ok +} diff --git a/pkg/networkservice/mechanisms/memif/option.go b/pkg/networkservice/mechanisms/memif/option.go index 4198b362..ec1a8a7d 100644 --- a/pkg/networkservice/mechanisms/memif/option.go +++ b/pkg/networkservice/mechanisms/memif/option.go @@ -14,6 +14,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package memif // Option is an option for the connect server diff --git a/pkg/networkservice/mechanisms/memif/server.go b/pkg/networkservice/mechanisms/memif/server.go index 3dfba338..8b74e04c 100644 --- a/pkg/networkservice/mechanisms/memif/server.go +++ b/pkg/networkservice/mechanisms/memif/server.go @@ -14,11 +14,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +// +build linux + package memif import ( "context" - "net/url" "git.fd.io/govpp.git/api" "github.com/golang/protobuf/ptypes/empty" @@ -29,8 +30,6 @@ import ( "github.com/networkservicemesh/sdk/pkg/networkservice/core/next" "github.com/networkservicemesh/sdk/pkg/networkservice/utils/metadata" "github.com/networkservicemesh/sdk/pkg/tools/postpone" - - "github.com/networkservicemesh/sdk-vpp/pkg/tools/ifindex" ) type memifServer struct { @@ -53,6 +52,12 @@ func NewServer(vppConn api.Connection, options ...Option) networkservice.Network } func (m *memifServer) Request(ctx context.Context, request *networkservice.NetworkServiceRequest) (*networkservice.Connection, error) { + if mechanism := memifMech.ToMechanism(request.GetConnection().GetMechanism()); mechanism != nil && m.directMemifEnabled { + storeDirectMemifInfo(ctx, &directMemifInfo{ + namespace: mechanism.GetSocketFileURL(), + }) + } + postponeCtxFunc := postpone.ContextWithValues(ctx) conn, err := next.Server(ctx).Request(ctx, request) @@ -61,21 +66,9 @@ func (m *memifServer) Request(ctx context.Context, request *networkservice.Netwo } if mechanism := memifMech.ToMechanism(conn.GetMechanism()); mechanism != nil { - // Direct memif if applicable - if memifSocketAddDel, ok := load(ctx, true); ok && m.directMemifEnabled { - _, ok := ifindex.Load(ctx, true) - if ok { - if err := del(ctx, conn, m.vppConn, true); err != nil { - if closeErr := m.closeOnFailure(postponeCtxFunc, conn); closeErr != nil { - err = errors.Wrapf(err, "connection closed with error: %s", closeErr.Error()) - } - return nil, err - } - mechanism.SetSocketFileURL((&url.URL{Scheme: memifMech.SocketFileScheme, Path: memifSocketAddDel.SocketFilename}).String()) - delete(ctx, true) - ifindex.Delete(ctx, true) - return conn, nil - } + if info, ok := loadDirectMemifInfo(ctx); ok && info.filename != "" { + mechanism.GetParameters()[memifMech.SocketFilename] = info.filename + return conn, nil } }