Channel Bonding possible with 2.2.X ?

Lars Steinke (steinke@hpcip00.physik.uni-freiburg.de)
Fri, 26 Feb 1999 18:03:27 +0100


--4bRzO86E/ozDv8r1
Content-Type: multipart/mixed; boundary=C7zPtVaVf+AK4Oqc

--C7zPtVaVf+AK4Oqc
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable

Hi there,

attached is the Beowulf network channel bonding patch which used
to work a treat in 2.0.35, but won't patch the 2.2.x series, most
probably due to the major overhaul of the network code...

We use the patch together with the control program ifenslave.c to
spread outgoing network traffic across 3 DEC Tulip 100MBit
Ethernet cards in our servers. This is a brilliant load balancing
feature as the three network cards share one IP so that our
switch also balances the incoming network load across the three
interfaces - a lot easier than using OSPF routing to balance our
net load !

I find this a rather desirable feature for the LinUX kernel and
it's very easy to set up for the user, so I'd like to ask one of
you to review the patch and perhaps ask Don Becker for permission
to incorporate his code in the kernel (ifenslave.c is GPL...).

Alternatively I'd be infinitely grateful for pointers to other
possibilites to balance our net load across three interfaces with
2.2.X (as long as it's NOT OSPF routing :-) !!!) so we can benefit=20
from the SMP speedups.

Regards,
--=20
/(__ __|\ Lars Steinke, Research Student @
( \/ __)_ www.fmf.uni-freiburg.de, Germany
) (_____ / for PGP PKey and WWW-Page finger
/___________/ steinke@mibm.ruf.uni-freiburg.de

--C7zPtVaVf+AK4Oqc
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="linux-2.0.31-bonding.patch"

diff -urN linux-pristine/arch/i386/config.in linux/arch/i386/config.in
--- linux-pristine/arch/i386/config.in Mon May 13 00:17:23 1996
+++ linux/arch/i386/config.in Thu Oct 30 11:01:23 1997
@@ -31,6 +31,7 @@
fi
fi
bool 'System V IPC' CONFIG_SYSVIPC
+bool 'Beowulf Clustering' CONFIG_BEOWULF
tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
if [ "$CONFIG_EXPERIMENTAL" =3D "y" ]; then
diff -urN linux-pristine/net/Config.in linux/net/Config.in
--- linux-pristine/net/Config.in Tue Aug 12 14:30:22 1997
+++ linux/net/Config.in Thu Oct 30 11:01:23 1997
@@ -5,6 +5,9 @@
comment 'Networking options'
bool 'Network firewalls' CONFIG_FIREWALL
bool 'Network aliasing' CONFIG_NET_ALIAS
+if [ "$CONFIG_BEOWULF" =3D "y" ]; then
+ bool 'Beowulf network channel bonding' CONFIG_BEOWULF_BONDING
+fi
bool 'TCP/IP networking' CONFIG_INET
if [ "$CONFIG_INET" =3D "y" ]; then
source net/ipv4/Config.in
diff -urN linux-pristine/net/core/dev.c linux/net/core/dev.c
--- linux-pristine/net/core/dev.c Tue Aug 12 17:15:56 1997
+++ linux/net/core/dev.c Thu Oct 30 11:01:51 1997
@@ -124,6 +124,16 @@
=20
static int backlog_size =3D 0;
=20
+#ifdef CONFIG_BEOWULF_BONDING
+/*
+ * Channel bonding interface control. These variables should really be kept
+ * with the slave interface, but are global to minimize the patch size. Th=
is
+ * implementation limits us to one slave chain.
+ */
+static slave_count =3D 0;
+static struct device *slave_list[8];
+#endif
+
/*
* Return the lesser of the two values.=20
*/
@@ -394,6 +404,26 @@
if (net_alias_is(dev))
skb->dev =3D dev =3D net_alias_dev_tx(dev);
#endif
+#ifdef CONFIG_BEOWULF_BONDING
+ /*=20
+ * Here is where the master/slave strategy algorithm is.
+ * Right now we are using a global incrementing value to
+ * select a queue for the current packet.
+ * The original condition was
+ * if (dev->slave->pkt_queue < dev->pkt_queue)
+ * which left the slave until the master device's queue
+ * (sometimes 16 packets!) filled.
+ */
+ if (dev->flags & IFF_MASTER) {
+ static dev_bond_index =3D -1;
+ if (++dev_bond_index >=3D slave_count) {
+ dev_bond_index =3D -1;
+ } else if (slave_list[dev_bond_index] &&
+ (slave_list[dev_bond_index]->flags & IFF_UP))
+ skb->dev =3D dev =3D slave_list[dev_bond_index];
+ }
+#endif
+
=20
/*
* If we are bridging and this is directly generated output
@@ -529,6 +559,10 @@
#if CONFIG_SKB_CHECK
IS_SKB(skb);
#endif=09
+#ifdef CONFIG_BEOWULF_BONDING
+ if (skb->dev->flags & IFF_SLAVE && skb->dev->slave)
+ skb->dev =3D skb->dev->slave;
+#endif
skb_queue_tail(&backlog,skb);
backlog_size++;
=20
@@ -1119,7 +1153,32 @@
*/
=09
dev_lock_wait();
- =09
+#ifdef CONFIG_BEOWULF_BONDING
+ if (dev->flags & IFF_SLAVE) {
+ int i;
+ if (ifr.ifr_flags & IFF_UP)
+ return -EBUSY;
+ /* Shutdown the slave, decrement the master
+ count, and perhaps un-master the master. */
+ /* Delete the slave from the table of slaves. */
+ for (i =3D 0; i < slave_count; i++) {
+ if (dev =3D=3D slave_list[i]) {
+ do {
+ slave_list[i] =3D slave_list[i+1];
+ } while (++i < slave_count);
+ }
+ }
+ /* If we are out of slaves, sell the plantation. */
+ if (--slave_count <=3D 0) {
+ struct device *master =3D dev->slave;
+ master->flags &=3D ~IFF_MASTER;
+ master->slave =3D NULL;
+ dev->flags &=3D ~IFF_SLAVE;
+ dev->slave =3D NULL;
+ }
+ /* The device is actually closed below. */
+ }
+#endif
/*
* Set the flags on our device.
*/
@@ -1127,6 +1186,9 @@
dev->flags =3D (ifr.ifr_flags & (
IFF_BROADCAST | IFF_DEBUG | IFF_LOOPBACK |
IFF_POINTOPOINT | IFF_NOTRAILERS | IFF_RUNNING |
+#ifdef CONFIG_BEOWULF_BONDING
+ IFF_SLAVE | IFF_MASTER |
+#endif
IFF_NOARP | IFF_PROMISC | IFF_ALLMULTI | IFF_SLAVE | IFF_MASTER
| IFF_MULTICAST)) | (dev->flags & (IFF_SOFTHEADERS|IFF_UP));
/*
@@ -1370,6 +1432,41 @@
return -EINVAL;
dev_mc_delete(dev,ifr.ifr_hwaddr.sa_data,dev->addr_len, 1);
return 0;
+#ifdef CONFIG_BEOWULF_BONDING
+ case SIOCGIFSLAVE:
+ if(dev->slave=3D=3DNULL)
+ return -ENOENT;
+ strncpy(ifr.ifr_name,dev->name,sizeof(ifr.ifr_name));
+ memcpy_tofs(arg,&ifr,sizeof(struct ifreq));
+ return 0;
+ case SIOCSIFSLAVE:
+ {
+ unsigned long flags;
+ struct device *slave =3D dev_get(ifr.ifr_slave);
+ if (slave =3D=3D NULL)
+ return -ENODEV;
+ save_flags(flags);
+ cli();
+ if ((slave->flags & (IFF_UP|IFF_RUNNING))
+ !=3D (IFF_UP|IFF_RUNNING)) {
+ restore_flags(flags);
+ return -EINVAL;
+ }
+ if (dev->flags & IFF_SLAVE
+ || slave->flags & IFF_SLAVE) {
+ restore_flags(flags);
+ return -EBUSY;
+ }
+ dev->slave =3D slave;
+ slave_list[slave_count++] =3D slave;
+ slave->slave =3D dev; /* save the master in slave->slave */
+ slave->flags |=3D IFF_SLAVE;
+ dev->flags |=3D IFF_MASTER;
+ restore_flags(flags);=09
+ return 0;
+ }
+ break;
+#endif
/*
* Unknown or private ioctl
*/

--C7zPtVaVf+AK4Oqc
Content-Type: text/x-csrc
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="ifenslave.c"

/* Mode: C;
* ifenslave.c: Configure network interfaces for parallel routing.
*
* This program controls the Linux implementation of running multiple
* network interfaces in parallel.
*
* Usage: ifenslave [-v] master-interface slave-interface [metric <N>]
*
* Author: Donald Becker <becker@cesdis.gsfc.nasa.gov>
* Copyright 1994-1996 Donald Becker
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation.
*
* The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
* Center of Excellence in Space Data and Information Sciences
* Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
*/

static char *version =3D
"ifenslave.c:v0.07 9/9/97 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
static const char *usage_msg =3D
"Usage: ifenslave [-afrvV] <master-interface> <slave-interface> [metric <N>=
]\n";

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/if_ether.h>

struct option longopts[] =3D {
/* { name has_arg *flag val } */
{"all-interfaces", 0, 0, 'a'}, /* Show all interfaces. */
{"force", 0, 0, 'f'}, /* Force the operation. */
{"help", 0, 0, '?'}, /* Give help */
{"receive-slave", 0, 0, 'r'}, /* Make a receive-only slave. */
{"verbose", 0, 0, 'v'}, /* Report each action taken. */
{"version", 0, 0, 'V'}, /* Emit version information. */
{ 0, 0, 0, 0 }
};

/* Command-line flags. */
unsigned int
opt_a =3D 0, /* Show-all-interfaces flag. */
opt_f =3D 0, /* Force the operation. */
opt_r =3D 0, /* Set up a Rx-only slave. */
verbose =3D 0, /* Verbose flag. */
opt_version;
int skfd =3D -1; /* AF_INET socket for ioctl() calls. */

static void if_print(char *ifname);

int
main(int argc, char **argv)
{
struct ifreq ifr2, if_hwaddr, if_ipaddr, if_metric, if_mtu, if_dstaddr;
struct ifreq if_netmask, if_brdaddr, if_flags;
int goterr =3D 0;
int c, errflag =3D 0;
char **spp, *master_ifname, *slave_ifname;

while ((c =3D getopt_long(argc, argv, "afrvV?", longopts, 0)) !=3D EOF)
switch (c) {
case 'a': opt_a++; break;
case 'f': opt_f++; break;
case 'r': opt_r++; break;
case 'v': verbose++; break;
case 'V': opt_version++; break;
case '?': errflag++;
}
if (errflag) {
fprintf(stderr, usage_msg);
return 2;
}

if (verbose || opt_version)
printf(version);

/* Open a basic socket. */
if ((skfd =3D socket(AF_INET, SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(-1);
}

#ifdef notdef
/* Find options scattered throughout the command line.
I should change this to use getopt() sometime. */
argc--; argv++;
while (*argv[0] =3D=3D '-') {
char *argp =3D *argv++;
argc--;
while (*++argp) {
switch (*argp) {
default:
fprintf(stderr, "Unrecognized option '%c'.\n%s",
argp[0], usage_msg);
return 2;
}
}
}
#endif

if (verbose)
fprintf(stderr, "DEBUG: argc=3D%d, optind=3D%d and argv[optind] is %s.\n",
argc, optind, argv[optind]);

/* No remaining args means show all interfaces. */
if (optind =3D=3D argc) {
if_print((char *)NULL);
(void) close(skfd);
exit(0);
}

/* Copy the interface name. */
spp =3D argv + optind;
master_ifname =3D *spp++;
slave_ifname =3D *spp++;

/* A single args means show the configuration for this interface. */
if (slave_ifname =3D=3D NULL) {
if_print(master_ifname);
(void) close(skfd);
exit(0);
}

/* Get the vitals from the master interface. */
strncpy(if_hwaddr.ifr_name, master_ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr) < 0) {
fprintf(stderr, "SIOCGIFHWADDR on %s failed: %s\n", master_ifname,
strerror(errno));
return 1;
} else { /* Gotta convert from 'char' to unsigned for printf(). */
unsigned char *hwaddr =3D (unsigned char *)if_hwaddr.ifr_hwaddr.sa_data;

/* The family '1' is ARPHRD_ETHER for ethernet. */
if (if_hwaddr.ifr_hwaddr.sa_family !=3D 1 && !opt_f) {
fprintf(stderr, "The specified master interface '%s' is not"
" ethernet-like.\n This program is designed to work"
" with ethernet-like network interfaces.\n"
" Use the '-f' option to force the operation.\n",
master_ifname);

return 1;
}

if (verbose)
printf("The hardware address (SIOCGIFHWADDR) of %s is type %d "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", master_ifname,
if_hwaddr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
}

{
struct ifreq *ifra[6] =3D { &if_ipaddr, &if_mtu, &if_dstaddr,
&if_brdaddr, &if_netmask, &if_flags };
const char *req_name[6] =3D {
"IP address", "MTU", "destination address",
"broadcast address", "netmask", "status flags", };
const int ioctl_req_type[6] =3D {
SIOCGIFADDR, SIOCGIFMTU, SIOCGIFDSTADDR,
SIOCGIFBRDADDR, SIOCGIFNETMASK, SIOCGIFFLAGS, };
int i;

for (i =3D 0; i < 6; i++) {
strncpy(ifra[i]->ifr_name, master_ifname, IFNAMSIZ);
if (ioctl(skfd, ioctl_req_type[i], ifra[i]) < 0) {
fprintf(stderr,
"Something broke getting the master's %s: %s.\n",
req_name[i], strerror(errno));
}
}
}

do {
strncpy(ifr2.ifr_name, slave_ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCGIFFLAGS, &ifr2) < 0) {
int saved_errno =3D errno;
fprintf(stderr, "SIOCGIFFLAGS on %s failed: %s\n", slave_ifname,
strerror(saved_errno));
return 1;
}
if (ifr2.ifr_flags & IFF_UP) {
printf("The interface %s is up, shutting it down it to enslave it.\n",
slave_ifname);
ifr2.ifr_flags &=3D ~IFF_UP;
if (ioctl(skfd, SIOCSIFFLAGS, &ifr2) < 0) {
int saved_errno =3D errno;
fprintf(stderr, "Shutting down interface %s failed: %s\n",
slave_ifname, strerror(saved_errno));
}
}

strncpy(if_hwaddr.ifr_name, slave_ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCSIFHWADDR, &if_hwaddr) < 0) {
int saved_errno =3D errno;
fprintf(stderr, "SIOCSIFHWADDR on %s failed: %s\n", if_hwaddr.ifr_name,
strerror(saved_errno));
if (saved_errno =3D=3D EBUSY)
fprintf(stderr, " The slave device %s is busy: it must be"
" idle before running this command.\n", slave_ifname);
else if (saved_errno =3D=3D EOPNOTSUPP)
fprintf(stderr, " The slave device you specified does not support"
" setting the MAC address.\n Your kernel likely does not"
" support slave devices.\n");
else if (saved_errno =3D=3D EINVAL)
fprintf(stderr, " The slave device's address type does not match"
" the master's address type.\n");
return 1;
} else {
if (verbose) {
unsigned char *hwaddr =3D if_hwaddr.ifr_hwaddr.sa_data;
printf("Set the slave's hardware address to "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n", hwaddr[0],
hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
}
}
=09
if (*spp && !strcmp(*spp, "metric")) {
if (*++spp =3D=3D NULL) {
fprintf(stderr, usage_msg);
exit(2);
}
if_metric.ifr_metric =3D atoi(*spp);
if (ioctl(skfd, SIOCSIFMETRIC, &if_metric) < 0) {
fprintf(stderr, "SIOCSIFMETRIC: %s\n", strerror(errno));
goterr =3D 1;
}
spp++;
}

if (strncpy(if_ipaddr.ifr_name, slave_ifname, IFNAMSIZ) <=3D 0
|| ioctl(skfd, SIOCSIFADDR, &if_ipaddr) < 0) {
fprintf(stderr,
"Something broke setting the slave's address: %s.\n",
strerror(errno));
} else {
if (verbose) {
unsigned char *ipaddr =3D if_ipaddr.ifr_addr.sa_data;
printf("Set the slave's IP address to %d.%d.%d.%d.\n",
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
}
}

if (strncpy(if_mtu.ifr_name, slave_ifname, IFNAMSIZ) <=3D 0
|| ioctl(skfd, SIOCSIFMTU, &if_mtu) < 0) {
fprintf(stderr, "Something broke setting the slave MTU: %s.\n",
strerror(errno));
} else {
if (verbose)
printf("Set the slave's MTU to %d.\n", if_mtu.ifr_mtu);
}

if (strncpy(if_dstaddr.ifr_name, slave_ifname, IFNAMSIZ) <=3D 0
|| ioctl(skfd, SIOCSIFDSTADDR, &if_dstaddr) < 0) {
fprintf(stderr, "Error setting the slave with SIOCSIFDSTADDR: %s.\n",
strerror(errno));
} else {
if (verbose) {
unsigned char *ipaddr =3D if_dstaddr.ifr_dstaddr.sa_data;
printf("Set the slave's destination address to %d.%d.%d.%d.\n",
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
}
}

if (strncpy(if_brdaddr.ifr_name, slave_ifname, IFNAMSIZ) <=3D 0
|| ioctl(skfd, SIOCSIFBRDADDR, &if_brdaddr) < 0) {
fprintf(stderr,
"Something broke setting the slave broadcast address: %s.\n",
strerror(errno));
} else {
if (verbose) {
unsigned char *ipaddr =3D if_brdaddr.ifr_broadaddr.sa_data;
printf("Set the slave's broadcast address to %d.%d.%d.%d.\n",
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
}
}
=09
if (strncpy(if_netmask.ifr_name, slave_ifname, IFNAMSIZ) <=3D 0
|| ioctl(skfd, SIOCSIFNETMASK, &if_netmask) < 0) {
fprintf(stderr,
"Something broke setting the slave netmask: %s.\n",
strerror(errno));
} else {
if (verbose) {
unsigned char *ipaddr =3D if_netmask.ifr_netmask.sa_data;
printf("Set the slave's netmask to %d.%d.%d.%d.\n",
ipaddr[0], ipaddr[1], ipaddr[2], ipaddr[3]);
}
}
=09
if ((if_flags.ifr_flags &=3D ~(IFF_SLAVE | IFF_MASTER)) =3D=3D 0
|| strncpy(if_flags.ifr_name, slave_ifname, IFNAMSIZ) <=3D 0
|| ioctl(skfd, SIOCSIFFLAGS, &if_flags) < 0) {
fprintf(stderr,
"Something broke setting the slave flags: %s.\n",
strerror(errno));
} else {
if (verbose)
printf("Set the slave's flags %4.4x.\n", if_flags.ifr_flags);
}

/* Do the real thing: set the second interface as a slave. */
if ( ! opt_r) {
strncpy(if_flags.ifr_name, master_ifname, IFNAMSIZ);
strncpy(if_flags.ifr_slave, slave_ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCSIFSLAVE, &if_flags) < 0) {
fprintf(stderr, "SIOCSIFSLAVE: %s.\n", strerror(errno));
}
}
} while ( (slave_ifname =3D *spp++) !=3D NULL);

/* Close the socket. */
(void) close(skfd);

return(goterr);
}

static short mif_flags;

/* Get the inteface configuration from the kernel. */
static int if_getconfig(char *ifname)
{
struct ifreq ifr;
int metric, mtu; /* Parameters of the master interface. */
struct sockaddr dstaddr, broadaddr, netmask;

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
return -1;
mif_flags =3D ifr.ifr_flags;
printf("The result of SIOCGIFFLAGS on %s is %x.\n",
ifname, ifr.ifr_flags);

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
return -1;
printf("The result of SIOCGIFADDR is %2.2x.%2.2x.%2.2x.%2.2x.\n",
ifr.ifr_addr.sa_data[0], ifr.ifr_addr.sa_data[1],
ifr.ifr_addr.sa_data[2], ifr.ifr_addr.sa_data[3]);

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
return -1;

{ /* Gotta convert from 'char' to unsigned for printf(). */
unsigned char *hwaddr =3D (unsigned char *)ifr.ifr_hwaddr.sa_data;
printf("The result of SIOCGIFHWADDR is type %d "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x.\n",
ifr.ifr_hwaddr.sa_family, hwaddr[0], hwaddr[1],
hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
}

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFMETRIC, &ifr) < 0) {
metric =3D 0;
} else
metric =3D ifr.ifr_metric;

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFMTU, &ifr) < 0)
mtu =3D 0;
else
mtu =3D ifr.ifr_mtu;

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFDSTADDR, &ifr) < 0) {
memset(&dstaddr, 0, sizeof(struct sockaddr));
} else
dstaddr =3D ifr.ifr_dstaddr;

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0) {
memset(&broadaddr, 0, sizeof(struct sockaddr));
} else
broadaddr =3D ifr.ifr_broadaddr;

strcpy(ifr.ifr_name, ifname);
if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
memset(&netmask, 0, sizeof(struct sockaddr));
} else
netmask =3D ifr.ifr_netmask;

return(0);
}

static void if_print(char *ifname)
{
char buff[1024];
struct ifconf ifc;
struct ifreq *ifr;
int i;

if (ifname =3D=3D (char *)NULL) {
ifc.ifc_len =3D sizeof(buff);
ifc.ifc_buf =3D buff;
if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
return;
}

ifr =3D ifc.ifc_req;
for (i =3D ifc.ifc_len / sizeof(struct ifreq); --i >=3D 0; ifr++) {
if (if_getconfig(ifr->ifr_name) < 0) {
fprintf(stderr, "%s: unknown interface.\n",
ifr->ifr_name);
continue;
}

if (((mif_flags & IFF_UP) =3D=3D 0) && !opt_a) continue;
/*ife_print(&ife);*/
}
} else {
if (if_getconfig(ifname) < 0)
fprintf(stderr, "%s: unknown interface.\n", ifname);
}
}

=0C
/*
* Local variables:
* version-control: t
* kept-new-versions: 5
* c-indent-level: 4
* c-basic-offset: 4
* tab-width: 4
* compile-command: "gcc -Wall -Wstrict-prototypes -O ifenslave.c -o ifens=
lave"
* End:
*/

--C7zPtVaVf+AK4Oqc--

--4bRzO86E/ozDv8r1
Content-Type: application/pgp-signature

-----BEGIN PGP SIGNATURE-----
Version: 2.6.3ia

iQCVAgUBNtbT3sMnaHd2HseJAQHzaAQAhTTnArAVhrP7W74i03IrEDeH1ph569Ov
zUu7slg7oAMDwx/11Eacu3ULMQ1oFDs7esSN8u184qGq8ZsHh0OTmfDp6ctOxRc+
gtgdTLDJjLSxG71MzHx6vJj/bbEsu+MvzBNZ22YnmI68kmQnqDF2M2xCy2c5ADVu
007/iUJghqk=
=nTuO
-----END PGP SIGNATURE-----

--4bRzO86E/ozDv8r1--

-
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/