[ Top page ]

« A test program for sending/receiving packets with a VLAN tag | Main | Software-based Ethernet switch »

Network and communication

Connection check program for non IP network environment

To test connectivity through an IP network, "ping" is usually used. However, "ping" cannot be used or it is not convenient when non IP environment or using network interfaces directly. This page shows a simple tool for such situation. This tool can of course be used under an Ethernet environment, but it can also be used when Ethernet is not available but the promiscuous mode of Linux can be used.

The program is listed at the end of this page.

Usage

Run the program on a node on the network (slice) in the following method.

./test <VNode#> <#Links>

For example, run it on all the nodes in the network simultaneously. <VNode#> is the node number (Give unique numbers to nodes including terminal nodes), <#Links> is the number of links N. (Assume that eth1 to ethN are used.)

For example, to show the connection between (virtual) nodes 1, 2, 3, each of which has three links, the following command is to be run on each node.

./test 1 3
./test 2 3
./test 3 3

Example output

The following message shows the output obtained by running "./test 3 3" (on VNode 3). These messages are repeated. (Each node outputs a packet once in every second to each link.)

Received from VNode 1 through eth1 (56 bytes)

Received from VNode 2 through eth3 (56 bytes)

These messages mean that packets received by VNode 3 come from VNode 1 through eth1, and from VNode 2 through eth3.

Program

/***
 *
 * Non-IP Network Connection Tester
 *
 * Coded by Yasusi Kanada
 * Ver 0.2  2011-6-14	Initial version (for Linux promiscuous mode)
 * Ver 0.8  2012-5-23	Argument count updated
 *
 ***/

#include <linux/if_packet.h>
#include <linux/if_ether.h> 
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <stdio.h>
#include <elf.h>
#include <string.h>

#include <fcntl.h>

#define bool	int32_t
#define true	1
#define false	0

#define DEBUG	0

#define MAX_PACKET_SIZE	2048
// Sufficiently larger than the MTU

#define FirstInterface 1
#define LastInterface  16

int32_t fd[LastInterface];
int32_t ifindex[LastInterface];

int32_t firstInterface;
int32_t lastInterface;

extern void _exit(int32_t);


/**
 * Open a socket for the network interface
 */
int32_t open_socket(int32_t index, int32_t *rifindex) {
  unsigned char buf[MAX_PACKET_SIZE];
  int32_t i;
  int32_t ifindex;
  struct ifreq ifr;
  struct sockaddr_ll sll;
  unsigned char interface[IFNAMSIZ];
  strncpy(interface, "ethX", IFNAMSIZ);
  interface[3] = '0' + index;

  int32_t fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
  if (fd == -1) {
    printf("%s - ", interface);
    perror("socket");
    _exit(1);
  };

  // get interface index
  memset(&ifr, 0, sizeof(ifr));
  strncpy(ifr.ifr_name, interface, IFNAMSIZ);
  if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
    printf("%s - ", interface);
    perror("SIOCGIFINDEX");
    _exit(1);
  };
  ifindex = ifr.ifr_ifindex;
  *rifindex = ifindex;

  // set promiscuous mode
  memset(&ifr, 0, sizeof(ifr));
  strncpy(ifr.ifr_name, interface, IFNAMSIZ);
  ioctl(fd, SIOCGIFFLAGS, &ifr);
  ifr.ifr_flags |= IFF_PROMISC;
  ioctl(fd, SIOCSIFFLAGS, &ifr);

  memset(&sll, 0xff, sizeof(sll));
  sll.sll_family = AF_PACKET;
  sll.sll_protocol = htons(ETH_P_ALL);
  sll.sll_ifindex = ifindex;
  if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)) == -1) {
    printf("%s - ", interface);
    perror("bind");
    _exit(1);
  };

  /* flush all received packets. 
   *
   * raw-socket receives packets from all interfaces
   * when the socket is not bound to an interface
   */
  do {
    fd_set fds;
    struct timeval t;
    FD_ZERO(&fds);
    FD_SET(fd, &fds);
    memset(&t, 0, sizeof(t));
    i = select(FD_SETSIZE, &fds, NULL, NULL, &t);
    if (i > 0) {
      recv(fd, buf, i, 0);
    };
    printf("interface %d flushed\n", ifindex);
  } while (i);

  printf("%s opened (fd=%d interface=%d)\n", interface, fd, ifindex);

  return fd;
}


/**
 * Send a packet
 */
int32_t sendPacket(int vnodeNum) {
  unsigned char packet[MAX_PACKET_SIZE];
  struct sockaddr_ll sll;
  int ifnum;

  packet[0] = vnodeNum;

  memset(&sll, 0, sizeof(sll));
  sll.sll_family = AF_PACKET;
  sll.sll_protocol = htons(ETH_P_ALL);

  for (ifnum = firstInterface; ifnum <= lastInterface; ifnum++) {
    int sizein = 14; // >= ethernet packet size !
    sll.sll_ifindex = ifindex[ifnum];
    if (DEBUG) {
      printf("Send to eth%d\n", ifnum);
    }
    ssize_t sizeout = sendto(fd[ifnum], packet, sizein, 0,
			     (struct sockaddr *)&sll, sizeof(sll));
    if (sizeout < 0) {
      perror("sendto");
    }
  }
}


/**
 * Main program
 */
int32_t main(int32_t argc, char **argv) {
  unsigned char packet[MAX_PACKET_SIZE];
  int32_t ifnum;// interface number (different from ifindex)
  int32_t vnodeNum = 1;
  struct timeval now;
  struct timezone tz;
  gettimeofday(&now, &tz);
  time_t time = now.tv_sec;

  int32_t count = 0;
  if (++count < argc) {
    vnodeNum = atoi(argv[count]);
  }

  firstInterface = FirstInterface;
  lastInterface = LastInterface;
  if (++count < argc) {
    lastInterface = atoi(argv[count]);
  }

  // Open raw sockets and initialize for sending packets
  for (ifnum = firstInterface; ifnum <= lastInterface; ifnum++) {
    fd[ifnum] = open_socket(ifnum, &ifindex[ifnum]);

    // Set non-blocking mode:
    int32_t flags = fcntl(fd[ifnum], F_GETFL, 0);
    fcntl(fd[ifnum], F_SETFL, O_NONBLOCK | flags);
  }

  for (;;) {
    for (ifnum = firstInterface; ifnum <= lastInterface; ifnum++) {
      ssize_t sizein = recv(fd[ifnum], packet, MAX_PACKET_SIZE, 0);
      int senderNum = packet[0];
      if (sizein >= 0) {
	printf("Packet received from VNode %d through eth%d (%d bytes)\n",
	       senderNum, ifnum, sizein);
      }
    }

    gettimeofday(&now, &tz);
    time_t time1 = now.tv_sec;
    if (time1 > time) {
      sendPacket(vnodeNum);
      time = time1;
    }
  }
}
Keywords:

TrackBack

TrackBack URL for this entry:
http://www.kanadas.com/mt/mt-tb.cgi/5631

Post a comment

About

This page contains a single entry from the blog posted on May 20, 2012 4:13 PM.

Many more can be found on the main index page or by looking through the archives.

Creative Commons License
This weblog is licensed under a Creative Commons License.
Powered by
Movable Type 3.36