go.ligato.io/vpp-agent/v3@v3.5.0/plugins/linux/nsplugin/linuxcalls/namespace_api.go (about)

     1  // Copyright (c) 2018 Cisco and/or its affiliates.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at:
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package linuxcalls
    16  
    17  import (
    18  	"os"
    19  	"runtime"
    20  
    21  	"github.com/vishvananda/netns"
    22  	"go.ligato.io/cn-infra/v2/logging"
    23  )
    24  
    25  var enableNsCtxCheck = os.Getenv("NSPLUGIN_CHECK_NS_CTX") != ""
    26  
    27  // NamedNetNsAPI defines methods related to management of named network namespaces.
    28  type NamedNetNsAPI interface {
    29  	// CreateNamedNetNs creates a new named Linux network namespace.
    30  	// It does exactly the same thing as the command "ip netns add NAMESPACE".
    31  	CreateNamedNetNs(ctx NamespaceMgmtCtx, nsName string) (netns.NsHandle, error)
    32  	// DeleteNamedNetNs deletes an existing named Linux network namespace.
    33  	// It does exactly the same thing as the command "ip netns del NAMESPACE".
    34  	DeleteNamedNetNs(nsName string) error
    35  	// NamedNetNsExists checks whether named namespace exists.
    36  	NamedNetNsExists(nsName string) (bool, error)
    37  }
    38  
    39  // NamespaceMgmtCtx represents context of an ongoing management of Linux namespaces.
    40  // The same context should not be used concurrently.
    41  type NamespaceMgmtCtx interface {
    42  	// LockOSThread wires the calling goroutine to its current operating system thread.
    43  	// The method should implement re-entrant lock always called from a single go routine.
    44  	LockOSThread()
    45  	// UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
    46  	// The method should implement re-entrant lock always called from a single go routine.
    47  	UnlockOSThread()
    48  }
    49  
    50  // namespaceMgmtCtx implements NamespaceMgmtCtx.
    51  type namespaceMgmtCtx struct {
    52  	lockOsThreadCnt int
    53  }
    54  
    55  // LockOSThread wires the calling goroutine to its current operating system thread.
    56  func (ctx *namespaceMgmtCtx) LockOSThread() {
    57  	if ctx.lockOsThreadCnt == 0 {
    58  		runtime.LockOSThread()
    59  	}
    60  	ctx.lockOsThreadCnt++
    61  }
    62  
    63  // UnlockOSThread unwires the calling goroutine from its fixed operating system thread.
    64  func (ctx *namespaceMgmtCtx) UnlockOSThread() {
    65  	ctx.lockOsThreadCnt--
    66  	if ctx.lockOsThreadCnt == 0 {
    67  		runtime.UnlockOSThread()
    68  	}
    69  }
    70  
    71  // NewNamespaceMgmtCtx creates and returns a new context for management of Linux
    72  // namespaces.
    73  func NewNamespaceMgmtCtx() NamespaceMgmtCtx {
    74  	nsCtx := &namespaceMgmtCtx{}
    75  	if enableNsCtxCheck {
    76  		bt := make([]byte, 1<<16)
    77  		runtime.Stack(bt, false)
    78  		runtime.SetFinalizer(nsCtx, func(ctx *namespaceMgmtCtx) {
    79  			if ctx.lockOsThreadCnt != 0 {
    80  				panic("locked ns ctx to be GCed - created at: " + string(bt))
    81  			}
    82  		})
    83  	}
    84  	return nsCtx
    85  }
    86  
    87  // namedNetNsHandler implements NamedNetNsAPI using provided system handler.
    88  type namedNetNsHandler struct {
    89  	log        logging.Logger
    90  	sysHandler SystemAPI
    91  }
    92  
    93  // NewNamedNetNsHandler creates new instance of namespace handler
    94  func NewNamedNetNsHandler(sysHandler SystemAPI, log logging.Logger) NamedNetNsAPI {
    95  	return &namedNetNsHandler{
    96  		log:        log,
    97  		sysHandler: sysHandler,
    98  	}
    99  }