public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [Fwd: Re: Testing Dual Ethernet via Loopback]
@ 2004-04-20 16:25 Ben Greear
  0 siblings, 0 replies; only message in thread
From: Ben Greear @ 2004-04-20 16:25 UTC (permalink / raw)
  To: linux-kernel

Looks like this message failed to go through the first time...


-------- Original Message --------
Subject: Re: Testing Dual Ethernet via Loopback
Date: Mon, 19 Apr 2004 18:44:27 -0700
From: Ben Greear <greearb@candelatech.com>
Organization: Candela Technologies
To: Nick Popoff <cryptic-lkml@bloodletting.com>
CC: linux-kernel@vger.kernel.org
References: <200404190614.21764.cryptic-lkml@bloodletting.com>

Nick Popoff wrote:
> Greetings,
> 
> I am trying to write some software to test a dual port ethernet card.  I
> was hoping to be able to use an ethernet cable to just connect the
> ethernet board to itself and then write a program that talks to itself to
> make sure that both ports are working.  However, I've noticed that Linux
> is smart enough to realize it is talking to its own IP address, and it
> just delivers the data internally rather than use the network hardware at
> all.
> 
> So what I'm wondering is if there is a way to force Linux to actually
> utilize its network hardware in sending these packets to itself?  In other
> words, a ping or file transfer from an IP assigned to eth0 to another IP
> assigned to eth1 should fail if I unplug the network cable connecting the
> two.  Any advice on this would be much appreciated.  I'm not afraid of
> reading kernel source but have no idea where to start on this one.
> 
> I'm using 2.4.22 but would use any 2.4 or 2.6 kernel that supported this
> behavior. The National Semiconductor DP83815 (natsemi.o) is the 
> ethernet chipset.

You can apply the candela* patch from http://www.candelatech.com/~greear/vlan.html
and then use SO_BINDTODEVICE with something similar to this, where dev_to_bind_to
is a local interface, like "eth2":

int createTcpSocket(unsigned int ip_addr, int ip_port, const char* dev_to_bind_to) {
    LF_TRC_IN_NT;
    VLOG_DBG(VLOG << "ip_addr -:" << ip_addr << ": ip_port: " << ip_port << endl);
    char *opt;

    int s = socket(AF_INET, SOCK_STREAM, 0);

    VLOG_INF(VLOG << "createTcpSocket:  ip_addr -:" << ip_addr << ":  " << toStringIP(ip_addr)
             << ": ip_port: " << ip_port << " socket: " << s << endl);

    if (s < 0) {
       cerr << "ERROR: tcp socket:  " << strerror(errno) << endl;
       VLOG << "ERROR: tcp socket:  " << strerror(errno) << endl;
       return s;
    }

    if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&opt,
                   sizeof(opt)) < 0) {
       cerr << "ERROR:  setsockopt:  " << strerror(errno) << endl;
       LFEXIT(100);
    }//if

    if (dev_to_bind_to) {
       // Bind to specific device.
       if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE,
                      dev_to_bind_to, DEV_NAME_LEN + 1)) {
          VLOG_ERR(VLOG << "ERROR:  tcp-connect, setsockopt (BINDTODEVICE):  "
                   << strerror(errno) << "  Not fatal in most cases..continuing...\n");
       }
    }//if

    struct sockaddr_in my_ip_addr;
    memset(&my_ip_addr, 0, sizeof(my_ip_addr));

    my_ip_addr.sin_family = AF_INET;
    my_ip_addr.sin_addr.s_addr = htonl(ip_addr);
    my_ip_addr.sin_port = htons(ip_port);

    int r; //retval
    r = bind(s, (struct sockaddr*)(&my_ip_addr), sizeof(my_ip_addr));
    if (r < 0) {
       //system("netstat -an");
       cerr << "ERROR: tcp bind:  " << strerror(errno) << endl;
       VLOG_ERR(VLOG << "ERROR: tcp bind:  " << strerror(errno) << "  IP: "
                << toStringIP(ip_addr) << " ipPort: " << ip_port << endl);
       close(s);
       return r;
    }
    else {
       VLOG_INF(VLOG << "Successfully bound to IP: " << toStringIP(ip_addr) << " port: "
                << ip_port << endl);
    }

    nonblock(s);
    return s;
}


You will need to enable the send-to-self flag with something like this:

             // Set us up to accept local-generate packets if the kernel can support
             // it... (send-to-self)
             struct ifreq ifr;
             int fd = socket(PF_INET, SOCK_DGRAM, 0);
             if (fd < 0) {
                mudlog << "ERROR: socket: " << strerror(errno) << endl;
             }
             else {
                memset(&ifr, 0, sizeof(struct ifreq));

                // query to see if we are set up for send-to-self
                strcpy(ifr.ifr_name, dev_name);
                ifr.ifr_addr.sa_family = AF_INET;
                if (ioctl(fd, 0x89a1, &ifr) < 0) {
                   VLOG_ERR(VLOG << "ERROR: send-to-self ioctl(0x89a1): " << strerror(errno)
                            << " ifr.ifr_name -:" << ifr.ifr_name << ":-" << endl);
                   setSendToSelf(false);
                }
                else {
                   if (ifr.ifr_flags) {
                      setSendToSelf(true);
                   }
                   else {
                      // Try to make send_to_self true
                      memset(&ifr, 0, sizeof(struct ifreq));

                      strcpy(ifr.ifr_name, dev_name);
                      ifr.ifr_addr.sa_family = AF_INET;
                      ifr.ifr_flags = 1;
                      if (ioctl(fd, 0x89a0, &ifr) < 0) {
                         VLOG_ERR(VLOG << "ERROR: send-to-self ioctl(0x89a0): "
                                  << strerror(errno) << " ifr.ifr_name -:"
                                  << ifr.ifr_name << ":-" << endl);
                         setSendToSelf(false);
                      }
                      else {
                         setSendToSelf(true);
                         VLOG_ERR(VLOG << "Set send-to-self bit to true for interface: "
                                  << ifr.ifr_name << endl);
                      }
                   }//else, try to enable send-to-self
                }//else, we could read send-to-self IOCTL
                close(fd);
             }//else, could open socket


Hope that helps,
Ben

-- 
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc  http://www.candelatech.com


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-04-20 16:26 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-20 16:25 [Fwd: Re: Testing Dual Ethernet via Loopback] Ben Greear

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox