diff -urp v3.4/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v3.4/linux/Documentation/networking/ip-sysctl.txt	2012-05-21 23:03:38.000000000 +0300
+++ linux/Documentation/networking/ip-sysctl.txt	2012-05-21 23:55:22.438811703 +0300
@@ -761,6 +761,13 @@ accept_redirects - BOOLEAN
 forwarding - BOOLEAN
 	Enable IP forwarding on this interface.
 
+loop - BOOLEAN
+	By default (loop=0) the traffic between local IP addresses
+	is routed via interface "lo". Setting this flag for two
+	interfaces allows traffic between their IP addresses to
+	be looped externally. This is useful for setups where the
+	interfaces are attached to same broadcast medium.
+
 mc_forwarding - BOOLEAN
 	Do multicast routing. The kernel needs to be compiled with CONFIG_MROUTE
 	and a multicast routing daemon is required.
diff -urp v3.4/linux/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- v3.4/linux/include/linux/inetdevice.h	2012-05-21 23:04:36.000000000 +0300
+++ linux/include/linux/inetdevice.h	2012-05-21 23:55:46.046812794 +0300
@@ -30,6 +30,7 @@ enum
 	IPV4_DEVCONF_NOXFRM,
 	IPV4_DEVCONF_NOPOLICY,
 	IPV4_DEVCONF_FORCE_IGMP_VERSION,
+	IPV4_DEVCONF_LOOP,
 	IPV4_DEVCONF_ARP_ANNOUNCE,
 	IPV4_DEVCONF_ARP_IGNORE,
 	IPV4_DEVCONF_PROMOTE_SECONDARIES,
@@ -138,6 +139,7 @@ static inline void ipv4_devconf_setall(s
 	 || (!IN_DEV_FORWARD(in_dev) && \
 	  IN_DEV_ORCONF((in_dev), ACCEPT_REDIRECTS)))
 
+#define IN_DEV_LOOP(in_dev)		IN_DEV_CONF_GET(in_dev, LOOP)
 #define IN_DEV_ARPFILTER(in_dev)	IN_DEV_ORCONF((in_dev), ARPFILTER)
 #define IN_DEV_ARP_ACCEPT(in_dev)	IN_DEV_ORCONF((in_dev), ARP_ACCEPT)
 #define IN_DEV_ARP_ANNOUNCE(in_dev)	IN_DEV_MAXCONF((in_dev), ARP_ANNOUNCE)
diff -urp v3.4/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v3.4/linux/net/ipv4/devinet.c	2012-05-21 23:04:39.000000000 +0300
+++ linux/net/ipv4/devinet.c	2012-05-21 23:55:22.442811705 +0300
@@ -1609,6 +1609,7 @@ static struct devinet_sysctl_table {
 		DEVINET_SYSCTL_RW_ENTRY(LOG_MARTIANS, "log_martians"),
 		DEVINET_SYSCTL_RW_ENTRY(TAG, "tag"),
 		DEVINET_SYSCTL_RW_ENTRY(ARPFILTER, "arp_filter"),
+		DEVINET_SYSCTL_RW_ENTRY(LOOP, "loop"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_ANNOUNCE, "arp_announce"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_IGNORE, "arp_ignore"),
 		DEVINET_SYSCTL_RW_ENTRY(ARP_ACCEPT, "arp_accept"),
diff -urp v3.4/linux/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- v3.4/linux/net/ipv4/fib_frontend.c	2012-05-21 23:04:39.000000000 +0300
+++ linux/net/ipv4/fib_frontend.c	2012-05-21 23:55:22.442811705 +0300
@@ -197,6 +197,7 @@ int fib_validate_source(struct sk_buff *
 	struct fib_result res;
 	int no_addr, rpf, accept_local;
 	bool dev_match;
+	int loop = 0;
 	int ret;
 	struct net *net;
 
@@ -217,6 +218,7 @@ int fib_validate_source(struct sk_buff *
 
 		accept_local = IN_DEV_ACCEPT_LOCAL(in_dev);
 		fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0;
+		loop = IN_DEV_LOOP(in_dev);
 	}
 
 	if (in_dev == NULL)
@@ -225,6 +227,10 @@ int fib_validate_source(struct sk_buff *
 	net = dev_net(dev);
 	if (fib_lookup(net, &fl4, &res))
 		goto last_resort;
+	if (loop && res.type == RTN_LOCAL) {
+		*spec_dst = FIB_RES_PREFSRC(net, res);
+		return 0;
+	}
 	if (res.type != RTN_UNICAST) {
 		if (res.type != RTN_LOCAL || !accept_local)
 			goto e_inval;
diff -urp v3.4/linux/net/ipv4/route.c linux/net/ipv4/route.c
--- v3.4/linux/net/ipv4/route.c	2012-05-21 23:04:39.000000000 +0300
+++ linux/net/ipv4/route.c	2012-05-21 23:55:22.446811706 +0300
@@ -2766,6 +2766,27 @@ static struct rtable *ip_route_output_sl
 	}
 
 	if (res.type == RTN_LOCAL) {
+		struct in_device *in_dev;
+		__be32 src;
+
+		dev_out = FIB_RES_DEV(res);
+		in_dev = __in_dev_get_rcu(dev_out);
+		src = fl4->saddr? : FIB_RES_PREFSRC(net, res);
+		if (in_dev && IN_DEV_LOOP(in_dev) && src) {
+			struct net_device *dev_src;
+
+			dev_src = __ip_dev_find(net, src, false);
+			if (dev_src && dev_src != dev_out &&
+			    (in_dev = __in_dev_get_rcu(dev_src)) &&
+			    IN_DEV_LOOP(in_dev)) {
+				dev_out = dev_src;
+				fl4->saddr = src;
+				fl4->flowi4_oif = dev_out->ifindex;
+				res.type = RTN_UNICAST;
+				res.fi = NULL;
+				goto make_route;
+			}
+		}
 		if (!fl4->saddr) {
 			if (res.fi->fib_prefsrc)
 				fl4->saddr = res.fi->fib_prefsrc;
