Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Wednesday, May 26, 2010

Avoid Kmail Editor And Use Vim Editor Instead

Kmail has bad editor when it comes to sending patches inlined. More often the message gets mangled (word wrapped). To overcome this problem Kmail allows the use of external editor.

1. Settings->Configure Mail and Click on Composer
2. Click on "Use External Editor" and specify the editor as "xterm -e vim -f %f"
3. Click Apply.

Open the composer and type in mail id and subject and click on the body. When you start typing a new editor window opens up which is vim. Type in your message and type ":wq". Thats it.

For people intending to send patches, use :vsplit and use visual method to highlight and 'y' to yank the highlighted message. Close the vsplit and type "p" to paste it.

Monday, August 3, 2009

Dumping kernel page tables

Sometimes when debugging kernel issues, you might come across kernel addresses that you would find very difficult to map to a particular section in the kernel, ie, vmalloc, vmemmap, low/high kernel mapping, kernel text, etc. On x86, Arjan van de Ven has written an interface that provides a dump of the kernel page tables which gives information on the various memory areas in the kernel.

# cat /debug/kernel_page_tables
---[ User Space ]---
0x0000000000000000-0xffff800000000000 16777088T pgd
---[ Kernel Space ]---
0xffff800000000000-0xffff880000000000 8T pgd
---[ Low Kernel Mapping ]---
0xffff880000000000-0xffff880000200000 2M RW GLB x pte
0xffff880000200000-0xffff880040000000 1022M RW PSE GLB x pmd
0xffff880040000000-0xffff8800cfe00000 2302M RW PSE GLB NX pmd
...
---[ vmalloc() Area ]---
0xffffc20000000000-0xffffc20000001000 4K RW PCD GLB NX pte
0xffffc20000001000-0xffffc20000004000 12K pte
0xffffc20000004000-0xffffc20000005000 4K RW PCD GLB NX pte
0xffffc20000005000-0xffffc20000008000 12K pte
0xffffc20000008000-0xffffc2000000d000 20K RW PCD GLB NX pte
0xffffc2000000d000-0xffffc20000010000 12K pte
0xffffc20000010000-0xffffc20000011000 4K RW PCD GLB NX pte
....
---[ Vmemmap ]---
0xffffe20000000000-0xffffe20007c00000 124M RW PSE GLB NX pmd
0xffffe20007c00000-0xffffe20040000000 900M pmd
0xffffe20040000000-0xffffe28000000000 511G pud
0xffffe28000000000-0xffffff8000000000 29T pgd
0xffffff8000000000-0xffffffff80000000 510G pud
---[ High Kernel Mapping ]---
0xffffffff80000000-0xffffffff80200000 2M pmd
0xffffffff80200000-0xffffffff80a00000 8M RW PSE GLB x pmd
0xffffffff80a00000-0xffffffffa0000000 502M pmd
---[ Modules ]---
0xffffffffa0000000-0xffffffffa000a000 40K RW GLB x pte
0xffffffffa000a000-0xffffffffa000f000 20K pte
0xffffffffa000f000-0xffffffffa0016000 28K RW GLB x pte
0xffffffffa0016000-0xffffffffa001b000 20K pte
....
...

Understanding the above output:

o First field indicates the address range of a particular type of area (for example, user space, vmalloc area, kernel space, etc)
o The second field indicates the size of the address range in K,M,G,T units
o The fields following the size of the range have the following meaning:
USR - whether the page being mapped is a user page or not
RW - whether the page is read/write. If not RW, the output would be 'ro' to indicate a read-only page
PCD - Page Cache Disabled - maps a page with caching disabled
PWT - page with Page Write-Through set
PSE - Extended paging enabled - allows large linear contiguous address ranges to be mapped
GLB - Page Global flag - The global flag is set for a page that is frequently used and prevents it from being flushed from the TLB
NX - Page is non-executable, else marked as 'x'
o The last entry indicates the particular level of the page table - pgd, pud, pmd or pte that the region corresponds to

Enable the CONFIG_X86_PTDUMP configuration option, along with enabling debugfs. The corresponding kernel code for the interface can be found under arch/x86/mm/dump_pagetables.c

Saturday, May 30, 2009

Simplifying GCC

GCC is the GNU Compiler Collection which provides C, C++ etc compilers. These compilers are used by default in all *nixes .

Here i provide simple command line options which can prove to be quite useful.

  1. The simplest way to use GCC to compile a C source file is

    $ gcc -o test test1.c test2.c

    gcc is the C compiler, test1.c and test2.c are the input C source files and -o lets us specify the name of the output file. Here it is "test". Without the -o option, "a.out" is the default executable that gets created.

  2. The preprocessor:

    $ gcc -E test.c > test.out

    This option, ensures the compilation process stops after the pre-processor has run. This helps us in figuring out issues/problems in macros.


  3. The Compiler:

    $ gcc -c test.c -o test.o

    This option ensures the compilation process completes but doesn't invoke the linker/loader. This is useful if you want to just remove compilation warnings and errors.


  4. Header Files:

    $gcc -c test.c -I /location/of/header/files -o test

    Many a times the headers files you want to use, is located is some other directory. A "bad" practice followed is to include the direct path of the header files in the C src file.
    Instead use this option. It tells the compiler which directories to look in for the mentioned header files. The -I options can be used multiple times for multiple directories where header files are located.

  5. Library Files:

    $ gcc -c test.c -lpthread -L /usr/lib/libpthread


    Another requirement that is frequently required is using standard libraries ( NPTL Threads etc) or non-standard ones (expat etc). '-l' option tells which library to use while linking while '-L' tells where the find this library. In the above example during linking, it will search for pthread library in the dir /usr/lib/libpthread.

  6. Warnings, Errors, etc:

    $gcc test.c -o test -Wall -Werror


    -Wall options shows all warnings that are typically not shown during regular compilation. These errors are easy fixable like "Unused varniables", "implicit function declaration" etc. -Werror options tells the compiler to treat all warnings as errors and stop compilation instantly.
    Sometimes -Werror can be too strict for our purpose. Instead you can treat only certain warnings are errors.
    eg. -Werror-implicit-function-declaration: Treat only implicit function declaration warnings as errors. For more such options check the gcc man pages.

  7. Debugging:

    $gcc -g test.c -o test

    This option activates all the debugging symbols. This is required if one plans to use gdb for debugging (which is mostly the case).

  8. Optimizations:
    $gcc -O2 test.c -o test

    This option lets the compiler optimize the code . -O can take 0,1,2 levels of optimizations.
    More info is available in the man pages of gcc.
These options are the ones that are most frequently used. Obviously there are many more options available . Use them as per your needs and refer the man pages for the exhaustive list of options.

Friday, May 8, 2009

Fix Thinkpad Function Keys/Hot Keys in kde 4.2 (Jaunty)

Function keys doent work by default in kde 4.2. Those who migrate from gnome to kde 4 find it difficult to adjust without the 'fn' keys. The problem is with powerdevil. The new applet does not have options to configure the acpi events. This will exits till powerdevil is fixed. As of now, we can use a python script to handle these events. Make sure python-2.6, python-dbus and python-xlib are installed in your system. Download the script from here or here.
Give exe permission
#chmod +x softkeys.py

Place the script in ~/.kde/Autostart/ and restart your system. The function keys must start working now.

Thursday, April 30, 2009

Create Desktop Shortcuts Using Cmd Line On KDE 4.2

Here is a quick way to create desktop shortcuts for kde 4.2.
/usr/share/applications/ and /usr/share/applications/kde4 contains all the shortcut files (*.desktop).

Just copy what ever you want to ~/Desktop. Thats it!

Tuesday, April 28, 2009

fsck.ext3 Unable to resolve UUID error

I installed Kubuntu 9.04 recently and within a day i ran into a peculiar problem. When i boot my system an error message "fsck.ext3 Unable to resolve UUID=". This error generally happens when there is some information mismatch between what is specified in /etc/fstab and what information the OS gives to fsck utility. In this case, its quite easy to solve the problem.

Enter the root password to enter the Maintenance mode when asked during boot.

(Control - D to continue):

List the partition table of your system.

#fdisk -l

Device Boot Start End Blocks Id System
/dev/sda1 * 1 1913 15361888+ 83 Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2 1914 3186 10225372+ 83 Linux
/dev/sda3 3187 12161 72091687+ 5 Extended
/dev/sda5 3187 9265 48829536 83 Linux
/dev/sda6 9266 11697 19535008+ 83 Linux
/dev/sda7 11698 12161 3727048+ 82 Linux swap / Solaris

#vim /etc/fstab

Verify that each device entry specified in the file matches the correct file-system.This error can occur if FS type is wrongly specified. For example, /dev/sda7 is shown as ext3 FS when it clearly a swap in the above case. Correct such errors and reboot. This should solve the problem.

If the entries are correct then, possible problem lies in the UUID specified in fstab. To solve this problem

Determine the UUID of each and every device mentioned in fstab. This exmaple shows for sda1. Repeat this for all devices.

#vol_id -u /dev/sda1
b056f084-eb83-4374-9635-0b5904ff520a

A line taken from my fstab
# /virt was on /dev/sda1 during installation
UUID=b056f084-eb83-4374-9635-0b5904ff520a /virt ext3 relatime 02

Note that UUID matches the entry in fstab. If there is a mismatch, then the entry shown by fstab must be replaced by vol_id. Thats it! save and reboot. This will solve the problem.

REASON: The problem was solved but i was not sure what caused this problem. On further analysis i was able to narrow down on what caused the issue. Apparently, i did a format of a partition (/dev/sda1) which is NOT the / partition using gpartd. Gpart does not allow formats on mounted partitions, so the tools unmounts the partition and formats it. During this step, udev recognizes the new formated device as a new device and old one being removed(formated). Hence it assigned a new UUID which is now not same the one specified in /etc/fstab. Thats why on reboot i ran into this issue.

Change/Resassign Interface Name In Linux

Depending on the linux distro, the interface name given to network cards differ.
For example, on one distro Intel Giga bit Ethernet card might be detected as eth0 and Broadcom card as eth1 while with another distro this might be reversed. This causes a lot of problem, when one uses automated scripts which hardcode "eth0" and "eth1". In older distros it was matter of changing few network scripts to get this working. One can also use "ip" command to make this change temporarily. But to make it permanent it needs to be changed in udev. Here is how simple it is to change the ethernet names.
NOTE: This is only tested on F-10 and Ubuntu 9.04. Its expected to be the same for other distros. Only the name of the udev script might change.

Edit the rule script:

#vim /etc /udev/rules.d/70-persistent-net.rules

Here the list of n/w adapters and their names are specified!
Change the field NAME="eth0" to NAME="eth1" or vice versa
Remember to rename the other adapter whose name you have borrowed.
Restart the system and you will find the new names interchanged!

Tuesday, September 16, 2008

Adding New Users To vsftpd

I found it rather strange that there arent any good tutorial that can explain how to add new users to vftpd. Google gives few results but most of them are trial and error method. So i decided to write this post after spending 1 hr trying to accomplish this simple task.

#edit /etc/vsftpd.conf or /opt/etc/vsftpd.conf
Open the vsftpd.conf file and search for chroot_list_enable=YES
Make sure it is YES. Do the same for the following variables
chroot_list_file=/etc/vsftpd.chroot_list or /opt/etc/vsftpd.chroot_list
chroot_list_enable=YES
Save and close the file

Create vsftpd.chroot_list in /etc/ or /opt/etc/
Add the username you want to export to ftp.
IMP: The user must already be a system user with a valid passwd. You must be able to find /home/
If the user you want to add is not a system user then create that user first before editing the above file.
#adduser
#passwd

Restart the vsftpd server using /etc/init.d/vsftpd restart or service vsftpd restart
Now you can log into ftp using the new user.

Tuesday, July 22, 2008

Follow up to "Hardy Heron..... Ubuntu's latest!"

Adding two more to the Ugly things in Hardy....

1. If the network cable is not plugged in, while start up the corresponding ethernet drivers for wired network
is not loaded. When i manually modprode it, i still don't see a eth0 interface and dmesg doesn't give any error!!

2. Suddenly, after the recent updates the sound stopped working and kmix started cribbing.
I realized that the snd-hda-intel ( sound driver for intel chipsets) was not loaded.
I had to manually modprobe it in.

This surely bad and takes Ubuntu away from being user friendly. I wonder if a naive user would be able to figure out the problem ..

Thursday, May 1, 2008

end of reiserfs?

Iam not a file system expert so i cannot comment on the standard of reiserfs, but i used it for quite sometime with opensuse. Why am i saying this......well, not sure but when i read about the murder conviction of Hans Reiser i thought its worth a mention in my blog. As i see it, reiserfs4 has been struggling to get into mainline for quite sometime. Mostly due its radical ideas which were non posix compliant , they were rejected. Now with their main developer and architect out of the picture i see this as end of the road for the revolutionary FS. Will the reiser fanboys carry on with the development of reiser4 is to be seen. Its a sad to loose a really good programmer like reiser.

Installing Ubuntu Gutsy on Presario F500

Recently Leena got a new laptop [ Presario F500] . At its base, there is a 64-bit AMD Turion Processor and 1 GB RAM. To add to this there is a Wide Screen [15.4''] and Altec Lansing Speakers. But this is not good enough for Windows Vista [packed by default] to run.

Ubuntu Installs normally except certains glitches.

1. LiveCD causes the system to hang.

  1. Once you see the splash screen of Ubuntu's main menu press F6
  2. You will get the kernel command line, append vga=792 or vga=791 to that line and press Enter or b
  3. Now X server should start and you will see the Ubuntu Desktop
The reason for this hack is probably because it has a widescreen display.

2. Machine during boot up.
  1. Post Installation, your machine will hang because of the above mentioned problem.
  2. In grub edit the kernel command line and the params mentioned above.
  3. This may not be enough for your system to bootup. It wasn't surely enough for me.
  4. I had to remove the params quiet and splash also.
  5. Make these changes permanent once the system boots up by editing the /boot/grub/menu.lst .
NOTE: Removing quiet and splash, although necessary will not show any splash screen while the OS is booting. You will directly see to the login window.

3. Getting Wireless/Compiz working.
  1. Unfortunately Wireless doesn't work out of the box.
  2. You will need the Broadcom wireless binary driver.
  3. Goto Menu System-> Administrator -> Restricted Driver Manager .
  4. It will say Broadcom driver not in use. Select the checkbox associated with it .
  5. It will ask for a link from which to download firmware . You will get it here .
  6. Once the state changes to in use. You are successful.
  7. Similarly to get Compiz working, select the NVidia Driver which is not is use.
    It will download the driver and again once the state changes to in use. You are successful.
  8. This will need a system reboot.
4. Nonfree Flash doesn't work in Firefox.
  1. The non-free Adobe flash player embedded in Firefox will surely not work although package manager will say its installed, as there is no 64bit version yet.
  2. Use gnash [ open source/free flash player] . It works just fine.
  3. People seem to crib about java plugin for Firefox not working on 64bit boxes, but it worked fine for me.
  4. Else just a 32-bit version of Firefox(with 32-bit plugins) . I found a useful HOWTO

References:
1. Tom On Identity
2. Ubuntu's wireless Docs

Monday, April 21, 2008

Default Address Selection Part 1

If you are familiar with ipv6 then you'd be aware that default address selection is a very important concept. It was defined in RFC 3484 . Due to space constraint, i have decided to split this topic into 2 parts. The first part will deal with just introduction and how to use this feature. The second part will explain the kernel/glibc internals involved in this implementation. Hope i will write the second part soon. Its advisable to read the RFC before proceeding. To give a brief idea of what default address selection is, i would like to take an example of a host having multiple ipv6 address and needing to decide which address to be used for communication. For a communication to happen there must be a source address and destination address, but the problem arises when there are multiple source and destination address to select from. IPv6 by default allows a hosts to configure multiple addresses, so there is a need for an algorithm to sort this list. We can broadly classify default address selection into 2 types:

1) Default source address selection
2) Default destination address selection

Say a host A wants to communicate with another host B (can be external/internal system), it needs to know the destination ip of host B. To get the destination ip, a dns query is sent to the configured dns server and the response is taken as destination ip. What if the dns reply has multiple ip's to the same domain name? That is when destination address selection comes into picture. Now that we "somehow" selected the destination ip, we now need to select appropriate source ip. A question that might arise is, why do we need to do that? Cant we just pick the first ip from the list of source ip's and start the communication? The answer is no. This is because IPv6 ip's can be link-local , site-local or global ip. If the destination ip is a global ip and first source ip we select from the list is a link-local ip then obviously the communication cannot happen because of scope mismatch. So we need some intelligent algorithm to select the correct source ip.

Another interesting aspect in destination address selection is to decided which ip to use if the dns query returns an IPv4 as well as IPv6 address. There needs to be some factor to decide this selection. More on all this in Part 2 :-) . So, we have a situation where these addresses are selected based on a certain criteria. By default the criteria's are as per RFC. For most users this should hold good, but what if it needs to be changed? Let's say by default, IPv6 address is given more precedence than IPv4 , but the administrator wants IPv4 as higher precedence. In these cases there needs to be a way to configure source address selection and destination address selection. For this reason RFC defines User Configuration Tables for Source/Destination selection.
Before we go into the configuration tables lets look at a basic fact. The source address selection is implemented in the kernel and destination address selection in glibc. Wonder why? The reason is very simple. Glibc implements dns query api's like gethostbyname and family which triggers the dns query. So it is obvious that this api will get all the replies as well. It makes sense to implement the algorithm in glibc api's.

Lets look at the user configuration tables for both source address selection and destination address selection. There is an interesting article from the glibc maintainer Ulrich Drepper . You can find the article here .

Basic Requirements:

- Linux Kernel 2.6.24 or higher
- iproute2 utilities compiled for 2.6.24 (Check to see if "#ip help" supports 'addrlabel')
Once we have the prerequisites we are good to go.

User Configuration Table For Source Address Selection :
[root@t6018ab-009124035140 ip]# ./ip addrlabel show
prefix ::1/128 label 0
prefix ::/96 label 3
prefix ::ffff:0.0.0.0/96 label 4
prefix 2001::/32 label 6
prefix 2002::/16 label 2
prefix fc00::/7 label 5
prefix ::/0 label 1

This is the default source address user configuration table. The "label" field is a very important aspect of the table. The prefix with lower label value is given higher preference than the one with higher. For example prefix ::1 is given the highest preference when it is prefix label matching.
Lets say we have two prefix of same type
prefix 2003:470:1f00:ffff::4/64 label 8
prefix 2003:470:1f00:ffff::5/64 label 8
Source Address Selection List:
2003:470:1f00:ffff::4
2003:470:1f00:ffff::5
2003:470:1f00:ffff::6

Destination Address
2003:470:1f00:ffff::7

Irrespective of the order of the source address list the ip 2003:470:1f00:ffff::6 will be selected as the correct source candidate since the other two address have a label value of 8 where as 2003:470:1f00:ffff::6 will pass on the rule "prefix ::/0 label 1". Thus the lowest label value will be given higher priority. We can play around with giving different label value to different prefixes. Since source address selection works in conjunction with destination address selection ,we shall look into testing this aspect a little later.

User Configuration Table For Destination Address Selection :

The destination address user configuration table is based on a conf file called gai.conf. This is placed in /etc/. Distros dont place this file here for a certain reason. For more information please read the article by Ulrich Drepper as stated above. In my system the gai.conf file is located in /usr/share/doc/glibc-common-2.6/gai.conf. This file must be coped to /etc/ if you intend to change the default behavior.

A typical gai.conf file



# label
# Add another rule to the RFC 3484 label table. See section 2.1 in
# RFC 3484. The default is:
#
#label ::1/128 0
#label ::/0 1
#label 2002::/16 2
#label ::/96 3
#label ::ffff:0:0/96 4
#label fec0::/10 5
#label fc00::/7 6

#

# precedence
# Add another rule the to RFC 3484 precedence table. See section 2.1
# and 10.3 in RFC 3484. The default is:
#
#precedence ::1/128 50
#precedence ::/0 40
#precedence 2002::/16 30
#precedence ::/96 20
#precedence ::ffff:0:0/96 10
#
# For sites which prefer IPv4 connections change the last line to
#
#precedence ::ffff:0:0/96 100


For destination address selection, two main criteria's to be considered are label and precedence. It must always be remembered that precedence is associated with destination address selection only. Where as label is common for both source and destination address selection. It is for this reason both the tables must remain in sync for correct result.

Testing Destination Address Selection

To test destination selection algorithm we need to write a small program to test it. The best way to test the destination address selection algorithm is to use the examples given in RFC 3484. See section 10.2

Few Requirements:

- Add a entry "multi on" in /etc/host.conf
- Stop the name service caching daemon (service nscd stop)
- Compile the program given below (This will test the result of default address selection)


#include <errno.h>
#include <error.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <sys/socket.h>

char buf[INET6_ADDRSTRLEN];

int
main(int argc, char *argv[])
{
int err;
struct addrinfo *ai;
struct addrinfo hints;
struct addrinfo *runp;
int sock;

memset(&hints, '\0', sizeof(hints));
hints.ai_protocol = IPPROTO_TCP;

// dummy gethostbyname call so that /etc/host.conf is read
gethostbyname(argv[1]);

err = getaddrinfo(argv[1], "", &hints, &ai);
if (err != 0)
error(EXIT_FAILURE, 0, "getaddrinfo(%d): %s", err,
gai_strerror(err));
runp = ai;
while (runp != NULL) {
getnameinfo(runp->ai_addr, runp->ai_addrlen, buf,
INET6_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);

printf("family:%2d socktype:%2d protocol:%3d addr:%s(%d)\n",
runp->ai_family, runp->ai_socktype, runp->ai_protocol,
buf, runp->ai_addrlen);
runp = runp->ai_next;
}

freeaddrinfo(ai);
}




Example taken from section 10.2 of the RFC:
Candidate Source Addresses: 2001::2 or fec0::2 or fe80::2
Destination Address List: 2001::1 or fec0::1 or fe80::1
Result: fe80::1 (src fe80::2) then fec0::1 (src fec0::2) then 2001::1 (src 2001::2) (prefer smaller scope)

The destination address selection will be demonstrated using a example from RFC.
The first step is to add multiple dns entry in the dns server. This is big process, so i will use /etc/hosts file to make things simple (This works similar to dns server replies).

So add the following in /etc/hosts
fec0::1 rockon
2001::1 rockon
fe80::1 rockon

Add source addresses to the interface
#ip -6 addr add 2001::2 dev eth0
Similarly for fec0::2 and fe80::2

Next step is to make sure every destination route added in /etc/hosts must have valid route entry. Else the above will not work.
For Eg : fec0::1 is the destination ip. So the algorithm will choose this only if we have a valid route for this ip.
#ip -6 route add fec0::1 dev eth0
Similarly add routes for the other destination candidates.

To execute the program
#./a.out rockon
family:10 socktype: 1 protocol: 6 addr:fe80::1(28)
family:10 socktype: 1 protocol: 6 addr:fec0::1(28)
family:10 socktype: 1 protocol: 6 addr:2001::1(28)

The result shows the order in which destination addresses are sorted. Rest of the examples can be tried out. The destination user configuration table (gai.conf) can be modified to see different results.


Testing Source Address Selection :


Lets look at how to test source address selection functionality. The best way to do so is to follow the test cases specified in RFC 3484. See section 10.1.
For testing source address selection use ping6.

Example taken from section 10.1 of the RFC
Destination: 2001::1
Candidate Source Addresses: 3ffe::1 or fe80::1
Result: 3ffe::1 (prefer appropriate scope)

Configure IPv6 address for interface eth0
#ip -6 addr add 3ffe::1 dev eth0
fe80::1 can be ignored as you will have by default a linklocal address
Add a valid route to the destination ip.
#ip -6 route add 2001::1 dev eth0
#ping6 2001::1

The result will be destination unreachable if 2001::1 doesnt exits. But thats not our issue. The unreachable message will show what source address is selected. This is how one can test the source address selection algorithm. Try out all the different examples given in RFC.Now, by tweaking the user configuration table as mentioned in "User Configuration Table For Source Address Selection" we can modify the behavior.

Hope this little write was useful in understanding how address selection works. In the part 2 article i will explain how the algorithm work.

Update: Thanks to Brandon for pointing out a mistake in the post. Check comments for details.

Thursday, April 17, 2008

Division Between Users And Kernel Hackers On Git Bisect

The source code management tool git has come under scanner again. This time for a different reason. Flame war's are pretty common in linux community. Everytime there is a divided opinion on certain things, it unlocks a fury of mails from the community guru's. What happened this time is no different. It all started when Mark Lord reported a regression in the network stack. Even after a few mail exchanges it was not clear what the cause of problem was. So the netdev guru's asked Mark to "bisect" and arrive at the culprit patch. Mark responded furiously saying that he didnt have time or inclination to do such a thing. He argued that he was only a bug reporter and is not his job to do the bisection. This triggered the whole issue of who does what. It was exchange of heated arguments over mail and few humorous stories to support the claims. No one can forget the "Doctor Patient" story. To sum up the argument, main focus of this whole episode was who is responsible for such regressions. Lets know a little bit of git bisect. Git bisect is used to find a possible cause of the problem. It works on a simple principle, the bug hunter has to know which kernel is working well and which has bug. For example, 2.6.24 is not having any problem but 2.6.25 does, in this case one can use bisect to choose a version somewhere in the middle of these two release. Once done, the bug is to be verified and if found, git bisect has to be run again with the first half release. To make things easy take the same example as above. Bisecting this showed that 2.6.25-rc4 had the issue. So its now clear that the bug was introduced somewhere between 2.6.24 and 2.6.25-rc4. So running git bisect will narrow down even further and this will continue till we narrow down on a particular commit. This will help identify the bug. But the process is time consuming. To lay fact down plain and simple, git bisect need not necessarily narrow down on the correct patch which causes the problem. There is a possibility that problem was created else where and came into light on introducing this "culprit" patch. So this is not a sure shot way to identify the problem. In our issue Mark states that a user identifying a problem must only report it and that where his/her duty ends. It is upto the individual user to do some more homework and help the developers fix the bug. The developers argue that user will be asked to bisect as a last resort. By forcing users to do more work than just reporting bug can cause them to stop reporting bugs which is not a good thing for the community. On the other hand well known kernel hackers like David Miller claims that it is unavoidable sometimes due to unavailability of hardware the user had used in his environment. This requires the user to cooperate in this effort. As one can see, both side do have a strong point to argue. Its difficult to take sides here. This can become a major issue if not resolved quickly. Some suggestions made by Al Viro and James Morris suggest that the subsystem maintainers need to be more careful in committing patches. This can avoid most regression. Another question that was discussed was, how does a user decide which are "real" bugs? What happens in a complex code like the kernel is, bugs can arise due to some faulty hardware which nobody else faces. When that happens it is virtually impossible to fix it. In such cases the bug remains unfixed. It only come to light if multiple users complain of the same problem. The community urged its users to properly test before posting bugs on the mailing list. The story has not concluded yet as there is no clear solution to this problem. It is left to be seen as to how the community will tackle this issue.

Saturday, February 16, 2008

HOWTO: ipv6-ipv6 tunnel and ip4-ipv6 tunnel in linux

I had an requirement to setup an ipv6-ipv6 tunnel and ipv4-ipv6 tunnel and i found that there were very few howto's that were worth it. So i decided to write this blog to get people started with ipv6 tunneling.



Figure 1


-What is a IPv6 Tunnel?
A tunnel is a virtual device used to encapsulate any type of packet into a network aware packet type. That is, i can send any ipv4 type of packets over an ipv6 network. For more information click here.

-Types of IPv6 Tunnels:
-ipv6 - ipv6 Tunnel (ipv6 over ipv6 tunnel)
-ipv4 - ipv6 Tunnel (ipv4 over ipv6 tunnel)

-
Requirements:
- Any distro with kernel version 2.6.22 or above.
Note : The ipv4 over ipv6 feature was introduced only in 2.6.22 kernel. Older kernels wont work.
- iproute2 package. Most distro's package the "ip" command. It is to be noted that at the time of writing this blog, most distro's with ip command didnt support ipv4 over ipv6. If thats is the case please download the latest packages from here. For the developers, download from the git repo here.

-Steps to create a ipv6-ipv6 tunnel:
1) Configure Host A of Private Network A :
The configurations:
eth0: ipv6 address : 3001:470:1f00:fff::189
The node "Host A" must be having an ipv6 address. Even an linklocal address is ok.
Add the ip address to the interface if it is not configured already.
#ip -6 addr add 3001:470:1f00:ffff::189 dev eth0
#ip -6 route add 3001::/4 dev eth0
Add the default route to reach the router.
#ip -6 route add default via 3001:470:1f00:ffff::190 dev eth0

2) Configure Host B of Private Network B :
The configurations:
eth0: ipv6 address : 5001:470:1f00:fff::189
The node "Host A" must be having an ipv6 address. Even an linklocal address is ok.
Add the ip address to the interface if it is not configured already.
#ip -6 addr add 5001:470:1f00:ffff::189 dev eth0
#ip -6 route add 5001::/4 dev eth0
Add the default route to reach the router.
#ip -6 route add default via 5001:470:1f00:ffff::190 dev eth0


3) Configure Router A : (I Assume that your router is a linux box with 2 interfaces)
The configurations:
eth0 : ipv6: 3001:470:1f00:ffff::190
eth1 : ipv6: 2001:470:1f00:ffff::190
mytun : ipv6 : 4001:470:1f00:ffff::190

The router "Router A" must be having two physical interfaces with a ipv6 address each as shown above .
Add the ip address to the interface eth0 if it is not configured already.
#ip -6 addr add 3001:470:1f00:ffff::190 dev eth0
Add the ip address to the interface eth1 if it is not configured already.
#ip -6 addr add 2001:470:1f00:ffff::190 dev eth1
Add the route for each interface.
#ip -6 route add 3001::/4 dev eth0
#ip -6 route add 2001::/4 dev eth1
Now to setup the tunnel, we need to make sure we have the right module installed.
A simple modprobe will get you going.
#modprobe ip6_tunnel
Incase the above command results in error then check if it is statically compiled. If it is, then your output for "ifconfig -a" must be as shown below.

Figure 2

If you can see 'ip6tnl0' as one of the interfaces then you are good to go. Else you need to enable that module and compile the kernel.

Now, its time to create the tunnel. We assume that eth0 of this router is connected to private network A and eth1 is connected to "IPv6 network". So we create a tunnel associated with eth1.
#ip -6 tunnel add mytun mode ip6ip6 remote 2001:470:1f00:ffff::189 local 2001:470:1f00:ffff::190 dev eth1
Bring up the link of the interface
#ip link set dev mytun up
Assign an address to our virtual tunnel device.
#ip -6 addr add 4001:470:1f00:ffff::190 dev mytun
The most important step is to redirect all the traffic to our tunnel.
#ip -6 route add 5001::/4 dev mytun
Since we are using a normal linux system as router we have to enable forwarding.
#echo “1” > /proc/sys/net/ipv6/conf/all/forwarding

4) Configure Router B : (I Assume that your router is a linux box with 2 interfaces)
The configurations:
eth0 : ipv6: 5001:470:1f00:ffff::190
eth1 : ipv6: 2001:470:1f00:ffff::189
mytun : ipv6 : 6001:470:1f00:ffff::190

The router "Router B" must be having two physical interfaces with a ipv6 address each as
shown above .
Add the ip address to the interface eth0 if it is not configured already.
#ip -6 addr add 5001:470:1f00:ffff::190 dev eth0
Add the ip address to the interface eth1 if it is not configured already.
#ip -6 addr add 2001:470:1f00:ffff::189 dev eth1
Add the route for each interface.
#ip -6 route add 5001::/4 dev eth0
#ip -6 route add 2001::/4 dev eth1
Now to setup the tunnel, we need to make sure we have the right module installed.
A simple modprobe will get you going.
#modprobe ip6_tunnel
Incase the above command results in error then check if it is statically compiled. If it is, then your output for "ifconfig -a" must be as shown in
figure 2.

Now, its time to create the tunnel. We assume that eth0 of this router is connected to private network B and eth1 is connected to "IPv6 network". So we create a tunnel associated with eth1.
#ip -6 tunnel add mytun mode ip6ip6 remote 2001:470:1f00:ffff::190 local 2001:470:1f00:ffff::189 dev eth1
Bring up the link of the interface
#ip link set dev mytun up
Assign an address to our virtual tunnel device.
#ip -6 addr add 6001:470:1f00:ffff::190 dev mytun
The most important step is to redirect all the traffic to our tunnel.
#ip -6 route add 3001::/4 dev mytun
Since we are using a normal linux system as router we have to enable forwarding.
#echo “1” > /proc/sys/net/ipv6/conf/all/forwarding

5) Make sure the Firewalls are appropriately configured on the routers and hosts to allow tunneling. If you are in doubt, disable firewall and try.
6)Now you can ping6 across Node A and Node B via the tunnel.

-Steps to create a ipv4-ipv6 tunnel:
These types of tunnels are typically used in scenarios where we have two private ipv4 network and we wish to access then as same LAN network over an ipv6 internet. Although ipv6 has not yet established its self as the preferred protocol for the internet, its only matter of time. As of now we can find use in offices that have a mixture of ipv6 and ipv4 networks. If two ipv4 networks needed to be combined via an ipv6 backbone we can use this type of tunneling.

1) Configure Host A of Private Network A :
The configurations:
eth0: ipv4 address : 172.16.15.2
The node "Host A" must be having an ipv4 address.
Add the ip address to the interface if it is not configured already.
#ip addr add 172.16.15.2 dev eth0
Add default route showing the gateway as "Router A".

#ip route add default via 172.16.15.1 dev eth0

2) Configure Host A of Private Network B :
The configurations:
eth0: ipv4 address : 192.168.1.2
The node "Host B" must be having an ipv4 address.
Add the ip address to the interface if it is not configured already.
#ip addr add 192.168.1.2 dev eth0
Add default route showing the gateway as "Router A".

#ip route add default via 192.168.1.1 dev eth0

3) Configure Router A : (I Assume that your router is a linux box with 2 interfaces)
The configurations:
eth0 : ipv4:172.16.15.1
eth1 : ipv6: 2001:470:1f00:ffff::189
mytun : ipv6 : 4001:470:1f00:ffff::189

The router "Router A" must be having two physical interfaces with a ipv6 address and a ipv4 as shown above .
Add the ip address to the interface eth0 if it is not configured already.
#ip addr add 172.16.15.1 dev eth0
Add the ip address to the interface eth1 if it is not configured already.
#ip -6 addr add 2001:470:1f00:ffff::189 dev eth1
Add the route for interface eth1.
#ip -6 route add 2001::/4 dev eth1
Now to setup the tunnel, we need to make sure we have the right module installed.
A simple modprobe will get you going.
#modprobe ip6_tunnel
Incase the above command results in error then check if it is statically compiled. If it is, then
your output for "ifconfig -a" must be as shown in figure 2.

Now, its time to create the tunnel. We assume that eth0 of this router is connected to private network B and eth1 is connected to "IPv6 network". So we create a tunnel associated with eth1.
#ip -6 tunnel add mytun mode ipip6 remote 2001:470:1f00:ffff::190 local 2001:470:1f00:ffff::189 dev eth1
Bring up the link of the interface
#ip link set dev mytun up
Assign an address to our virtual tunnel device.
#ip -6 addr add 4001:470:1f00:ffff::189 dev mytun
The most important step is to redirect all the traffic to our tunnel.
#ip route add 192.168.1.0/24 dev mytun
Since we are using a normal linux system as router we have to enable forwarding.
#echo “1” > /proc/sys/net/ipv6/conf/all/forwarding
#echo "1" > /proc/sys/net/ipv4/ip_forward

4) Configure Router B : (I Assume that your router is a linux box with 2 interfaces)
The configurations:
eth0 : ipv4:192.168.1.1
eth1 : ipv6: 2001:470:1f00:ffff::190
mytun : ipv6 : 4001:470:1f00:ffff::190

The router "Router B" must be having two physical interfaces with a ipv6 address and a ipv4 as shown above .
Add the ip address to the interface eth0 if it is not configured already.
#ip addr add 192.168.1.1 dev eth0
Add the ip address to the interface eth1 if it is not configured already.
#ip -6 addr add 2001:470:1f00:ffff::190 dev eth1
Add the route for interface eth1.
#ip -6 route add 2001::/4 dev eth1
Now to setup the tunnel, we need to make sure we have the right module installed.
A simple modprobe will get you going.
#modprobe ip6_tunnel
Incase the above command results in error then check if it is statically compiled. If it is, then your output for "ifconfig -a" must be as shown in
figure 2.

Now, its time to create the tunnel. We assume that eth0 of this router is connected to private network B and eth1 is connected to "IPv6 network". So we create a tunnel associated with eth1.
#ip -6 tunnel add mytun mode ipip6 remote 2001:470:1f00:ffff::189 local 2001:470:1f00:ffff::190 dev eth1
Bring up the link of the interface
#ip link set dev mytun up
Assign an address to our virtual tunnel device.
#ip -6 addr add 4001:470:1f00:ffff::190 dev mytun
The most important step is to redirect all the traffic to our tunnel.
#ip route add 172.16.15.0/24 dev mytun
Since we are using a normal linux system as router we have to enable forwarding.
#echo “1” > /proc/sys/net/ipv6/conf/all/forwarding
#echo "1" > /proc/sys/net/ipv4/ip_forward

5) Make sure the Firewalls are appropriately configured on the routers and hosts to allow tunneling. If you are in doubt, disable firewall and try.
6)Now you can ping6 across Node A and Node B via the tunnel.

With these two methods we can successfully connect ipv4 networks to ipv6.