All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Greear <greearb@candelatech.com>
To: linux-kernel@vger.kernel.org
Subject: [Fwd: Re: Testing Dual Ethernet via Loopback]
Date: Tue, 20 Apr 2004 09:25:16 -0700	[thread overview]
Message-ID: <40854EEC.8020508@candelatech.com> (raw)

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


                 reply	other threads:[~2004-04-20 16:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=40854EEC.8020508@candelatech.com \
    --to=greearb@candelatech.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.