@@ -80,7 +80,10 @@ type libcni struct {
8080 cniConfig cnilibrary.CNI
8181 networkCount int // minimum network plugin configurations needed to initialize cni
8282 networks []* Network
83- sync.RWMutex
83+ // Mutex contract:
84+ // - lock in public methods: write lock when mutating the state, read lock when reading the state.
85+ // - never lock in private methods.
86+ RWMutex
8487}
8588
8689func defaultCNIConfig () * libcni {
@@ -135,11 +138,11 @@ func (c *libcni) Load(opts ...Opt) error {
135138
136139// Status returns the status of CNI initialization.
137140func (c * libcni ) Status () error {
141+ c .RLock ()
142+ defer c .RUnlock ()
138143 if err := c .ready (); err != nil {
139144 return err
140145 }
141- c .RLock ()
142- defer c .RUnlock ()
143146 // STATUS is only called for CNI Version 1.1.0 or greater. It is ignored for previous versions.
144147 for _ , v := range c .networks {
145148 err := c .cniConfig .GetStatusNetworkList (context .Background (), v .config )
@@ -162,11 +165,11 @@ func (c *libcni) Networks() []*Network {
162165
163166// Setup setups the network in the namespace and returns a Result
164167func (c * libcni ) Setup (ctx context.Context , id string , path string , opts ... NamespaceOpts ) (* Result , error ) {
168+ c .RLock ()
169+ defer c .RUnlock ()
165170 if err := c .ready (); err != nil {
166171 return nil , err
167172 }
168- c .RLock ()
169- defer c .RUnlock ()
170173 ns , err := newNamespace (id , path , opts ... )
171174 if err != nil {
172175 return nil , err
@@ -180,11 +183,11 @@ func (c *libcni) Setup(ctx context.Context, id string, path string, opts ...Name
180183
181184// SetupSerially setups the network in the namespace and returns a Result
182185func (c * libcni ) SetupSerially (ctx context.Context , id string , path string , opts ... NamespaceOpts ) (* Result , error ) {
186+ c .RLock ()
187+ defer c .RUnlock ()
183188 if err := c .ready (); err != nil {
184189 return nil , err
185190 }
186- c .RLock ()
187- defer c .RUnlock ()
188191 ns , err := newNamespace (id , path , opts ... )
189192 if err != nil {
190193 return nil , err
@@ -198,7 +201,7 @@ func (c *libcni) SetupSerially(ctx context.Context, id string, path string, opts
198201
199202func (c * libcni ) attachNetworksSerially (ctx context.Context , ns * Namespace ) ([]* types100.Result , error ) {
200203 var results []* types100.Result
201- for _ , network := range c .Networks () {
204+ for _ , network := range c .networks {
202205 r , err := network .Attach (ctx , ns )
203206 if err != nil {
204207 return nil , err
@@ -223,15 +226,15 @@ func asynchAttach(ctx context.Context, index int, n *Network, ns *Namespace, wg
223226func (c * libcni ) attachNetworks (ctx context.Context , ns * Namespace ) ([]* types100.Result , error ) {
224227 var wg sync.WaitGroup
225228 var firstError error
226- results := make ([]* types100.Result , len (c .Networks () ))
229+ results := make ([]* types100.Result , len (c .networks ))
227230 rc := make (chan asynchAttachResult )
228231
229- for i , network := range c .Networks () {
232+ for i , network := range c .networks {
230233 wg .Add (1 )
231234 go asynchAttach (ctx , i , network , ns , & wg , rc )
232235 }
233236
234- for range c .Networks () {
237+ for range c .networks {
235238 rs := <- rc
236239 if rs .err != nil && firstError == nil {
237240 firstError = rs .err
@@ -245,16 +248,16 @@ func (c *libcni) attachNetworks(ctx context.Context, ns *Namespace) ([]*types100
245248
246249// Remove removes the network config from the namespace
247250func (c * libcni ) Remove (ctx context.Context , id string , path string , opts ... NamespaceOpts ) error {
251+ c .RLock ()
252+ defer c .RUnlock ()
248253 if err := c .ready (); err != nil {
249254 return err
250255 }
251- c .RLock ()
252- defer c .RUnlock ()
253256 ns , err := newNamespace (id , path , opts ... )
254257 if err != nil {
255258 return err
256259 }
257- for _ , network := range c .Networks () {
260+ for _ , network := range c .networks {
258261 if err := network .Remove (ctx , ns ); err != nil {
259262 // Based on CNI spec v0.7.0, empty network namespace is allowed to
260263 // do best effort cleanup. However, it is not handled consistently
@@ -275,16 +278,16 @@ func (c *libcni) Remove(ctx context.Context, id string, path string, opts ...Nam
275278
276279// Check checks if the network is still in desired state
277280func (c * libcni ) Check (ctx context.Context , id string , path string , opts ... NamespaceOpts ) error {
281+ c .RLock ()
282+ defer c .RUnlock ()
278283 if err := c .ready (); err != nil {
279284 return err
280285 }
281- c .RLock ()
282- defer c .RUnlock ()
283286 ns , err := newNamespace (id , path , opts ... )
284287 if err != nil {
285288 return err
286289 }
287- for _ , network := range c .Networks () {
290+ for _ , network := range c .networks {
288291 err := network .Check (ctx , ns )
289292 if err != nil {
290293 return err
@@ -329,8 +332,6 @@ func (c *libcni) reset() {
329332}
330333
331334func (c * libcni ) ready () error {
332- c .RLock ()
333- defer c .RUnlock ()
334335 if len (c .networks ) < c .networkCount {
335336 return ErrCNINotInitialized
336337 }
0 commit comments