code: func (na *cnmNetworkAllocator) Allocate(n *api.Network) error {
  	if _, ok := na.networks[n.ID]; ok {
  		return fmt.Errorf("network %s already allocated", n.ID)
  	}
  
  	d, err := na.resolveDriver(n)
  	if err != nil {
  		return err
  	}
  
  	nw := &network{
  		nw:          n,
  		endpoints:   make(map[string]string),
  		isNodeLocal: d.capability.DataScope == datastore.LocalScope,
  	}
  
  	// No swarm-level allocation can be provided by the network driver for
  	// node-local networks. Only thing needed is populating the driver's name
  	// in the driver's state.
  	if nw.isNodeLocal {
  		n.DriverState = &api.Driver{
  			Name: d.name,
  		}
  		// In order to support backward compatibility with older daemon
  		// versions which assumes the network attachment to contains
  		// non nil IPAM attribute, passing an empty object
  		n.IPAM = &api.IPAMOptions{Driver: &api.Driver{}}
  	} else {
  		nw.pools, err = na.allocatePools(n)
  		if err != nil {
  			return errors.Wrapf(err, "failed allocating pools and gateway IP for network %s", n.ID)
  		}
  
  		if err := na.allocateDriverState(n); err != nil {
  			na.freePools(n, nw.pools)
  			return errors.Wrapf(err, "failed while allocating driver state for network %s", n.ID)
  		}
  	}
  
  	na.networks[n.ID] = nw
  
  	return nil
  }
docs: // Allocate allocates all the necessary resources both general
  // and driver-specific which may be specified in the NetworkSpec