|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FEEDS SEARCH LINKS CONTACT seb Template by Helquin |
Friday Mar 28, 2008
Configuring an OpenSolaris 6to4 router
A common problem in enterprise networks is that many IT departments have not begun to deploy IPv6 within their supported infrastructure, but developers need IPv6 networking in order to develop and test products which support IPv6. 6to4 (defined in RFC 3056) can be a quick way to obtain IPv6 connectivity between IPv6 nodes separated by IPv4 networks such as this. The general idea is that each 6to4 site has a 6to4 router which is responsible for automatically tunneling IPv6 packets from its site to other 6to4 routers in other 6to4 sites (or native IPv6 networks with the use of relay routers[1]) over IPv4. 6to4, then, can often be the answer for such developers, where configuring a 6to4 router in a lab environment or in a small subnet within an enterprise network is very easy and addresses their basic IPv6 connectivity requirements. OpenSolaris[2] can be used as a 6to4 router, and I've received so many requests for basic instructions on how to configure a 6to4 router with OpenSolaris, that I've decided to write a short blog entry on the subject. Note that while this blog may come in handy, there is in fact official Sun documentation on 6to4 routing [3] which may be even more useful. The following instructions configure a persistent configuration which will be enabled after a reboot of the system. All of this can also be configured similarly on the running system, but it is simpler to give one set of instructions. Experienced administrators will surely know how to interpret these instructions to apply configuration to the running system, and that's left as an exercise to the reader.
At this point, hosts which have IPv6 enabled in the link connected to the 6to4 router's <intf> interface will automatically configure IPv6 addresses based on the advertised prefix, and will have a default route to the 6to4 router. All packets destined off-link to other 6to4 sites will be tunneled to the remote 6to4 routers. <shameless plug>Of course, when the Clearview IP Tunneling Device Driver component delivers to Nevada, one will be able to use dladm(1M) to create a 6to4 tunnel with a meaningful name, and to observe packets in the 6to4 tunnel using snoop(1M), wireshark, or other such tools.</shameless plug> [1] I'm skipping discussing relay routers for various reasons which I won't go into here. [2] In fact, Solaris starting with Solaris 9. [3] Look for 6to4. Within this documentation, there are also instructions on how to configure 6to4 on Solaris, similar to this blog entry. Posted at 01:01PM Mar 28, 2008 by seb in OpenSolaris |
Tuesday Jan 29, 2008
Using New Networking Features in OpenSolaris
The Nemo Unification and Vanity Naming component of project Clearview has integrated into OpenSolaris build 83, which (among other things) allows administrators to give meaningful names to network datalink interfaces, including VLAN interfaces. I thought I'd share how I used this feature on one of our lab routers here in Sun. The system has four Ethernet NICs, but needs to be the router for 8 separate lab subnets. The aggregate bandwidth of four Gigabit pipes is plenty for all of the lab subnets combined, so it wasn't really worthwhile to go and add four more NICs to the system (plus, that's not really scalable). Instead, I created a single link aggregation (802.3ad) including all four Ethernet links, and created individual tagged VLAN interfaces (one for each of the 8 subnets) on top of this aggregation. Step by step, here's what I did. Keep in mind that this is done using a nightly build of OpenSolaris from after January 24th 2008. Here was the list of datalinks on the system before I started changing things (bonus points for anyone who can tell me what kind of system I'm doing this on based on the devices listed below) :-) : bash-3.2# dladm show-link First, I unplumbed all IP interfaces on each of these links by issuing appropriate "ifconfig <intf> unplumb" commands. This was necessary since renaming datalinks requires that no IP interfaces be plumbed above them. I then gave each of these interfaces more generic names. The benefit of doing this is that if we replace the Ethernet cards in the future with cards of a different chip set, we won't have to change the interface names associated with that card (one of the big benefits of Clearview UV vanity naming). bash-3.2# dladm rename-link nge0 eth0 Then I created a link aggregation using these four Ethernet links: bash-3.2# dladm create-aggr -P L2,L3 -l eth0 -l eth1 -l eth2 -l eth3 default0 I named the link "default0" because this is the main untagged subnet for the lab network, and the network to which the default route points. Now the set of links looks like: bash-3.2# dladm show-link The next step was to create the VLAN links on top of this aggregation. Our lab subnets have a color-coded naming scheme, which I used when naming the VLAN links. This is convenient when diagnosing network problems with particular systems, as our DNS naming uses a paralell scheme. For example, if a system's hostname is blue-98, I know to do my network snooping on the "blue" link. Creating the VLAN links was as simple as: bash-3.2# dladm create-vlan -v 2 -l default0 orange0 There is now one link for each subnet in the lab (one untagged link, and seven tagged VLAN links). bash-3.2# dladm show-link I then plumbed IP interfaces in each subnet. For example: bash-3.2# ifconfig orange0 plumb ... Configuring this router also involved configuring IPv4 dynamic routing and forwarding, IPv6 dynamic routing and forwarding, etc. All of these latter steps involved placing the network interface names in some sort of persistent configuration (like /etc/hostname.<intf>, /etc/inet/ndpd.conf, and IP filter rules to name a few). This is where giving meaningful names to network interfaces has the most value. With all of these interface names in various configuration files, we don't want to ever have to go and reconfigure all of those things if the underlying hardware of the system were to change from under them. Before Clearview UV's vanity naming feature, a VLAN interface above the e1000g1 interface would look something like e1000g80001 (for VLAN tag 8), thanks to the moldy "VLAN PPA-hack". This is ridiculous enough as an interface name, but what happens when I replace my e1000g1 card with a Broadcom card which has a device name of bge0? I need to go fetch every piece of configuration on the system that made reference to e1000g1 and e1000g8001, and change everything to bge0 and bge8000. With Clearview UV's vanity naming feature I could have named the link something meaningful like "private1", and assigned the newly added bge0 card that same name (using the dladm rename-link command I showcased above) to keep all of my network configuration intact. Posted at 10:42PM Jan 29, 2008 by seb in OpenSolaris | Comments[4]
Tuesday Sep 25, 2007
Early Access to Clearview IP Tunneling
Earlier today, early access build 74 of Project Clearview was announced to networking-discuss@opensolaris.org and clearview-discuss@opensolaris.org. This build introduces the new GLDv3-based IP tunneling driver to users. With this work, the 6000 or so lines of kernel code that comprised the "tun" STREAMS module is replaced with a GLDv3 driver which is half of that size and has more features. With this driver, IP tunnels in Solaris are now fully observable using snoop: seb# snoop -d ip.tun0 IP tunnels can be given meaningful names (thanks to Clearview vanity naming): seb# dladm create-iptun -T 6to4 -s 10.8.57.44 ipv6gateway0 seb# dladm create-iptun -T ipv4 -s seb -d vpngateway vpn0 IP tunnel links are administered using dladm (although pre-existing ifconfig syntax is still supported for backward compatibility): seb# dladm create-iptun -T ipv6 -s me -d you trans0 We welcome users to bfu these bits and try out the new features. Click here for download instructions and release notes, and let us know what you think by sending us feedback at clearview-discuss@opensolaris.org. Posted at 08:07PM Sep 25, 2007 by seb in OpenSolaris |
Tuesday Jun 14, 2005
How an IP Tunnel Interface Dynamically Adjusts its Link MTU
Tunnel MTU DiscoveryWith the launch of OpenSolaris comes the opportunity to discuss the implementation details behind existing Solaris features. I'd like to share some of the details behind one of my contributions to Solaris 10; the implementation of dynamic MTU calculation for IP tunnel interfaces. Solaris 8 was the first version of Solaris that implemented the IP in IP tunneling mechanism described in RFC1853. It did not, however, implement the "Tunnel MTU Discovery" section of this RFC. Tunneling over IPv6 (RFC2473) was implemented very early in Solaris 10 (and backported to Solaris 9 in Update 1) along with a Tunnel MTU Discovery mechanism that worked for IPv6 tunnel interfaces only. Some mechanism was needed that worked for both IPv4 and IPv6 tunnels, and that was visible to the administrator. One drawback to the IPv6 tunnel implementation of Tunnel MTU Discovery for IPv6 tunnels was that there was no observability into the Tunnel MTU (ifconfig's output always showed some static MTU value that was unrelated to the actual tunnel interface's MTU). This work became more important when customers (internal and external to Sun) started using Solaris' IPsec tunneling to implement VPN solutions. Without proper Tunnel MTU Discovery, things like TCP MSS calculations can take longer to converge to usable values and protocols that don't have any insight into Path MTU (UDP for example) yield unecessary amounts of IP fragmentation. For more on the benefits of Tunnel MTU Discovery, see the two aformentioned RFC's on IP tunneling. Without going into too much detail about the inner workings of the ip and tun modules or every line of code that was changed to implement this feature, I'd like to focus on two aspects of the implementation. The first is the mechanism used by the tun module to obtain path MTU information about the tunnel destination from ip, and the second is the mechanism by which the ip interface's MTU is dynamically changed when the tun module detects a change in the tunnel's link MTU. IRE_DB_REQ_TYPEIn order for the tun module to be able to calculate a useful tunnel MTU, it needs to know the Path MTU of the tunnel destination. The tunnel destination is the IP node we'll send encapsulated packets to when sending them through the tunnel interface. In ifconfig output, it is the "tunnel dst":
# ifconfig ip.tun0
ip.tun0: flags=10008d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST,IPv4> mtu 1480 index 4
inet tunnel src 11.0.0.1 tunnel dst 11.0.0.2
tunnel hop limit 60
inet 10.0.0.1 --> 10.0.0.2 netmask ff000000
In the above example, IP packets forwarded into ip.tun0 are encapsulated into an outer IP header with a source of 11.0.0.1 and a destination of 11.0.0.2. 11.0.0.2 is the "tunnel destination". The Path MTU to the destination is the size of the largest IP packet that can be sent to the destination without being fragmented nor resulting in an ICMP fragmentation needed message. The tunnel MTU of a given tunnel is the Path MTU of the tunnel destination plus any tunneling overhead (encapsulating IP header and perhaps IPsec headers if IPsec tunneling is being used). The ip module keeps this Path MTU information in a per-destination cache (aka IRE cache) table. The protocol used to keep track of this Path MTU information is described in RFC1191. The ip module provides a number of methods of accessing this per-destination cache. One of them is the ire_ctable_lookup() functional interface, but because tun and ip are separate STREAMS module and this functional interface was previously only safe to use within the ip module's STREAMS perimeter[1], tun could not use this functional interface. Another method ip provides is the IRE_DB_REQ_TYPE STREAMS message. An upstream module can send such a message down to ip, and ip will reply with an IRE_DB_TYPE message and append a copy of the IRE[2] requested to the message (assuming the requested IRE is found). This is the method used by the tun module. Periodically, tun sends down this message to get the current Path MTU for its tunnel destination. For example, it does this when sending a packet down to ip and the Path MTU information it has expired in tun_wdata_v4(). /* * Request the destination ire regularly in case Path MTU has * increased. */ if (TUN_IRE_TOO_OLD(atp)) tun_send_ire_req(q); DL_NOTIFY_REQ/IND and DL_NOTE_SDU_SIZEOnce the tun module has obtained the Path MTU information of the destination, it needs to recalcule the link MTU of the tunnel interface and notify the upper instance of ip if the MTU has changed. The ip module can then update the IP interface's MTU accordingly. The MTU calculation is done by the tun_update_link_mtu() function, which in turn calls tun_sendsdusize() to notify the ip module of the new MTU if it has changed:
/*
* Given the path MTU to the tunnel destination, calculate tunnel's link
* mtu. For configured tunnels, we update the tunnel's link MTU and notify
* the upper instance of IP of the change so that the IP interface's MTU
* can be updated. If the tunnel is a 6to4 or automatic tunnel, just
* return the effective MTU of the tunnel without updating it. We don't
* update the link MTU of 6to4 or automatic tunnels because they tunnel to
* multiple destinations all with potentially differing path MTU's.
*/
static uint32_t
tun_update_link_mtu(queue_t *q, uint32_t pmtu, boolean_t icmp)
{
tun_t *atp = (tun_t *)q->q_ptr;
uint32_t newmtu = pmtu;
boolean_t sendsdusize = B_FALSE;
/*
* If the pmtu provided came from an ICMP error being passed up
* from below, then the pmtu argument has already been adjusted
* by the IPsec overhead.
*/
if (!icmp && (atp->tun_flags & TUN_SECURITY))
newmtu -= atp->tun_ipsec_overhead;
if (atp->tun_flags & TUN_L_V4) {
newmtu -= sizeof (ipha_t);
if (newmtu < IP_MIN_MTU)
newmtu = IP_MIN_MTU;
} else {
ASSERT(atp->tun_flags & TUN_L_V6);
newmtu -= sizeof (ip6_t);
if (atp->tun_encap_lim > 0)
newmtu -= IPV6_TUN_ENCAP_OPT_LEN;
if (newmtu < IPV6_MIN_MTU)
newmtu = IPV6_MIN_MTU;
}
if (!(atp->tun_flags & (TUN_6TO4 | TUN_AUTOMATIC))) {
if (newmtu != atp->tun_mtu) {
atp->tun_mtu = newmtu;
sendsdusize = B_TRUE;
}
if (sendsdusize)
tun_sendsdusize(q);
}
return (newmtu);
}
Note, there is a cosmetic bug in the above code. The fix would be a good starter fix for anyone wishing to be introduced to the OpenSolaris development process. :-) The sendsdusize variable is obviously not needed and the last if statement can be reduced to:
if (newmtu != atp->tun_mtu &&
!(atp->tun_flags & (TUN_6TO4 | TUN_AUTOMATIC))) {
atp->tun_mtu = newmtu;
tun_sendsdusize(q);
}
How does the notification between tun and ip work? It's done via a DLPI notification mechanism that is Solaris specific. The dlpi(7P) man page describes the mechanism as "Notification Support", and it includes support for the asynchronous nofication of link status (up or down), SDU (send data unit, or MTU) size, link speed, and other information. The tun modules uses the SDU notification. The mechanism works as follows:
[1] The IP Multithreading feature of the FireEngine project now makes it possible for other modules to use this functional interface. Some modules such as ipf (IP Filter) and nattymod (IPsec NAT traversal) already use it. The tun module can now use it as well, which is something we plan on doing. [2] An IRE, or internet routing entry is a data structure internal to Solaris' IP implementation used to represent forwarding table entries _and_ per-destination cache entries. Creation and maintenance of IRE tables is by far the most complex (some would say overly complex) parts of the ip module. The subject of IRE's would make for a very lengthy blog entry on its own. Technorati Tag: OpenSolaris Technorati Tag: Solaris Posted at 11:17AM Jun 14, 2005 by seb in OpenSolaris | Comments[0] |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||