code: func NewSandbox(key string, osCreate, isRestore bool) (Sandbox, error) {
  	if !isRestore {
  		err := createNetworkNamespace(key, osCreate)
  		if err != nil {
  			return nil, err
  		}
  	} else {
  		once.Do(createBasePath)
  	}
  
  	n := &networkNamespace{path: key, isDefault: !osCreate, nextIfIndex: make(map[string]int)}
  
  	sboxNs, err := netns.GetFromPath(n.path)
  	if err != nil {
  		return nil, fmt.Errorf("failed get network namespace %q: %v", n.path, err)
  	}
  	defer sboxNs.Close()
  
  	n.nlHandle, err = netlink.NewHandleAt(sboxNs, syscall.NETLINK_ROUTE)
  	if err != nil {
  		return nil, fmt.Errorf("failed to create a netlink handle: %v", err)
  	}
  
  	err = n.nlHandle.SetSocketTimeout(ns.NetlinkSocketsTimeout)
  	if err != nil {
  		logrus.Warnf("Failed to set the timeout on the sandbox netlink handle sockets: %v", err)
  	}
  	// In live-restore mode, IPV6 entries are getting cleaned up due to below code
  	// We should retain IPV6 configurations in live-restore mode when Docker Daemon
  	// comes back. It should work as it is on other cases
  	// As starting point, disable IPv6 on all interfaces
  	if !isRestore && !n.isDefault {
  		err = setIPv6(n.path, "all", false)
  		if err != nil {
  			logrus.Warnf("Failed to disable IPv6 on all interfaces on network namespace %q: %v", n.path, err)
  		}
  	}
  
  	if err = n.loopbackUp(); err != nil {
  		n.nlHandle.Delete()
  		return nil, err
  	}
  
  	return n, nil
  }
docs: // NewSandbox provides a new sandbox instance created in an os specific way
  // provided a key which uniquely identifies the sandbox