Subnetting with IPv6 Part 1/2
By Yucel Guven, (c) 2013
Introduction:
We are in the transition phase from IPv4 to IPv6 addressing structure, and network engineers should easily plan their IPv6 addressing /subnetting infrastructure without any error. In this article I tried to explain how IPv6 subnetting works by giving examples. I also wrote and distributed a free IPv6 Subnetting Tool / Calculator using Java JDK 1.7.0.17, and it is based on Swing Application Framework.
It enables you to play with all 128bits of an IPv6 address.
I distributed the application in the hope that it will be useful for your subnet calculations.
Don't hesitate to comment/inform for any bugs or new feature suggestions.
1. How does '/' (slash or prefix-length notation) works with IPv6?
The '/' indicates the bits which are fixed for your subnetwork. Fixed means that you do not have any control on these bits, you must not change them ( I like to call them "don't touch only watch bits").
IPv6 is 128 bits long and your network/organization is assigned "128 minus (/prefix-length Value)"
and these are the bits given under your control. You can do your subnetting with these bits and assign addresses to your computer/car/mobile/etc.
For example, assume that the prefix '2001:db8:1234::/48' is assigned to your network by your service provider (or by RIPE, ARIN, etc). In this case, /48 indicates that starting from the left-most bit up to and including the 48th bit, these bits are fixed and must not be changed (don't touch only watch bits). And the rest of the bits which have the length of 128-48=80bits are given to your control.
So, the importance of '/' prefix-length comes from the point that it indicates the boundary of your network. In other words, from which number your assigned network start and at which number it ends.
2. Finding IPv6 Start and End Addresses of our Subnet:
If we have for example 192.168.3.0/24 subnet prefix, then 24 bits are fixed. You must not change these bits. And our netmask will be 255.255.255.0, we can do subnetting by using 32-24=8bits by taking care of subnet and broadcast addresses, as we all know very well with our IPv4 experience.
2.1 Three useful Bitwise Operators: &, |, ~
& (AND), | (OR), ~ (NOT or bit INVERTER) : We will use these three bitwise operators in our calculations.
I think everybody knows their "truth table" and how they operate. I will not explain them here again.
If you like you can search for 'bitwise operators'.
Now how can we find our subnets and starting and end addresses of it? We can easily calculate them with the help of these three bitwise operators as follows. I will try to demonstrate on both IPv4 and IPv6.
With IPv4:
What is our mask if we have '/24'? it is simply 255.255.255.0 which is 24 bits all 'set' or 'all one' starting from the left-most bit up to and including 24th bit.
Finding Start Address is just 'AND' your address with your mask which is:
(192.168.3.5) & (255.255.255.0) = 192.168.3.0 This is our Starting Address, or as we call
Network address.
Finding End Address is 'OR' your address with the inverted (NOT) mask which is:
(192.168.3.5) | ~ (255.255.255.0) = 192.168.3.255 This is our End Address, or as we call
Broadcast address.
With IPv6:
What is our mask if we have '/48'? Simply it is ffff:ffff:ffff:: for which all 48 bits are 'set' or 'all one' starting from the left-most bits up to and including 48th bit. As you can see the evaluation way of the mask is exactly same as in IPv4. As for our IPv6 subnet prefix '2001:db8:1234::/48', again same calculation method applies. It is also useful to remember that we always use 'hexadecimal' instead of decimal numbers for addressing since IPv6 is completely based on hexadecimal numbers. So,
Finding Start Address is just 'AND' your address with your mask which is:
( 2001:db8:1234:: ) & ( ffff:ffff:ffff:: ) = 2001:db8:1234::
(you can also try for other addresses, e.g. (2001:db8:1234:abcd::ef ) & ( ffff:ffff:ffff:: ) = 2001:db8:1234:: again same result.)
Finding End Address is 'OR' your address with your inverted (NOT) mask which is:
(2001:db8:1234:: ) | ~( ffff:ffff:ffff:: ) = 2001:db8:1234:ffff:ffff:ffff:ffff:ffff
As a result, for the subnet-prefix '2001:db8:1234::/48' we have the range or interval of our subnet:
IPv6 Starting Address of subnet > 2001:db8:1234:0:0:0:0:0 (or compressing zeros 2001:db8:1234:: )
IPv6 End Address of subnet > 2001:db8:1234:ffff:ffff:ffff:ffff:ffff
Also remember that we don't have broadcast mechanism in IPv6, so we don't have broadcast address.
3. How can we do subnetting with our IPv6 subnet-prefix?
As we know, our first prefix-length indicates our fixed bits and we can borrow bits starting from (but excluding) prefix-length value towards the right-most bit (from left to right).
Example:
Let's use the subnet-prefix '2001:db8:1234::/48', and borrow 2 bits for subnetting.
The beauty of number conversion shows itself when we do hexadecimal to binary conversion.
When converting from hex-to-binary or vice versa, you can simply and directly convert each hex-digit into binary form without caring about the digit weights. In hexadecimal notation each hex-digit corresponds to 4 bits, usually called as 'nibble'. In expanded form, our example address is 2001:db8:1234:0:0:0:0:0
And in 4-bit binary form (or with nibbles) it is;
2 0 0 1 : 0 d b 8 : 1 2 3 4 : 0 0 ... (all the rest zeros)
0010 0000 0000 0001 : 0000 1101 1011 1000 : 0001 0010 0011 0100 : 0000 0000 ... (all the rest zeros)
Let's borrow 2 bits starting from /48 (excluding 48. bit) up to /50 (we include 50.bit) :
0010 0000 0000 0001 : 0000 1101 1011 1000 : 0001 0010 0011 0100 : 0000 : 0000 : ... (all the rest zeros)
By borrowing 2 bits, we can have 2^2= 4 unique subnets, which are:
1) 0010 0000 0000 0001 : 0000 1101 1011 1000 : 0001 0010 0011 0100 : 0000 0000 ... (all the rest zeros)
2) 0010 0000 0000 0001 : 0000 1101 1011 1000 : 0001 0010 0011 0100 : 0100 0000 ... (all the rest zeros)
3) 0010 0000 0000 0001 : 0000 1101 1011 1000 : 0001 0010 0011 0100 : 1000 0000 ... (all the rest zeros)
4) 0010 0000 0000 0001 : 0000 1101 1011 1000 : 0001 0010 0011 0100 : 1100 0000 ... (all the rest zeros)
Let's convert these numbers back into hexadecimal and see the result:
1) 2001:db8:1234:0000::/50 (First subnet)
2) 2001:db8:1234:4000::/50 (Second subnet)
3) 2001:db8:1234:8000::/50 (Third subnet)
4) 2001:db8:1234:c000::/50 (Fourth subnet)
If you are a service provider, you can assign these subnet-prefixes to your customers one by one with '/50' prefix-length, e.g. 2001:db8:1234:0000::/50 for one customer, and 2001:db8:1234:4000:/50 for other, etc.
And now your customers should know the End of their assigned address space. At this point remember 'Finding Start and End addresses of our subnet' and perform the bitwise calculations.
First of all, your customers will have mask of '/50' which is all 50 bits 'set' or all 50 bits are 'ones' giving us the mask of ' ffff:ffff:ffff:c000:: '. Now using this mask we can easily calculate the start-end addresses, i.e. the range or interval of our subnet. Let's do it one by one.
1st. Customer subnet Start address=
(2001:db8:1234:0000:: ) & ( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:0000:0:0:0:0 = 2001:db8:1234::
1st. Customer subnet End address=
(2001:db8:1234:0000:: ) | ~( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:3fff:ffff:ffff:ffff:ffff
2nd. Customer subnet Start address=
(2001:db8:1234:4000:: ) & ( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:4000:0:0:0:0 = 2001:db8:1234:4000::
2nd. Customer subnet End address=
(2001:db8:1234:4000:: ) | ~( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:7fff:ffff:ffff:ffff:ffff
3th Customer subnet Start address=
(2001:db8:1234:8000:: ) & ( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:8000:0:0:0:0 = 2001:db8:1234:8000::
3th Customer subnet End address=
(2001:db8:1234:8000:: ) | ~( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:bfff:ffff:ffff:ffff:ffff
and
4th Customer subnet Start address=
(2001:db8:1234:c000:: ) & (ffff:ffff:ffff:c000:: ) = 2001:db8:1234:c000:0:0:0:0 = 2001:db8:1234:c000::
4th Customer subnet End address=
(2001:db8:1234:c000:: ) | ~( ffff:ffff:ffff:c000:: ) = 2001:db8:1234:ffff:ffff:ffff:ffff:ffff
Notice that each of the subnet-prefixes can also be used again to perform subnetting.
For example 4th customer may use the subnet-prefix '2001:db8:1234:d000::/50' to do subnetting by borrowing bits again say from /50 to /54, according to their needs of course.
Summary
In order to find the starting and end address of your subnet, you only need to know IPv6 address and prefix-length value.
Remember this bitwise operation (which is also valid for IPv4):
(IPv6 Address) & (/prefix-length mask) is equal to (IPv6 subnet Start address), and
(IPv6 Address) | ~ (/prefix-length mask) is equal to (IPv6 subnet End address).
Subnetting with IPv6 Part 2/2.
By Yucel Guven , (c) 2013
About This Application
First start by checking the entered value to see either the user entered a valid IPv6 address or not.
For this purpose the function IsAddressCorrect() gets the entered string, and does the necessary checks on it,
and returns either 'true' or 'false' boolean value depending on the check result.
If the entered value is a valid IPv6 address, then we need to formalize the entered address into 16 Bytes hexadecimal value in order to perform our calculations on it. The function FormalizeAddress() gets a valid IPv6 address as string, inserts the necessary amount of zeros if the address is compressed, and returns 16 Bytes formal IPv6 address in related data type.
These two functions might also be combined in a general class library to validate and formalize an IPv6 address but I did not do it here. Instead I wrote them in a separate class, for the sake of keeping the functions of the application simple and visible.
As I try to explain in the 'Subnetting with IPv6' article, it is easy and obvious to find the subnet start and end addresses of a given address by using the /prefix-length value. The function StartEndAddresses() takes an IPv6 address and returns the subnet start and end addresses that the address belongs to.
Another issue is how to find the neighbor subnet addresses, or subnets that just comes after our subnet? In other words, how can we move or walk through the neighboring subnet address spaces?
Very easy and simple way of achieving this is to get the end address, and increment by one which gives the start address of the next subnet address. By using this start address, find the end address, then increment by one which will give the next subnet address, and so on. As you notice we are now able to move or walk through the subnet address spaces with this algorithm.
An iterative procedure to obtain the next subnet addresses might be:
Step1. Get the IPv6 address
Step2. Find the subnet start address
Step3. Find the subnet end address
Step4. Increment the subnet end address by one
The start address of the next subnet obtained.
Step5. Go to step 3 with the address found in Step 4.
An example approach might be:
public SEaddress StartEndAddresses(SEaddress input) {
BigInteger mask = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);
mask = mask.shiftRight(input.slash);
input.End = mask.or(input.Resultv6);
mask = mask.not();
input.Start = mask.and(input.Resultv6);
return input;
}
where SEaddress is a storage object:
public class SEaddress {
public BigInteger Resultv6 = BigInteger.ZERO;
public BigInteger Start = BigInteger.ZERO;
public BigInteger End = BigInteger.ZERO;
public int slash = 0;
public int subnetslash = 0;
public BigInteger subnetidx = BigInteger.ZERO;
}
For the subnetting, we borrow the bits by using the second slider or track bar. Despite we can easily find our subnets, now another question is what is the index number of our subnet and how can we find the index number of it? i.e. is it 4th subnet, or 5th, or 6th, or which?
The answer is inside the address itself and we can extract this index number from the address.
Actually, using the second slider, i.e. borrowing the bits, we are creating the subnet index numbers, too.
The interval between the two sliders has our subnet index number. For example, if we drag the first slider to /48 and the second slider to /52, it means that we borrow 4-bits and created 2^4=16 different subnets having index values from 0 to 15. So how can we handle finding the index value in our application? We can copy the bits in this interval by means of testing the bits and then setting it into our index variable.For testing the bit we can perform the bitwise operation (number &(1<< i ) ), where i is an integer to shift. If the result is 1 then the bit at that position is 1, otherwise it is zero.
The code might be :
input.subnetidx = BigInteger.ZERO;
int delta = input.subnetslash - input.slash - 1;
for (int i = (127 - input.slash); i > (127 - input.subnetslash); i--) {
if (input.Start.testBit(i) == true) {
input.subnetidx = input.subnetidx.setBit(delta);
} else {
input.subnetidx = input.subnetidx.clearBit(delta);
}
delta--;
}
Up to this point, we know how to find the subnet start/end addresses and subnet indexes. What is left is to produce these values in a simple for loop with an 'upto' limit variable.
for (count = 0; count < upto; count++)
{
subnets = Subnetting(subnets);
//Displaying etc...
subnets.Start = subnets.End.add(BigInteger.ONE);
}
Happy IPv6 subnetting!