Tuesday, September 2, 2014

ThreadPool implementation using IO Completion Ports (Visual C++)

Looking for an efficient, fast and custom thread pool using Visual C++? Then implement a custom thread pool using IO-Completion ports.

Overview

There are two ways to manage a pool of threads.

One is, to depend on Microsoft’s straight forward way of thread pool implementation using Win32-API’s such as ‘QueueUserWorkItem’. Though simple, it lacks on the performance side. This is due to the fact that, frequent thread context switching can happen, while selecting worker threads from the pool to process requests. Also if we’ve a multi-core CPU, all cores may not be used in this implementation. Typically for inter-thread communications, we might be using ‘window messages’ that might also be slow.

The second way is to build your own thread pool using ‘I/O Completion ports (IOCP)’ API’s. It is known to be an extremely fast and efficient solution for custom thread pooling, that can far outweigh the rudimentary thread pooling described above. At the very heart, IOCP implementation is revolving around the usage of the below 3 Win32-API’s.

CreateIoCompletionPort

This API will create the IO queue, to which work requests will be posted and retrieved. In a thread pool scenario, work requests will be submitted and retrieved to/from this queue and worker thread will process the requests.

PostQueuedCompletionStatus

This API is used to post a work request to the queue, by any client to the thread pool.

GetQueuedCompletionStatus

Worker threads, will call and wait on this API, to retrieve work request from the queue. This API, will not add any overhead to the CPU, like the conventional way of waiting on handles. 

Advantages

The following are the advantages of using ‘IO-Completion ports’ for thread pool implementations.

1. Maximum CPU core usage

If you haven’t specified otherwise, IOCP will use the maximum number of CPU cores.

2. No unwanted context switching

The threads are used in LIFO (Last in first out) manner, hence the last thread in memory will get the priority to process the next work item and hence, no context switches will happen to load another thread to memory.

3. No clogging up CPU, for polling or waiting

IOCP is more efficient than, the conventional way of waiting on events, polling or messages.

4. Make a configured number of pre-created worker threads to be available in thread pool

While setting up the thread pool, we can create a configured number of threads and make them readily available for servicing the requests as soon as, we starts the thread pool.

That being said, this is the most recommended way of doing multithreading on a server scenario, as the server can have a very high loads of requests to be processed by a pool of threads. Also IOCP is not only for a custom thread pool implementation, it can be used with any object, that can work with overlapped IO and Asynchronous IO events to get the maximum performance and to use the least amount of server resources. Typical examples are WSA sockets, file handles e.t.c.

You can get a good understanding on IOCP by following articles in msdn (Threadpool, IOCP in msdn).

Demo

Ok that’s about the theory. Let’s go ahead and create a custom thread pool using IOCP. For this exercise, we will be using Visual C++ with MFC (Microsoft Foundation Classes). Below depicts the high level view on the implementation.

a. Create the IO-Completion port for the thread pool (Using API CreateIoCompletionPort)

b. Create pre-defined number of worker threads, that is to be readily available to the pool

c. For each ‘work request’ from client:

Queue work request to IOCP using API ‘PostQueuedCompletionStatus’

d. Each worker thread will be waiting for queued jobs

using API ‘GetQueuedCompletionStatus’

If any jobs available (eg: Step#c got invoked by a client), one worker thread will awaken to process the request

e. Once we’ve done with the thread pool, stop it:

Make all worker threads exit (using ‘PostQueuedCompletionStatus’, with a different parameter)

A work request constitutes of two arguments.

Work Request:

Data to be processed

This is a void long pointer, that can point to any structure or object. Using LPVOID, we can support any objects as the Data and it ensures scalability.

Function to act up on the Data

Client has the option to attach a pointer to ‘C++ class member function’ or a ‘Global C function’, that needs to be invoked by the worker thread to process the supplied data.

Demo – UI walkthrough

Below shows the UI of the test application.

image

You will start, by providing the desired number ‘Number of Worker Threads’ in the very first text box and hitting on the ‘Start Thread Pool Manager’ button. This will initialize the thread pool and creates the worker threads on the startup.

Now you can push as many job as you wish, by providing the ‘Jobs To Push’ as a desired integer value (Number of jobs to push) and hitting either ‘Push Jobs to Job Queue Using Member Function’ or ‘Push Jobs to Job Queue using Global Function’. The former button is to use ‘C++ class member function’ to process the data or the latter is to use a ‘Global C Function’.

These functions will simply write some text (given to it as its Data) to a file to make them simple enough.

Once you experiment enough, don’t forget to hit ‘Stop Thread Pool Manager’ button to gracefully shutdown the thread pool. It will remove any pending jobs in the queue and wait for any pending processing to finish.

Demo – Code Walkthrough

Below are the type definitions for the ‘Global C’ and ‘C++ class member’ prototype functions. Please note that, if you need to attach a ‘C++ class member function’, the class containing the member function should be derived from the very base class of MFC, the ‘CObject’.

// Function prototype of the worker function to be supported at the client side
// [For Non Member functions, i.e. For static or global functions
typedef void ( WINAPI   *WORKER_CALLBACK_PROTOTYPE )( LPVOID pDataIn_i );


// Function prototype of the worker function to be supported at the client side
// [For Class Member Functions that should be invoked using an object]

typedef void ( CObject::*MEMBER_FUNCTION_WORKER_CALLBACK_PROTOTYPE )( LPVOID pDataIn_i );

The below listing will give you a summary on the codebase. Please note that, in actual project source attached, they are scattered around various places like inside button clicks and MFC dialog classes. But for simplicity we’ve consolidated all such code into a single place here.

The header file contains the thread pool manager object. The implementation file contains the ‘Global C Function’ and ‘C++ member function’ to be invoked by the worker threads in the thread pool. ‘InitializeThreadPool’ should be called first to initialize the thread pool. Then jobs are pushed the thread pool using the ‘EnQueue’ method. Supporting macros are being used to attach the functions to the structure members. ‘pJobInput’ is the member, that will contain the ‘Data’ to be processed. In our case its simply the for loop index. Finally ‘StopThreadPool’ is being called to shutdown the threadpool gracefully.

Header File (.h)

CThreadPoolEx m_ThreadPoolManager;

void MemberFunctionWorkerProc( LPVOID pDataIn_i );

Implementation File (.cpp)

void GlobalWorkerProc( LPVOID pDataIn_i )
{…}

// Worker function [ A global function ]that will call backed by the thread pool manager
void CThreadPoolManagerDlg::MemberFunctionWorkerProc( LPVOID pDataIn_i )
{…}

// Initialize the thread pool first
if( !m_ThreadPoolManager.InitializeThreadPool( m_nWorkerThreadCount ))
{…}

void CThreadPoolManagerDlg::OnButtonStartJobs()
{

    // Create the job item and set the worker and call back functon
    // Which is same for all the worker procedure
    THREAD_POOL_JOB_ITEM JobItem;

    CREATE_MEMBER_FUNCTION_CALLBACK( CThreadPoolManagerDlg::MemberFunctionWorkerProc, JobItem );

    bool bNotInitialized = false;
    int nIndex;
    for( nIndex = 1; nIndex <= m_nJobsToPush; ++nIndex )
    {
        // Add the job input to the job item
        JobItem.pJobInput = (LPVOID)nIndex;      
        // Add the job item to the job queue
        m_ThreadPoolManager.EnQueue( JobItem );
    }
}

void CThreadPoolManagerDlg::OnButtonStartJobsNonmember()
{
    // Create the job item and set the worker and call back functon
    // Which is same for all the worker procedure
    THREAD_POOL_JOB_ITEM JobItem;

    CREATE_FUNCTION_CALLBACK( GlobalWorkerProc, JobItem );

    bool bNotInitialized = false;
    int nIndex;
    for( nIndex = 1; nIndex <= m_nJobsToPush; ++nIndex )
    {
        // Add the job input to the job item
        JobItem.pJobInput = (LPVOID)nIndex;      
        // Add the job item to the job queue
        m_ThreadPoolManager.EnQueue( JobItem );
    }

    return;
}

void CThreadPoolManagerDlg::OnButtonStopThreadPoolMgr()
{
    // Stop the thread pool gracefully
    m_ThreadPoolManager.StopThreadPool();
}

Demo – Code Download

Download the complete source code from here.

Note: We’ve provided two version of thread pool classes. ‘CThreadPool’ and ‘CThreadPoolEx’. In the former version, we are creating all the worker thread at once during the startup of the thread pool. So a pre defined number of threads will always be available during startup. In the latter version, a single worker thread will be created during the startup of the thread pool. Later, as requests get queued and there is no free worker thread available to process the request, additional worker threads will be created on the fly.

Tuesday, August 26, 2014

Type1 (Bare Metal) Hypervisor for Desktops/Laptops–XenClient

 
Note: This product has been discontinued by Citrix. The below package is no more available for Download!
 
For a long time, Type1 (Bare Metal) hypervisors are reserved for server environments. They are known for speed, consistency and stability during heavy loads. They are the only hypervisors that provides ‘near native’ performance. Typically Type-1 hypervisors are not available or used under traditional desktops/laptops due the the below reasons.
 
A. Issues with Type1 hypervisors (For Desktop usage)
1. No GUI for Type-1 Hypervisors
Type1 hypervisors are installed to a machine, without any GUI. Most often the physical host machine (In which hypervisor has installed) will be controlled by a terminal/client installed on a second machine. This is perfect for a server scenario, where most of the time, the machines are sealed inside Datacenters and managed remotely.
This setup is not at all viable for a desktop/laptop machine, as user will be directly interacting with the machine.
2. Hardware compatibility
Desktops/Laptops are offered by a diverse list of manufacturers, than any server counter parts. So there is a huge effort for supporting all these diverse hardware environment, to any hypervisors targeting desktops. This is not the case with servers, as there are a few vendors manufacturing servers, as compared to personnel computer industry.
So typically Desktops/Laptops lives with Type2 hypervisors like Virtualbox, VirutalPC, VMWare Workstation e.t.c. Though KVM can be considered as a Type1 hypervisor, that statement is not completely true, as it requires an host OS to be present.
B. A true Type1/Bare Metal Desktop Hypervisor – XenClient
Does this means, desktops has to live with only Type2 hypervisors?
The answer is ‘No’, as Citrix has now come up with a BareMetal/Type1 hypervisor for desktop/laptop environments. It is a “Type1 BareMetal Desktop Hypervisor”. The product is ‘XenClient’. More specifically the hypervisor is called ‘XenClient Engine’.
The product can be used free, for managing up to 10 virtual machines. It has the following advantages that are typically required for any desktop/laptop environments and that are not available in server environments.
i. Hypervisor is integrated with GUI, for managing virtual machines.
The hypervisor comes with a GUI frontend, by which we can create and manage virtual machine. So a single machine can be used to host virtual machine as well as managing them using GUI.
Also remote management is possible with client products installed on other machines.
j. Additional utilities are available.
One good thing with this desktop edition is, it contains ‘Google Chrome’ browser. It’s a must utility that every desktop can’t live without.
C. Download and Configure – XenClient in your desktop
XenClient is free for use (To create/manage up to 10 virtual machines), though it requires registration.
Go to XenClient Home Page and click on ‘Download Now’ button. You many need to create an account next, by providing a valid email id and other details. Once done you will redirected to the ‘XenClient’ download page.
image
image
Download ‘XenClient Enterprise Engine’ ISO file (See above fig.). Now burn it to a DVD and use it for installation. The installation procedure can be found in the manual, Please read it carefully. Normally the setup will install into the first available free space in the first hard disk and format it with LVM partition format (logical volume manager).
For experimental usage, we’ve installed ‘XenClient’ as a KVM Guest, as KVM supports nested virtualization. To install XenClient engine as a KVM guest, you can find the procedure here. Below given the screenshots from our XenClient Engine installed as a KVM Guest.
image
For more management capabilities, we can use ‘XenClient Synchronizer’, that can be installed into any windows machine (.NET Framework should be installed). The free usage allows us to manage at most 10 virtual machines.

Installing KVM in Lubuntu14.04 with Nested Virtualization Support

Virtualization can be quite useful. Rather than disrupting our base system, we can create virtual machines, try things out, snapshot it, restore back and throw away once done. We can try out a new update’s stability in a virtual machine, before applying to your physical machine. Also we can run other OS’s along side with your OS of choice, like running Windows 8.1 along side of your Ubuntu installation without a reboot. In virtualization terms, our physical computer will be called as Host and the virtual machines created are called ‘Guests’. The software that provide virtualization capability to your physical computer, is called Hypervisor.

Hypervisors are categorized in to Type1 (Bare Metal) and Type2.

Type1 will be directly installed to the ‘Host’ machine and it does not requires any existing operating system to work. It will directly talk to the hardware and will manage virtual machines.  So Type1 hypervisors are special OS’s, that are specifically designed for virtualization tasks. So they provide ‘near native’ performance for virtual machines. Examples are VMWare ESXi, XenClient and XenServer.

Type2 requires an existing ‘OS’ installation and will be installed on top of it. For managing physical hardware resources, Type2 hypervisors will talk to the installed OS (Called Host OS), and Host OS will in turn talk to the hardware. So due to this double indirection, Type2 hypervisors are bit slower than Type1. Examples are VirtualBox, VMWare Workstation and VirtualPC.

There are certain OS’s that are neither Type1, nor Type2, like KVM. In fact KVM is sometime called as Type1, but it does requires an existing OS installation to work. The KVM Hypervisor module itself is implemented as a ‘Kernel Module’ and hence, it might be providing near native performance. Still user space tools are required to manage virtual machines like ‘libvirt’ and ‘qemu-kvm’, that are installed on top of the Host OS.

Whether it’s Type1 or Type2, most of the Hypervisors are designed to use ‘Hardware Assisted Virtualization’ to boost ‘Guest machine’s’ performance. In other terms they make use of your physical computer's processor virtualization extensions (AMD-V for AMD processors, and Intel-VT for Intel processors), to improve ‘Virtual Machine’ performance. This requires ‘Virtualization Extension’ to be supported by your ‘Processor’ (And it does for all recent Intel/AMD processors) and need to be enabled under your ‘BIOS’. Certain hypervisors (like Virtualbox) can work without ‘Hardware Assisted Virtualization’, and that scenario is called ‘Full Virtualization’ where performance will be much lower.

Some of the Hypervisors strictly requires ‘Hardware Assisted Virtualization’ to be available and enabled in BIOS and is recommended as well. Example XenClient, VMWare ESXi.

OK, that’s all about virtualization and hypervisors. Now consider an extreme scenario. You want to virtualize a Hypervisor itself! That means you would like to install a Hypervisor inside an Hypervisor and the nested Hypervisor demands ‘Virtualization Extensions’. This scenario requires the Hypervisor running on the Host, should be able to pass through the ‘Virtualization Extension’ (AMD-V, Intel-VT) to the nested Hypervisor (i.e The Guest Hypervisor, which is running as a virtual machine). This is called ‘Nested Virtualization’. Using this technique, you can test various Hypervisors in virtual environment, before the actual deployment to checkout the features and limitations. You can try create virtual machines inside the nested hypervisor, which itself is a virtual machine. Sounds interesting right?

For common purposes, we heavily use Virtualbox (A Type2 Hypervisor), as it is quite simple to setup and have a very friendly GUI for managing virtual machines. But it lacks on ‘Nested Virtualization’ support for the guests.

Recently we’d to virtualize a Bare Metal hypervisor, named ‘XenClient’ that mandates ‘Processor Virtualization Extensions’ to be available on it’s virtual host (i.e Virtual machine, on which ‘XenClient’ got installed).

XenClient is a ‘Bare Metal’ Type-1, hypervisor specifically designed for Desktops and Laptops. Though the hardware support is somewhat limited for older version, the compatibility base is now getting better with the latest versions. XenClient requires ‘Processor Virtualization Extensions’ to be available and it has one more additional requirement, It does requires hard disk to be attached to SATA Controller. It does not support IDE controller for hard disks.

So to virtualize XenClient, we cannot use Virtualbox, as it does not support nested virtualization. We cannot use ‘VMWare Workstation’ either, as it does not support SATA controllers, though it supports nested virtualization.

As per our experience, we found that ‘KVM’ (Kernel Virtual Machine) is the best option for such nested virtualization scenarios, where you want to run a Hypervisor as a guest inside a Hypervisor. KVM does allows nested virtualization through some minor tweaks. It also supports SATA controllers for hard disks. KVM is by default available in mainline Linux kernel. The below steps explains, setting up KVM in Lubuntu14.04 host with Nested Virtualization features.

1. Check whether, your processor support ‘Virtualization Extensions’? (Intel-VT/AMD-V)

Run the following command in the terminal.

“egrep -c '(vmx|svm)' /proc/cpuinfo”

If 0 it means that your CPU doesn't support hardware virtualization. If 1 or more it does - but you still need to make sure that virtualization is enabled in the BIOS.

Alternatively, you may execute: “kvm-ok”. This should return the below.

INFO: /dev/kvm exists
KVM acceleration can be used

2. Install KVM and Management Tools

Use the below command line to install the Qemu emulation layer and the virtual machine manager.

“sudo apt-get install qemu-kvm libvirt-bin virt-manager bridge-utils”

Add the current user to the ‘libvirtd’ group.

“sudo adduser `id -un` libvirtd”

3. Enable Nested Virtualization In KVM

By default nested virtualization is not enabled in KVM, It needs to be activated explicitly. First try check its already enabled by you previously, by issuing the below command;

cat /sys/module/kvm_intel/parameters/nested

If the output is ‘N’. Then enable it by issuing the below command.

echo 'options kvm_intel nested=1' >> /etc/modprobe.d/qemu-system-x86.conf

We’re done setting up KVM. Now only thing remember is to enable ‘Nested Virtualization’ while creating a virtual machine using ‘Virt-Manager’, that is explained in the next step.

3. Created a virtual machine with Nested Virtualization Support.

In this exercise, we’re installing ‘XenClient’ (A Type1, Bare Metal Desktop Hypervisor) as a guest in KVM. Create a virtual machine and install ‘XenClient’. Before install, ensure the below settings, for the virtual machine.

Ensure ‘vmx’ settings as ‘require’. This enables the nested virtualization available to the KVM guest.

image

Below are the settings specifically required for ‘XenClient’.

Ensure, Virtual disk is attached to ‘SATA’ controller.

image

Ensure, Video model as ‘VMVGA’. NB: This is important, ‘XenClient’ only seems to detect this video model only under KVM.

image

Here you are! Below figure shows our successfully installed and running ‘XenClient’ as a KVM Guest.

image

Note: If you’re getting the below error while starting a nested guest, inside XenClient, check XenClient system requirements and verify your hardware compatibility. Your processor, chipset, and BIOS settings should support VT-x and VT-d (For inter processors) and must be enabled.

image

4. Appendix.

Read more on KVM installation in Ubuntu here.

Read more on configuring Nested KVM under Ubuntu14.04 here.

Saturday, July 26, 2014

Interconnecting (Bridging) LAN with VirtualBox Host Only Adapter–Lubuntu/FatDog64

In this article we will discuss about interconnecting the Wired Ethernet with the VirtualBox’s Host Only network. But why think about such a scenario? See the below points that are our specific requirements.

a. VirtualBox Guests should be visible in the Physical LAN, like any other physical device attached to the network

b. Guest Machines should be able to acquire dynamic IP addresses from the DHCP server attached in the LAN

b. We should be able to RDP, the Guest, by directly specifying its name or IP Address

c. Guests should be able to directly access, network resources like a network share, Printer connected to LAN

d. Guests should be able to communicate with each other, even if the physical LAN cable is unplugged in the host machine

Note: We can use ‘bridged Adapter’ in VirtualBox UI (See below figure), to bridge the physical network, with the virtual box network. But the problem is, once the Physical LAN cable is unplugged, the guest should see their virtual network as unplugged as well, and they will not able to communicate with other Guest machines that resides in the same host machine itself.

image

e. Guest should have only one ‘Virtual Network Adapter’ be configured in the VirtualBox UI, for easy management.

Note: We can have multiple network adapters to handle this situation. Like one adapter (configured as host only) for communicating among only with guests and another adapter (Bridged to physical network, like in the above figure) to communicate  out side of the host machine. But we feel it as a less streamlined solution, as we’ve to manage 2 separate adapters inside the guest machine only for handling this scenario.

Being said that, we can now look into a solution on how to achieve this. Typically the solution will be, bridging the Ethernet (eth0) with the Virtualbox’s host only adapter (vboxnet0).

This article assumes, the below prerequisites.

i. You’ve a working Ubuntu (Or its derivatives) or FatDog64 Full installation (Like one discussed here)

j. You’ve a working VirtualBox installation and the Host only adapter have been created.

image

Note: Installing latest virtualbox in FatDog64 full install is discussed here.

k.Bridge Utility is available with your installation

Note: FatDog64 installation already contains ‘bridge-utils’. For ubuntu, use ‘apt-get install bridge-utils’ command.

The below figure, help us to grasp the over all picture.

image

Ok that’s all about the environment, now we will look into the implementation.

1. Bridge Physical LAN/Ethernet with VirtualBox’s Host Only Adapter

Please remember to replace the IP Addresses, Subnetmask, default gateway as per your environment.

In our case, we are using static IP’s for both our bridge (192.168.1.200) and vboxnet0 (192.168.1.201). Our default gateway is a ‘iBall Router’ (192.168.1.1) . For our virtualbox guest VM’s and other PC’s connected to LAN, IP address will be served by the ISC-DHCP-Server, as it is configured to listen through ‘br0 eth0’, on its own configuration file.

1.1 FatDog64 Implementation

Add the below script segments to the very end of ‘/etc/rc.d/rc.local’ file.

vboxmanage hostonlyif ipconfig vboxnet0 --ip 192.168.1.201 --netmask 255.255.255.0

brctl addbr br0
ifconfig eth0 0.0.0.0 down
ifconfig vboxnet0 0.0.0.0 down
brctl addif br0 eth0
brctl addif br0 vboxnet0
ifconfig eth0 up
ifconfig vboxnet0 up
ifconfig br0 192.168.1.200 netmask 255.255.255.0 up

route add default gw 192.168.1.1

#uncomment, if you've setup ISC-DHCP-Server, and not relying on Virtualbox built in DHCP Server
#/usr/local/etc/ISC-DHCP-Server/dhcp-server start

1.2 Ubuntu Implementation

Add the below script segments to the end of ‘/etc/rc.local’ file, just before the ‘exit 0’ statement.

sudo vboxmanage hostonlyif ipconfig vboxnet0 --ip 192.168.1.201 --netmask 255.255.255.0

sudo brctl addbr br0
sudo ifconfig eth0 0.0.0.0 down
sudo ifconfig vboxnet0 0.0.0.0 down
sudo brctl addif br0 eth0
sudo brctl addif br0 vboxnet0
sudo ifconfig eth0 up
sudo ifconfig vboxnet0 up
sudo ifconfig br0 192.168.1.200 netmask 255.255.255.0 up

sudo route add default gw 192.168.1.1

#uncomment, if you've setup ISC-DHCP-Server, and not relying on Virtualbox built in DHCP Server
#sudo restart isc-dhcp-server

2. Configure VirtualBox Guest Machines, with Host Only Adapter

Now for each virtual machine, that should be directly exposed to the physical LAN, Select ‘Host-Only Adapter’ and ‘vboxnet0’, in the Virtual machine’s Network property page.

image

Once done, these machines will be exposed to the physical LAN, like every other physical machine attached to it.

Advantages:

You can create network shares inside, the virtual machine and can be accessed directly across other physical machines attached to the LAN and vice versa.

Virtual Machines can be configured for ‘DHCP’ and will be able to lease dynamic IP addresses from the actual physical DHCP server hosted on the network. This is worth, if you’re managing a large number of virtual box guest machines (i.e Configuring static IP addresses, default gateway to each one is a tedious and time consuming). This is a versatile design, if you’re going for a failover mechanism once the default gateway is down and you want to redirect all traffic to another router.

You can directly connect to the virtual machines, from any where in the network using its IP or Host Name.

Even if the physical network cable is unplugged in the Host Machine, virtual machines hosted on the same virtual box host machine, will be able to communicate with each other, as the bridge will still work inside the host machine.

3. Verify that Virtual Machine is directly exposed in Physical Network

You can verify this, in many ways. Like you can check whether virtual machine is getting a valid IP from your DHCP-Server. In our case, we’ve done the below:

We’ve created a read only ‘samba share’ in our virtual box host machine (Lubuntu Installation). Now from our virtual machine (Windows 7), we’ve tried to access the ‘samba share’ in the host machine, using it’s UNC path. Like (\\HostMachineName\ShareName). Now we’ve been able to view and browse the network share contents without any issues as below.

image

Appendix: Setting up a Bridge in Linux Variants – A generic Approach

Though the above article describes on bridging between LAN and Virtualbox host only network in specific, bridging concept is a generic term that is not specific to any specific virtual network adapter implementation.

Bridge works at the Data Link Layer (Layer2) of the OSI network model. Bridges inspect incoming traffic and decide whether to forward or discard it. An Ethernet bridge, for example, inspects each incoming Ethernet frame - including the source and destination MAC addresses, and sometimes the frame size - in making individual forwarding decisions.Bridges serve a similar function as network switches that also operate at Layer 2. Traditional bridges, though, support one network boundary (accessible through a hardware port), whereas switches usually offer four or more hardware ports. Switches are sometimes called "multi-port bridges" for this reason.

In Linux, we can define bridges in two places, so that they are functional at the very startup of the system.

Method A: (rc.local)

One is, as described in the above article ‘rc.local’ file. The above example can be extended to have a generic approach, that can bridge any network interfaces in theory (Both physical and virtual network interfaces). For example a virtual network adapter, created with the KVM Virtualization utility can be bridged along with Virtualbox Host Only Adapter. We can define that generic approach as below.

brctl addbr br0 

#for each interface $iface in the list to be bridged
; do
#ifconfig $iface 0.0.0.0 down
#brctl addif br0
$iface 
#done

#for each interface $iface in the list to be bridged ; do
ifconfig $iface up 
#done 

ifconfig br0 <IP> netmask <subnetmask> up
 

In the above example, a base bridge (br0) has been setup and we are adding each network interfaces (that is to be bridged) using a ‘For Loop’ (each interfaces will be iterated through the variable ‘$iface’). The ‘$iface’ can take any network interface, including the ‘VirtualBox host only adapter-vboxnet0’ as in the above example.

Method B: (/etc/network/interfaces)

There is one more streamlined approach to define bridges. Similar to defining network interfaces in ‘/etc/network/interfaces’ file, we can also define bridges as well in that file. As sample is given below.

auto br0
              iface br0 inet static
                  address 192.168.1.200
                  network 192.168.1.0
                  netmask 255.255.255.0
                  broadcast 192.168.1.255
                  gateway 192.168.1.1
                   bridge_ports
eth0 vboxnet0
                   bridge_maxwait 0

The above snippet does the same thing as we’ve done with the ‘rc.local’ example in the entire article. See how ‘eth0’ and ‘vboxnet0’ has been bridged using ‘bridge_ports’ element. You can include many more options in this way, like bridging every network interfaces available in one go. Read more on this page.

Note: Direct bridging will only work with wired Ethernet (eth0) and vboxnet0. If you’re using wireless physical adapter (wlan0), then you may have to do some extra configurations (like hostpad) to make it work. You should probably start here.

Thursday, July 24, 2014

Setting up DHCP Server in FatDog64

In this article we will look into DHCP Server installation with FatDog64 full install. By default, FatDog64 comes with the DnsMasq package, which can be configured as a basic DHCP server. You can find plenty of articles on how to setup DnsMasq as a DHCP Server, here, here and here. But if you need a full blown and dedicated DHCP Server with advanced options, use ISC-DHCP-Server, which is a free package from Internet System Consortium.

This article assumes, you already owns the below:

a. A True Full Install of FatDog64

If you’re not, you can follow this tutorial to have a fully working install.

b. Development Libraries have been setup for your installation

If you’re not, you can follow step #4 to #7 in this article to have the build environment ready for your FatDog64 installation.

c. Kernel Sources and Headers have been setup for your installation

If you’re not, you can follow step #4 to #7 in this article to have the build environment ready for your FatDog64 installation.

 

Ok lets dive into the implementation.

1. Download ISC-DHCP-Server Source from Internet System Consortium

Note: You can read more on installation from here (Official link)

Download it from this official page. Scroll to bottom, expand ‘ISC-DHCP’ section, then you can see the different versions that are available for download. We took the current version. For convenience here is the direct link to the download,  which starts the download instantly.

image

Put the downloaded archive file (dhcp-4.2.6.tar.gz) in ‘/Packages’ folder.

image

Now extract the contents.(Right Click->Extract Tarball)

2. Build ISC-DHCP-Server Source Code

Go inside the extracted folder and open a terminal there. Type in the below command.

“bash ./Configure”

This command will identify your linux installation and verify the build environment. If everything work fine it will recommend you to make your build. Otherwise you’ve to trouble shoot the issues.

image

Once the configure returns successfully, make the sources using below command.

“make”

image

‘make’ will take some time, so be patient.

3. Install ISC-DHCP-Server

Once ‘make’ command returns, install it using,

‘make install’

image

This will install your DHCP server and copies the ‘dhcpd’ to ‘/usr/local/sbin/dhcpd’.

4. Download and Integrate Custom Scripts to manage ISC-DHCP-Server

Now we need to have some custom scripts to manage the DHCP server, like start, stop and restart the server as a daemon. For your convenience, we’ve shared the scripts here. Just download it to ‘/Packages’ folder.

Note: We’ve inspired by the scripts available in Lubuntu, and rebuilt it based on those.

Now extract it to the same folder.

image

image

Move into the extracted folder and Type in the below commands

“cp –a ./* /”

image

Now the ISC-DHCP-Server installation is ready with your FatDog64. Now you’ve to edit it’s configuration as per your system environment.

5. Configure ISC-DHCP-Server settings

Navigate to ‘/usr/local/etc/ISC-DHCP-Server/Config’ folder.Open ‘DHCP-Server.conf’ file.

image

Now as per your environment, update the sub-net settings in this configuration file. Basically setting up the sub-net information with DHCP server, is a major topic on it’s own respect. If you’re new to this, this article will provide you a fare introduction to start with. Or you can refer the original ISC documentation here. 

If you’re feeling difficult to follow those documentation, the below settings will be fare enough for your environment, that will be discussed in detail here.

See the lines, which are marked in green. The first line starts with ‘subnet’ defines, one subnet to which our DHCP server should serve IP addresses. The defined subnet (192.168.1.0), is a ‘Class-C’ network address, that represents the subnet (i.e all addresses with the last octet as 0, is the address of the network itself). Now the second line (starts with ‘option routers’, define the gateways for your network. i.e Your primary router’s IP address. This can be your FatDog64 installation, if its directly connected internet. Or it can be of your Router Device’s, that’s connected to the internet. In our case, it’s a ‘iBall ADSL Router’, with IP 192.168.1.1. This is our primary gateway to internet. Again ‘domain-name-servers’ will be the same as our gateway.

Now the ‘range’ section, define the range of IP’s, that will be served by the DHCP server, to the clients. In our case, IP’s range from 192.168.1.51 to 192.168.1.59, will be served. So a total of 9, clients can be served.

Note: you can configure multiple subnets. The official documentation describes that in details.

image

Now close the file. Move to the parent folder, and open ‘Env.conf’ file.

image

Now edit the ‘INTERFACES’ variable to point to your network interface name, through which the DHCP server should listen for DHCP requests and serve IP’s. You can easily check your network interface name using the command ‘ifconfig’ in the terminal. Most often it will be ‘eth0’. If you’ve more than one network interfaces, you can list it here, with a space in between, like “eth0 eth1 br0”.

image

Below figure will help you to understand our current environment, that we’ve described in the example above.

image

6. Test your ISC-DHCP-Server settings

Now it’s the time to test your DHCP server. Open up a terminal in the same folder and issue the below commands.

‘bash dhcp-server start’

‘bash dhcp-server restart’

‘bash dhcp-server stop’

First command will start the server. Second command is to restart the server and the third one to stop the server. If you’ve done it all well, you should get the responses as in the below figure.

image

7. Configure ISC-DHCP-Server on Startup

Now configure the DHCP Server to run on startup, by adding the below line to ‘/etc/rc.d/rc.local’.

“/usr/local/etc/ISC-DHCP-Server/dhcp-server  start”

image

image

8. Verify ISC-DHCP-Server Installation

Now you can fire up any PC’s connected to your network, which can be configured to get it’s IP through DHCP and verify that, it is getting a valid IP from your DHCP server, by looking into the ‘/var/db/dhcpd.leases’ file.

In our case, we’ve configured a windows XP, PC to get it’s address through ‘DHCP’ and verified that it leases valid IP address from the DHCP Server.

As you can see below, the Windows XP PC, got the first available IP address (192.168.1.51). It also got the correct ‘subnet mask’, Default Gateway Address, DNS Server Address details (Which are configured as per step#5, in the configuration files of DHCP-Server). Also please note, the IP Address of the ‘DHCP Server’ is listed as 192.168.1.50, which is our FatDog64 installation. The default gateway is ‘192.168.1.1’, which is the ‘iBall Router’.

image

image

Sunday, July 20, 2014

Avoid Spinning Down Hard Disks During Restarts – FatDog64 Full Installation

FatDog64 is an excellent OS with an incredible boot speed (< 6 Seconds) and very light on resources (<95MB RAM usage on startup). You can achieve this using the Full Installation Option of FatDog64 described here.

Everything went perfect after the full install, except one. FatDog6 seems to spin down the hard disks even during a restart. But we would expect spinning down the hard disks only during a shutdown. For testing new updates and procedures, we often want to restart the FatDog64 every now and then (Some time 15+ time a day!).

Frequent spin down and spin up of hard disks have the following disadvantages.

1. More importantly, It can easily shorten the life span of the drive.

2. The restart will be slower, as the BIOS has to wait for the hard disks to be spin up and available during boot.

Note: That’s why we’ve opted to, not to spin down disks even in power save or sleep mode as well. You can save a bit of power on a cost of your hard drive.

So the solution will be, during the restart mode, FatDog64 should only unmount the drives. And during an actual shutdown, it should unmount and spin down the disks. Unfortunately FatDog64’ does not support this setup, as it may not be able to distinguish between a Restart/Shutdown mode.

The reason is, Fatdog64 uses busybox init, and busybox init has no state (or "runlevel" like a full-fledged sysv init or openrc). As far as busybox init is concerned, "shutdown" and "reboot" is the same thing and they behave identically. This is clearly mentioned in this discussion forum. Thanks to ‘James Bond’ for clarifying this.

So the solution is not rely on the FatDog64’s native Restart/Shutdown option, but customize it to our own, to distinguish the Restart/Shutdown mode. The custom solution is defined as below.

Solution: We need to update the ‘/etc/rc.d/rc.cleanup’ script, so that ‘Spin Down’ operation should only be invoked during a shutdown only. But there is some way to let this script know, what’s the mode for which it has been called for. Either for shutdown or for a restart! For this we need to write two separate script files. One for shutdown and one for restart. In our custom ‘Restart’ script, we will create a temporary file named ‘Restart.txt’ in ‘/tmp’ location and then invoke the reboot operation. Then we will update ‘rc.cleanup’ script in such a way that, if ‘/tmp/Restart.txt’ exists, then it will skip the ‘Spin Down Disks’ operation. Then in our custom ‘Shutdown’ script, we will delete the temporary file ‘/tmp/Restart.txt’, if it exists and then will invoke the shutdown operation. So in ‘rc.cleanup’, the script will unable to find ‘/tmp/Restart.txt’ file and hence it will ‘Spin Down Disks’ as usual.

Now for a restart and shutdown, we will only use these custom ‘Shutdown’ and ‘Restart’ scripts files. We will not use the normal Shutdown and Restart menu items in FatDog64.

Ok lets implement the solution now.

1. Create ‘Restart.sh’ script

Create the script on the desktop and make it executable.

image

Put the below as the only script content.

image

2. Create ‘Shutdown.sh’ script

Create the script on the desktop and make it executable

image

Put the below as the only script content.

image

3. Update ‘rc.cleanup’ script

Open ‘/etc/rc.d/rc.cleanup’ in your favorite editor.

image

At the very top of the file (See below) just add the below script code marked in green. This code is basically checking for the existence of ‘/tmp/Restart.txt” file and set a boolean flag to 1 (if the file exists) or 0 (if the file does not exists). Remember, we’ve created this temp file with in our custom ‘Restart.sh’ script file, and the restart operation in turn invoked ‘rc.cleanup’.

image

Scroll to the bottom position of the ‘rc.cleanup’ file, that contains the ‘Spin Down Disks’ section. Below we’re changing the console message properly, based on the current mode (shutdown/restart) it has called for. If you don’t care about the message display, you don’t have to make this change!

image

NB: Now the most important change! Put the ‘Spin Down Disks’ section, inside an ‘if’ block that will only trigger, during a shutdown operation. During restart ‘if’ block condition will be false, and ‘Spin Down’ wont happen.

i.e Change the below line

$SDPARM -C stop /dev/$dev > /dev/null)

to

#Change - Checking Restart Mode - Start

#$SDPARM -C stop /dev/$dev > /dev/null

if [ $restartFlg -ne 1 ]

then

         $SDPARM -C stop /dev/$dev > /dev/null

fi

#Change - Checking Restart Mode - End

image

4. Now on, Only rely on the custom ‘Restart.sh’ and ‘Shutdown.sh’ scripts for Restart/Shutdown

Now if you would like to shutdown the machine, click on ‘Shutdown.sh’. For restart, click on ‘Restart.sh’. Do not opt the FatDog64’s native menu entries.

5. Download the script files

If you’re having difficulty editing the scripts files on your own, We’ve shared it here. Just download and put them under proper locations.