LANMAR for IPv6

advertisement
LANMAR for IPv6
Jason Chen, Teresa Breyer
Tutor: Zeng-Zhong Lee
1. Introduction and Background
1.1 LANMAR
LANMAR is a routing scheme for wireless ad-hoc networks [1] which combines the
ideas of both Fisheye State Routing (FSR) and Landmark Routing. Groups of nodes that
move similarly are formed into a logical subnet and each such subnet elects a Landmark
node to represent the group. Each node has, in addition to its physical identifier (e.g.
Ethernet address), a logical identifier which consists of a subnet and a unique host field
within the subnet. Each node stores Link State information and a Time Stamp for each
destination within fisheye scope, as well as the Next Hop and distance to all known
destinations within the scope and to each Landmark node as well. A node exchanges Link
State only with nodes in its scope and the rate with which Link State packets are sent
decreases as the hop distance increases. Consequently routes within Fisheye scope are
accurate, and as hop distance increases, accuracy of the routing information degrades.
The major difference to FSR is that in LANMAR the routing table includes only nodes
within scope and all landmark nodes. This improves scalability by reducing the Routing
Table size. Typically all members in a logical subnet are within fisheye scope. However,
nodes that are out of the scope are called Drifters. However, a packet to a destination
within neighbor scope is routed directly using the local routing table. A packet to a
destination out of scope is routed towards the corresponding Landmark using the subnet
field of the destination to look up the next hop in the landmark routing table. Once the
packet reaches a node within the scope of the destination, the direct route to the
destination can be found in that forwarding node’s local routing table and that route is
applied. This means that a packet does not necessarily need to pass through the
Landmark. [7] of a destinations subnet to reach the destination.
Landmark
Logical Subnet
1.2 IPv4 versus IPv6
In IPv4 addresses consist of 4 bytes or 32 bits. Each byte is written as a decimal number
between 0 and 255 separated by a dot. That means there are 4,294,967,296 possible IP
addresses. Initially these IPv4 addresses were split into four different classes. Addresses
between 1.0.0.0 and 127.255.255.255 are class A, addresses between 128.0.0.0 and
191.255.255.255 are class B, addresses between 192.0.0.0 and 223.255.255.255 are class
C, and between 224.0.0.0 and 239.255.255.255 are all Multicast addresses. The network
field of A addresses has 7 bits, of B addresses 14 bits and of C addresses 21 bits. So
obviously A and B addresses are in high demand and there is actually a shortage of IPv4
addresses. There have been several solutions proposed to alleviate this problem. The most
efficient, but most difficult to deploy, is to increase the number of bytes used to represent
an IP addresses as proposed in IPv6.
IPv6 addresses consist of 16 bytes or 128 bits, so they are four times as long as IPv4
addresses. That means there are more than 3.4*1038 such addresses. There are 3 types of
IPv6 addresses, unicast, anycast, and multicast.
Unicast addresses are used for sending a unicast message from one interface to another
interface. Multicast addresses are to send a packet to each member of a group of nodes.
This multicast solution was proposed to replace broadcast in IPv4. Anycast addresses are
used for sending packets to the closest node, distance wise, out of a set of nodes.
An example of an IPv6 addresses has the format of:
2128-1: 0xffffffffffffffffffffffffffffffff
This is not very legible, so a separator is inserted after every 16 bits, and the leading 0x
may be omitted:
2128-1:ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff
ffe80:0000:0000:0000:0202:2dff:fe2e:3ad6
Also, one sequence of adjacent 16 bit blocks of 0’s may be omitted using the double
colon:
fe80::0202:2dff:fe2e:3ad6
Finally, the leading zeros of each block can be omitted:
fe80::202:2dff:fe2e:3ad6
Below one can see the differences in the IPv4 and IPv6 headers. While the IPv4 header is
20 bytes plus up to 40 bytes of options, the IPv6 header is 40 bytes by default [7].
IPv4:
32 bits
ver head. type of Total length
len service
16-bit identifier flgs fragment
offset
time to protocol
IP header
live
checksum
source IP address
20 bytes
destination IP address
Options (if any)
Data
Figure 1.1
-IPv4 packet header.
IPv6:
Version Priority
Payload
Length
Flow
Label
Next
Header
Source Address (16 bytes)
Destination Address (16 bytes)
Figure 1.2
-IPv6 packet header.
1.3 Operating System
Hop
Limit
The system that was used for our implementation was Mandrake 2.4.3 kernel. The Linux
kernel series 2.2.x cannot be used, because it is not IPv6-up-to-date [4]. Thus, only
kernels later than 2.2.x may be used for any implementations using IPv6
To load the IPv6 module use the command:
# modprobe ipv6
To verify that the IPv6module was loaded correctly simply execute the following test:
# lsmod |grep -w 'ipv6' && echo "IPv6 module successfully
loaded"
1.4 Linux commands
To view the routing table in IPv4 the following command is used:
# route
In IPv6:
# route –A inet6
To view the IPv6 addresses the same command as in IPv6 may be used:
# ifconfig
The IPv6 address can be found directly under the IPv4 address using this.
2. Implementation
2.1 Introduction
As mentioned in the first section, two complementary and cooperating routing schemes
are used to form LANMAR. These schemes were implemented using three concurrent
threads. A local “myopic” proactive routing scheme that operates within limited scope
centered at each node and exchanges route information about nodes up to only a few hops
corresponds to Fisheye Scope. A long haul distance vector routing scheme that
propagates the elected landmark of each subnet and the path to it into entire network
takes care of the global routing. Within our implementation Routing Information Protocol
(RIP) was used but other routing protocols may be used as well. The first thread is used
for sending these RIP messages. The second thread is used for sending information about
Landmarks between nodes. The third thread is a common thread for receiving RIP and
LANMAR messages and processing there messages accordingly.
Since LANMAR is a proactive routing protocol, periodic routing update messages are
sent. Landmark routing control packets have the following format:
<LM_Address, LM_NextHop, LM_Distance, LM_Members, Seq#>
Landmark routes are advertised to all nodes, so these packets are also sent to all nodes as
well. In comparison, local routing control packet have this format:
<Address, NextHop, Distance>
Routes to destinations that are not Landmarks are only advertised to nodes within the
scope. In our implementation the default maximum hop distance is set to 2 hops from any
given node.
When a message is received, a subnet mask is used to extract the group ID from a node’s
IP address. Landmark election is performed only among nodes in the same LANMAR
group. The subnet masks used for IPv4 and IPv6 are implemented as follows:
LANMAR Group ID
IPv4
Subnet
Mask
Version
XXXXXXXX
11111111
11111111
48 bits
IPv6
Network ID
Subnet
Mask
Node ID
XXXXXXXX XXXXXXXX
11111111
16 bits
Grp ID
00000000
64 bits
Node ID
00000000………0000000 111…11 000000……………………000000
Figure 2.1 & 2.2
-The two figures show how the subnets of nodes are calculated given a nodes IP address in both IPv4 and
IPv6.
In the IPv4 implementation the first 24-bits of the nodes IP address are used to elect the
LANMAR group ID. However, in IPv6 the last 16-bits of the first half of the IP address
are used thus taking advantage of the fact that IPv6 has dedicated this selection to
identify the groups ID of an IP address.
The Unicast Routing Table stores routing information for all unicast routing protocols
running on router. For LANMAR the Routing Table has two sub tables, a Local routing
table which is flat without the concept of a group or subnet, and the Landmark routing
table keeps one entry from each group (subnet).
2.2 Challenges
2.2.1 Data Structures
Various data structures are different for IPv4 and IPv6 [6].
For socket addresses the following structure
struct sockaddr_in6 {
sa_family_t sin6_family; /*AF_INET6*/
in_port_t sin6_port; /*Port number*/
uint32_t sin6_flowinfo; /*IPv6 traffic class and flow
information*/
struct in6_addr sin6_addr; /*IPv6 address */
uint32_t sin6_scope_id; /*Set of interfaces for a
scope*/
}
replaces
struct sockaddr {
sa_family_t sin_family; /*AF_INET*/
in_port_t sin_port; /*Port number*/
struct in_addr sin_addr; /*IP address*/
}
Here one can see that not only were new elements added to the structure, but also the
types of some of them have changed. E.g. the type that stores an IP address has become
struct in6_addr instead of struct in_addr. Below we can see that struct
in6_addr has a member called s6_addr, which is an array of sixteen unsigned
char, while in_addr has a member called s_addr of type unsigned int. This
means that all occurences of ==, =,!=, <, >, &,and | operators that can be used for
s_addr as a uint32_t can not be used for s6_addr which is a uint8_t array.
struct in6_addr {
uint8_t s6_addr[16];
}
typedef unsigned char uint8_t;
struct in_addr {
in_addr_t s_addr;
}
typedef uint32_t in_addr_t;
typedef unsigned int uint32_t;
To overcome this problem a library performing all these operations was required. Here
are the definitions of all the functions:
void uintcpy(uint8_t array1[],
const uint8_t array2[],
int n);
This function copies the elements of array2 into array1.
int uintcmp(const uint8_t array1[],
const uint8_t array2[],
int n);
This function returns -1 if array1 < array2, 0 if array1 = array2, 1 if array1 >
array2.
void uintand(uint8_t result[],
const uint8_t array1[],
const uint8_t array2[],
int n);
This function stores bitwise & of array1 and array2 in result.
void uintor(uint8_t result[],
const uint8_t array1[],
const uint8_t array2[],
int n);
This function stores bitwise | of array1 and array2 in result.
int uintzero(const uint8_t array[],
int n);
This function returns 1 if array is all 0s, and 0 otherwise.
2.2.2 Multicasting
For Multicasting IPv4 uses:
struct ip_mreq {
struct in_addr imr_multiaddr; /* multicast group to
join */
struct in_addr imr_interface; /* interface on which
to join */
};
The following syntax is used for IPv6:
struct ipv6_mreq {
struct in6_addr ipv6mr_multiaddr; /* IPv6 multicast
address */
unsigned int ipv6mr_interface;
/* interface index;
0 =>
* pick a default interface
* that supports IP
multicast*/
};
Again the new type in6_addr for storing IPv6 addresses is used. Also instead of the
actual interface, which was also of type in_addr, an integer storing the index of the
interface is used. In IPv4, to use the default interface the option the interface had to be
sent to inaddr_any, while in IPv6 the index is simply set to 0.
Also Multicast options changed from IPv4 to IPv6. IP_MULTICAST_LOOP specifies
whether or not subsequent IPv4 datagrams are looped back, giving the sender explicit
control. Here is an example:
u_char loop;
/* 0 = disable, 1 = enable (default) */
setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
sizeof(loop));
For IPv6 this option becomes IPV6_MULTICAST_LOOP and the syntax is the
following:
u_int on = 0; /* 0 = disable, 1 = enable; default = 1 */
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
&on, sizeof(on)) < 0){
perror("setsockopt IPV6_MULTICAST_LOOP ");
}
Here, in addition to appending ‘6’ to the options there is also a minuscule difference that
has a major impact. The type of the variable indicating whether datagrams are looped
back changed from u_char to u_int. If this minor change is not fixed, even though
the variable is set to 0, datagrams will be looped back to the sender.
To join an IPv4 multicast group, the option IP_ADD_MEMBERSHIP was used, such as
in:
struct ip_mreq mreq;
setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
sizeof(mreq));
In IPv6 this simple becomes IPV6_ADD_MEMBERSHIP, and the corresponding IPv6
structures are used.
struct ipv6_mreq imr6;
imr6.ipv6mr_interface = if_index;
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
(char *)&imr6, sizeof(imr6)) < 0) {
perror("setsockopt IPV6_JOIN_GROUP");
}
2.2.3 Functions
Some functions that only support IPv4 addresses had to be replaced with the newer
versions that support both [8] IPv4 and IPv6. Address and protocol family constants are
used to indicate whether IPv4 or IPv6 will be used. AF_INET6 stands for the IPv6
address family, and PF_INET6 for the IPv6 protocol family. They replace AF_INET
and PF_INET which correspond to IPv4.
gethostbyname() retrieves the network host entry referenced by a host name with an
IPv4 address. This had to be replaced with gethostbyname2(), which retrieves the
network host entry referenced by a host name and its address family, which will be
AF_INET6 .
inet_addr() interprets a character string representing an address in Internet dot
notation (IPv4) and returns a value suitable for use as an Internet address.
inet_pton() performs the same operation for both IPv4 and IPv6 address notations.
This is the synopsis for both these functions:
in_addr_t inet_addr(const char *cp);
char *inet_pton(int af, const char *src, void *dst);
af specifies the address family and src points to the presentation-format address. The
format of the address is interpreted according to af. dst points to the buffer into which
the converted address is stored.
While inet_addr returnes the address, inet_pton stores the result in the buffer
pointed to by dst and returns 1 if successfull, 0 if the address was not parsable in the
specified address family, and -1 otherwise. inet_ntoa() interprets an IPv4 internet
address and converts it to a character string. inet_ntop() performs the same
operation for both IPv4 and IPv6 addresses. The following is the synopsis for both
functions:
char *inet_ntoa(struct in_addr in);
char *inet_ ntop(int af, const void *src, char *dst, size_t
size);
in is the internet host address to convert. af specifies the address family and src
points to the address. The format of the address is interpreted according to af. dst
points to the buffer where the converted address is stored. size is the size of dst, in
bytes.
The inet_ntoa() function returns a pointer to the network address in Internet
standard dot notation. On success, the inet_ntop() function returns dst,
otherwise it returns a null pointer
2.2.4 Routing Table and IP address configuration
The IPv6 addresses for the local interfaces are found in the file /proc/net/if_inet6 after the
IPv6 module has been loaded. The format of this file is:
00000000000000000000000000000001 01
Figure 2.3
10
80
01
lo
- Format of the file /proc/net/if_inet6
The following is a list of the functions of each of the columns enumerated from left to
right:
1.) IPv6 addresses in 32-bit hexadecimal.
2.) Interface device index number in hexadecimal.
3.) IPv6 address prefix in hexadecimal.
4.) Scope value.
5.) Flags set.
6.) Device name.
The IPv6 routing table can be found in the file /proc/net/ipv6_route. The format of the
file is:
00000000000000000000000000000000
00000000000000000000000000000000
Figure 2.4
00
00000000000000000000000000000000
ffffffff
00000001 00000001 00000000
-Format of the file /proc/net/ipv6_route
*All of the information is given on a single row in the actual file. It is given in two rows here because of
formatting constraints.
The following is the list of what the fields are for enumerated from left to right and top to
bottom:
1.) IPv6 destination addresses given in 32-bit hexadecimal.
2.) Destination prefix given in hexadecimal.
3.) IPv6 source address given in 32-bit hexadecimal.
4.) Source prefix given in hexadecimal.
5.) IPv6 next hop address given in 32-bit hexadecimal.
6.) Metric in hexadecimal.
7.) Reference count.
8.) Use count.
9.) Flags set.
10.) Device name.
As one can see there are various changes to the IPv6 routing table from the IPv4 routing
table. One challenge that the new routing table presented was the introduction of the
00
lo
prefix fields for both the destination and the source addresses. The prefix could not be
calculated from the IP after masking it because of the short cuts that IPv6 uses to
represent addresses (section 1.2) because it is impossible to determine whether the user
wanted a short cut section as part of the subnet or not. Thus, in our implementation the
prefix of the subnet is calculated from the hard-coded LANDMARK_MASK6. Thus, the
developer can specify all the bits that are to be used in the mask without short cuts which
makes calculation of the prefix possible.
Another issue that the prefix brought about was in the implementation of RIP. IPv4 does
not use prefix’s but rather mask’s. Since this mask field was eliminated from IPv6 a
prefix had to be calculated to add to the IPv6 routing messages before adding it to the
routing table. There were two solutions to this problem. The first solution was to add the
nodes prefix along with the IP address to the RIP messages. This would have worked but
this would require that RIP messages be larger to accommodate the prefix. Thus, another
solution was proposed that the prefix of all IP addresses that are received by RIP all have
the prefix of 128. This solution works since the unicast address of any node will require
that all 128 bits of the address be used to determine the correct node. Also, this solution
would not require extraneous modifications to the RIP messages.
2.2.5 Adding, Deleting and Updating Routes.
Changes had to be made to the IPv4 implementation so that the system knew to make
changes to the IPv6 routing table instead of the IPv4 one. The linux command ioctl
was used in the IPv4 implementation to send routing commands to the kernel. This
function is still used in the IPv6 implementation but instead of sending it struct
rtentry this is replaced with struct in6_rtmsg otherwise everything else
remains unchanged. The format of the structure is as follows:
struct in6_rtmsg
{
struct in6_addr rtmsg_dst;
struct in6_addr rtmsg_src;
struct in6_addr rtmsg_gateway;
u_int32_t rtmsg_type;
u_int16_t rtmsg_dst_len;
u_int16_t rtmsg_src_len;
u_int32_t rtmsg_metric;
unsigned long int rtmsg_info;
u_int32_t rtmsg_flags;
int rtmsg_ifindex;
};
Clearly, there are numerous changes to the routing message that the kernel receives to
update the table. One note worthy change to the routing message is that the IPv6 message
no longer takes the name of the interface device in a char* but now it take the index of
the device thus the index of the device must be found within the application and
explicitly added to the in6_rtmsg structure before calling ioctl with the new
routing message.
3. Conclusion & Future work
This project proved to be a great challenge given the fact that documentation of IPv6 was
scarce in addition to being very parse. The greatest implementation challenge was simply
determining how changes from IPv4 to IPv6 would affect other parts of the
implementations. The most obvious example of this would be replacing the old IPv4
addresses with the new IPv6 addresses. Not only did the syntax have to be changed
throughout all of the code to accommodate IPv6 addresses but this change also affected
how the landmark subnet was calculated. Also, this affected how IP addresses were
compared (see section 2.1.3), the size of lanmar and routing messages sent to other nodes,
and the way messages received by nodes were parsed. Further more this, affected how
addresses were parsed and represented to the user on top of numerous other minuscule
changes. So as you can see from just this one example a minor change can affect
numerous things and thus this was the axiom throughout the entire project. However, in
the end we were able to complete the entire implementation of LANMAR in IPv6.
Testing of this implementation was done mainly using ping6 and simply outputting all
the packets received by all the nodes to the screen. We were able to test this
implementation with variations on three nodes thus allowing us to verify that the
implementation followed the LANMAR scheme as expected. However, large amounts of
traffic with a large sample of nodes were not tested nor were samples taken of round trip
time or throughput and thus these are areas for future work.
References
[1] G. Pei. M.Gerla, and X. Hong, " LANMAR: Landmark Routing for Large Scale
Wireless Ad Hoc Networks with Group Mobility, " In Proceedings of IEEE/ACM
MobiHOC 2000, Boston, MA, Aug. 2000.
[2] Xiaoyan Hong,Li Ma, Mario Gerla, " Multiple-Landmark Routing for Large Groups
in Ad Hoc Networks, " In Proceedings of MILCOM 2002 Military Communications
Conferences, Anaheim, CA, Oct.7-10,2002.
[3] Kaixin Xu,Xiaoyan Hong, and Mario Gerla, " Landmark Routing in Ad Hoc
Networks with Mobile Backbones, " In Journal of Parallel and Distributed Computing
(JPDC), Special Issues on Ad Hoc Networks, 2002.
[4] http://www.tldp.org/HOWTO/Linux+IPv6-HOWTO/
[5] http://keetweej.vanheusden.com/~folkert/porting_ipv4_to_ipv6.html
[6] http://www.opengroup.org/onlinepubs/007904975/basedefs/netinet/in.h.html
[7] Lecture slides from cs118 and cs218
http://www.cs.ucla.edu/classes/spring03/cs118/slides.html
http://www.cs.ucla.edu/classes/fall03/cs218/slides.html
[8] http://www.mkssoftware.com/docs/man3/inet_pton.3.asp
http://www.mkssoftware.com/docs/man3/inet_addr.3.asp
http://www.mkssoftware.com/docs/man3/inet_ntop.3.asp
http://www.mkssoftware.com/docs/man3/inet_ntoa.3.asp
Landm
ark
routing
table
[9] http://sources.redhat.com/ml/libc-hacker/2002-10/txt00000.txt
[10] http://www.linux.org/docs/ldp/howto/Linux+IPv6-HOWTO/proc-net.html
[11] Structures for new routing entry in IPv6
http://sources.redhat.com/ml/libc-hacker/2002-10/txt00000.txt
[12] Yeng-Zhong Lee “How to implement routing protocols on Linux”
Download