2007-04-10 02:27:25 +02:00
|
|
|
/*-
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef lint
|
|
|
|
static const char rcsid[] =
|
|
|
|
"$FreeBSD$";
|
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/sockio.h>
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include <net/ethernet.h>
|
|
|
|
#include <net/if.h>
|
2007-04-17 02:35:11 +02:00
|
|
|
#include <net/if_lagg.h>
|
2007-04-10 02:27:25 +02:00
|
|
|
#include <net/route.h>
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <err.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "ifconfig.h"
|
|
|
|
|
|
|
|
static void
|
2007-04-17 02:35:11 +02:00
|
|
|
setlaggport(const char *val, int d, int s, const struct afswtch *afp)
|
2007-04-10 02:27:25 +02:00
|
|
|
{
|
2007-04-17 02:35:11 +02:00
|
|
|
struct lagg_reqport rp;
|
2007-04-10 02:27:25 +02:00
|
|
|
|
|
|
|
bzero(&rp, sizeof(rp));
|
|
|
|
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
|
|
|
|
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
if (ioctl(s, SIOCSLAGGPORT, &rp))
|
|
|
|
err(1, "SIOCSLAGGPORT");
|
2007-04-10 02:27:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-04-17 02:35:11 +02:00
|
|
|
unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
|
2007-04-10 02:27:25 +02:00
|
|
|
{
|
2007-04-17 02:35:11 +02:00
|
|
|
struct lagg_reqport rp;
|
2007-04-10 02:27:25 +02:00
|
|
|
|
|
|
|
bzero(&rp, sizeof(rp));
|
|
|
|
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
|
|
|
|
strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
if (ioctl(s, SIOCSLAGGDELPORT, &rp))
|
|
|
|
err(1, "SIOCSLAGGDELPORT");
|
2007-04-10 02:27:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-04-17 02:35:11 +02:00
|
|
|
setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
|
2007-04-10 02:27:25 +02:00
|
|
|
{
|
2007-04-17 02:35:11 +02:00
|
|
|
struct lagg_protos tpr[] = LAGG_PROTOS;
|
|
|
|
struct lagg_reqall ra;
|
2007-04-10 02:27:25 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
bzero(&ra, sizeof(ra));
|
2007-04-17 02:35:11 +02:00
|
|
|
ra.ra_proto = LAGG_PROTO_MAX;
|
2007-04-10 02:27:25 +02:00
|
|
|
|
|
|
|
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) {
|
|
|
|
if (strcmp(val, tpr[i].tpr_name) == 0) {
|
|
|
|
ra.ra_proto = tpr[i].tpr_proto;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2007-04-17 02:35:11 +02:00
|
|
|
if (ra.ra_proto == LAGG_PROTO_MAX)
|
|
|
|
errx(1, "Invalid aggregation protocol: %s", val);
|
2007-04-10 02:27:25 +02:00
|
|
|
|
|
|
|
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
|
2007-04-17 02:35:11 +02:00
|
|
|
if (ioctl(s, SIOCSLAGG, &ra) != 0)
|
|
|
|
err(1, "SIOCSLAGG");
|
2007-04-10 02:27:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-04-17 02:35:11 +02:00
|
|
|
lagg_status(int s)
|
2007-04-10 02:27:25 +02:00
|
|
|
{
|
2007-04-17 02:35:11 +02:00
|
|
|
struct lagg_protos tpr[] = LAGG_PROTOS;
|
|
|
|
struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
|
|
|
|
struct lagg_reqall ra;
|
2007-04-10 02:27:25 +02:00
|
|
|
const char *proto = "<unknown>";
|
|
|
|
int i, isport = 0;
|
|
|
|
|
|
|
|
bzero(&rp, sizeof(rp));
|
|
|
|
bzero(&ra, sizeof(ra));
|
|
|
|
|
|
|
|
strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
|
|
|
|
strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
if (ioctl(s, SIOCGLAGGPORT, &rp) == 0)
|
2007-04-10 02:27:25 +02:00
|
|
|
isport = 1;
|
|
|
|
|
|
|
|
strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
|
|
|
|
ra.ra_size = sizeof(rpbuf);
|
|
|
|
ra.ra_port = rpbuf;
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
if (ioctl(s, SIOCGLAGG, &ra) == 0) {
|
2007-04-10 02:27:25 +02:00
|
|
|
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++) {
|
|
|
|
if (ra.ra_proto == tpr[i].tpr_proto) {
|
|
|
|
proto = tpr[i].tpr_name;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
printf("\tlagg: laggproto %s", proto);
|
2007-04-10 02:27:25 +02:00
|
|
|
if (isport)
|
2007-04-17 02:35:11 +02:00
|
|
|
printf(" laggdev %s", rp.rp_ifname);
|
2007-04-10 02:27:25 +02:00
|
|
|
putchar('\n');
|
|
|
|
|
|
|
|
for (i = 0; i < ra.ra_ports; i++) {
|
2007-04-17 02:35:11 +02:00
|
|
|
printf("\t\tlaggport %s ", rpbuf[i].rp_portname);
|
|
|
|
printb("", rpbuf[i].rp_flags, LAGG_PORT_BITS);
|
2007-04-10 02:27:25 +02:00
|
|
|
putchar('\n');
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 /* XXX */) {
|
2007-04-17 02:35:11 +02:00
|
|
|
printf("\tsupported aggregation protocols:\n");
|
2007-04-10 02:27:25 +02:00
|
|
|
for (i = 0; i < (sizeof(tpr) / sizeof(tpr[0])); i++)
|
2007-04-17 02:35:11 +02:00
|
|
|
printf("\t\tlaggproto %s\n", tpr[i].tpr_name);
|
2007-04-10 02:27:25 +02:00
|
|
|
}
|
|
|
|
} else if (isport)
|
2007-04-17 02:35:11 +02:00
|
|
|
printf("\tlagg: laggdev %s\n", rp.rp_ifname);
|
2007-04-10 02:27:25 +02:00
|
|
|
}
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
static struct cmd lagg_cmds[] = {
|
|
|
|
DEF_CMD_ARG("laggport", setlaggport),
|
|
|
|
DEF_CMD_ARG("-laggport", unsetlaggport),
|
|
|
|
DEF_CMD_ARG("laggproto", setlaggproto),
|
2007-04-10 02:27:25 +02:00
|
|
|
};
|
2007-04-17 02:35:11 +02:00
|
|
|
static struct afswtch af_lagg = {
|
|
|
|
.af_name = "af_lagg",
|
2007-04-10 02:27:25 +02:00
|
|
|
.af_af = AF_UNSPEC,
|
2007-04-17 02:35:11 +02:00
|
|
|
.af_other_status = lagg_status,
|
2007-04-10 02:27:25 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static __constructor void
|
2007-04-17 02:35:11 +02:00
|
|
|
lagg_ctor(void)
|
2007-04-10 02:27:25 +02:00
|
|
|
{
|
|
|
|
#define N(a) (sizeof(a) / sizeof(a[0]))
|
|
|
|
int i;
|
|
|
|
|
2007-04-17 02:35:11 +02:00
|
|
|
for (i = 0; i < N(lagg_cmds); i++)
|
|
|
|
cmd_register(&lagg_cmds[i]);
|
|
|
|
af_register(&af_lagg);
|
2007-04-10 02:27:25 +02:00
|
|
|
#undef N
|
|
|
|
}
|