External Ethernet Loopback Problems/Solution

Brian Moyle (BMoyle@redcreek.com)
Thu, 29 Oct 1998 11:46:24 -0800


(please CC any responses to "bmoyle@redcreek.com")

I'm still pretty new to kernel hacking, so if you see any problems
with my solution below, please let me know.

Problem
Attempting external loopback tests via an ethernet cross-over
cable fails.

Configuration
cross-over cable connected between two ethernet cards
ifconfig --> 10.0.0.1 = eth0
11.0.0.1 = eth1

Route entries that work
route --> 10.0.0.0/255.0.0.0 eth0 {internal}
11.0.0.0/255.0.0.0 eth1

Route entries that don't
route --> 10.0.0.0/255.0.0.0 eth1 {external}
11.0.0.0/255.0.0.0 eth0

Details
/usr/src/linux/net/ipv4/arp.c (kernel 2.0.34-0.6, RH5.1)
has a routine called "arp_set_predefined()", which is
responsible for filling in MAC addresses for local IP
addresses. It makes an assumption that a packet destined for
a local address will have the same MAC address as the interface
it's leaving. As a result, when attempting external loopbacks,
the wrong destination MAC address is filled in for the header.
Adding a few extra lines of code seems to fix the problem.

Kernel 2.1 Note
I've looked at a recent 2.1 kernel and see that RTN_LOCAL is
used instead of IS_MYADDR, but the remaining code is the same,
so I suspect this fix is applicable to 2.1 kernels as well.

Fix
----------------------------------------------------------------------------
----
*** arp.c~ Thu Oct 29 05:04:42 1998
--- arp.c Thu Oct 29 04:48:42 1998
***************
*** 20,25 ****
--- 20,27 ----
* 2 of the License, or (at your option) any later version.
*
* Fixes:
+ * Brian Moyle : Fixed arp_set_predefined() to
+ * work with external loopbacks.
* Alan Cox : Removed the ethernet assumptions in
* Florian's code
* Alan Cox : Fixed some small errors in the ARP
***************
*** 1287,1295 ****
switch (addr_hint)
{
case IS_MYADDR:
printk(KERN_DEBUG "ARP: arp called for own IP address\n");
! memcpy(haddr, dev->dev_addr, dev->addr_len);
return 1;
#ifdef CONFIG_IP_MULTICAST
case IS_MULTICAST:
if(dev->type==ARPHRD_ETHER || dev->type==ARPHRD_IEEE802
--- 1289,1303 ----
switch (addr_hint)
{
case IS_MYADDR:
+ {
+ struct device *dev_found=ip_dev_find(paddr);
printk(KERN_DEBUG "ARP: arp called for own IP address\n");
! if (dev_found)
! memcpy(haddr, dev_found->dev_addr, dev_found->addr_len);
! else
! memcpy(haddr, dev->dev_addr, dev->addr_len);
return 1;
+ }
#ifdef CONFIG_IP_MULTICAST
case IS_MULTICAST:
if(dev->type==ARPHRD_ETHER || dev->type==ARPHRD_IEEE802
----------------------------------------------------------------------------
----

Sincerely,

Brian Moyle
RedCreek Communications, Inc.
3900 Newpark Mall Road
Newark, CA 94560
email: bmoyle@redcreek.com
phone: (510)745-3924
fax: (510)745-3999

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/