Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 05 Jun 2002 01:49:01 +0200
From:      Marko Zec <zec@tel.fer.hr>
To:        freebsd-net@freebsd.org
Subject:   Patch for review: source VIPA
Message-ID:  <3CFD51EC.AD9D7192@tel.fer.hr>

next in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.
--------------2FB848ED7893B437F014C895
Content-Type: text/plain; charset=iso-8859-2
Content-Transfer-Encoding: 7bit

Bellow is a patch that enables all outgoing sessions to always use the
same source IP address by default, no matter what outbound interface is
used. If on a multi-homed host the source IP address always originates
from an "always-up" internal virtual interface, than the established TCP
sessions won't break in case of failure of one of the physical
interfaces, or similar serious network topology changes.
The idea is not new, as far as I know it was introduced a couple of
years ago in OS/390 V2R5 TCP/IP implementation, if not earlier. IBM
called this feature "Virtual IP Address - VIPA", so just for fun I also
borrowed the name along with the idea...
Anyway, after applying the patch (against 4.6-RC3 kernel source), a new
sysctl variable net.inet.ip.sourcevipa becomes available, which can be
set to an existing IP address of desired internal interface. Although
any interface can be used for source-VIPA feature, the patch also
provides a new interface type "vipa", which is nothing else than a
standard loopback ifc, but without the loopback flag set, so that it can
be conveniently advertised via the routed daemon. The following line
should be added to your kernel config file in order to make the vipa ifc
available:

pseudo-device    vipa    1

Here is an configuration example:

vmbsd# routed
vmbsd# ifconfig
lnc0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet 192.168.201.143 netmask 0xffffff00 broadcast
192.168.201.255
        ether 00:50:56:ac:c9:7a
lnc1: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> mtu 1500
        inet 192.168.202.143 netmask 0xffffff00 broadcast
192.168.202.255
        ether 00:50:56:ac:c9:8c
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
        inet 127.0.0.1 netmask 0xff000000
vipa0: flags=61<UP,SMART,RUNNING> mtu 1500
        inet 192.168.1.1 netmask 0xffffffff
vmbsd# sysctl net.inet.ip.sourcevipa
net.inet.ip.sourcevipa: none
vmbsd# sysctl net.inet.ip.sourcevipa=192.168.1.1
net.inet.ip.sourcevipa: none -> 192.168.1.1
vmbsd#
vmbsd# telnet 192.168.201.10
[cut]
%who am i
marko            ttyp2   Jun  5 01:37   (192.168.1.1)

Have fun!

--------------2FB848ED7893B437F014C895
Content-Type: text/plain; charset=iso-8859-2;
 name="vipa.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="vipa.diff"

--- netinet/in_pcb.c	Thu May  2 04:36:50 2002
+++ netinet/in_pcb.c.vipa	Wed Jun  5 00:14:19 2002
@@ -122,6 +122,50 @@ SYSCTL_PROC(_net_inet_ip_portrange, OID_
 SYSCTL_PROC(_net_inet_ip_portrange, OID_AUTO, hilast, CTLTYPE_INT|CTLFLAG_RW,
 	   &ipport_hilastauto, 0, &sysctl_net_ipport_check, "I", "");
 
+
+static char sourcevipastr[16] = "none";
+static u_long sourcevipa=0;
+
+static int
+sourcevipa_sysctl(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	u_char i,j;
+	u_long addr=0;
+	char *c;
+	
+	error = sysctl_handle_string(oidp,
+		oidp->oid_arg1, oidp->oid_arg2, req);
+	if (error)
+		return error;
+	c=sourcevipastr;
+	for (i=0;i<4;i++) {
+		j=0;
+		while (*c>='0'&&*c<='9') {
+			j*=10;
+			j+=*c-'0';
+			c++;
+		}
+		if (*c!=0)
+			c++;
+		addr=(addr<<8)+j;
+	}
+	sourcevipa=addr;
+	if (addr) {
+		unsigned char *ucp=(u_char *)&addr;
+		sprintf(sourcevipastr, "%d.%d.%d.%d",
+			ucp[0], ucp[1], ucp[2], ucp[3]);
+	} else {
+		sprintf(sourcevipastr, "none");
+	}
+	return 0;
+}
+
+SYSCTL_PROC(_net_inet_ip, OID_AUTO, sourcevipa, CTLTYPE_STRING|CTLFLAG_RW,
+	sourcevipastr, sizeof(sourcevipastr), &sourcevipa_sysctl, "A",
+	"Always try to use this IP address as source");
+
+
 /*
  * in_pcb.c: manage the Protocol Control Blocks.
  *
@@ -438,7 +482,25 @@ in_pcbladdr(inp, nam, plocal_sin)
 		 * to our address on another net goes to loopback).
 		 */
 		if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
-			ia = ifatoia(ro->ro_rt->rt_ifa);
+		{
+			/*
+			 * Use source VIPA, if available
+			 * M. Zec (zec@tel.fer.hr) 2002/06/24
+			 */
+			if (sourcevipa) {
+				u_long addr = sin->sin_addr.s_addr;
+				u_short fport = sin->sin_port;
+	
+				sin->sin_addr.s_addr = htonl(sourcevipa);
+				sin->sin_port = 0;
+				ia = ifatoia(ifa_ifwithaddr(sintosa(sin)));
+				sin->sin_addr.s_addr = addr;
+				sin->sin_port = fport;
+			}
+
+			if (ia == 0)
+				ia = ifatoia(ro->ro_rt->rt_ifa);
+		}
 		if (ia == 0) {
 			u_short fport = sin->sin_port;
 
--- net/if_loop.c	Thu Dec 20 11:30:16 2001
+++ net/if_loop.c.vipa	Wed Jun  5 00:16:40 2002
@@ -38,6 +38,7 @@
  * Loopback interface driver for protocol testing and timing.
  */
 #include "loop.h"
+#include "vipa.h"
 
 #include "opt_atalk.h"
 #include "opt_inet.h"
@@ -53,6 +54,7 @@
 
 #include <net/if.h>
 #include <net/if_types.h>
+#include <net/ethernet.h>
 #include <net/netisr.h>
 #include <net/route.h>
 #include <net/bpf.h>
@@ -103,7 +105,7 @@ int looutput __P((struct ifnet *ifp,
 #define LOMTU	16384
 #endif
 
-struct	ifnet loif[NLOOP];
+struct	ifnet loif[NLOOP+NVIPA];
 
 /* ARGSUSED */
 static void
@@ -113,11 +115,18 @@ loopattach(dummy)
 	register struct ifnet *ifp;
 	register int i = 0;
 
-	for (ifp = loif; i < NLOOP; ifp++) {
-	    ifp->if_name = "lo";
-	    ifp->if_unit = i++;
-	    ifp->if_mtu = LOMTU;
-	    ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
+	for (ifp = loif; i < NLOOP+NVIPA; ifp++) {
+	    if (i<NLOOP) {
+		ifp->if_name = "lo";
+		ifp->if_unit = i++;
+		ifp->if_mtu = LOMTU;
+		ifp->if_flags = IFF_LOOPBACK | IFF_MULTICAST;
+	    } else {
+		ifp->if_name = "vipa";
+		ifp->if_unit = i++ - NLOOP;
+		ifp->if_mtu = ETHERMTU;
+		ifp->if_flags = IFF_SMART; /* joke! */
+	    }
 	    ifp->if_ioctl = loioctl;
 	    ifp->if_output = looutput;
 	    ifp->if_type = IFT_LOOP;
--- conf/files	Sat May  4 10:48:53 2002
+++ conf/files.vipa	Tue Jun  4 23:56:15 2002
@@ -698,6 +698,7 @@ net/if_faith.c		optional faith
 net/if_fddisubr.c	optional fddi
 net/if_gif.c		optional gif
 net/if_loop.c		optional loop
+net/if_loop.c		optional vipa
 net/if_media.c		standard
 net/if_mib.c		standard
 net/if_ppp.c		optional ppp
--- i386/conf/LINT	Wed Jun  5 00:20:55 2002
+++ i386/conf/LINT.vipa	Wed Jun  5 00:19:59 2002
@@ -525,6 +525,8 @@ options 	ETHER_8023		# enable Ethernet_8
 options 	ETHER_8022		# enable Ethernet_802.2 frame
 options 	ETHER_SNAP		# enable Ethernet_802.2/SNAP frame
 
+pseudo-device	vipa	1		# Virtual IP Address (routable loopback)
+
 # for IPv6
 pseudo-device	gif			#IPv6 and IPv4 tunneling
 pseudo-device	faith	1		#for IPv6 and IPv4 translation





--------------2FB848ED7893B437F014C895--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-net" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3CFD51EC.AD9D7192>