NetBSD/sys/altq/altq_conf.c
jdolecek e0cc03a09b merge kqueue branch into -current
kqueue provides a stateful and efficient event notification framework
currently supported events include socket, file, directory, fifo,
pipe, tty and device changes, and monitoring of processes and signals

kqueue is supported by all writable filesystems in NetBSD tree
(with exception of Coda) and all device drivers supporting poll(2)

based on work done by Jonathan Lemon for FreeBSD
initial NetBSD port done by Luke Mewburn and Jason Thorpe
2002-10-23 09:10:23 +00:00

454 lines
10 KiB
C

/* $NetBSD: altq_conf.c,v 1.10 2002/10/23 09:10:25 jdolecek Exp $ */
/* $KAME: altq_conf.c,v 1.13 2002/01/29 10:16:01 kjc Exp $ */
/*
* Copyright (C) 1997-2000
* Sony Computer Science Laboratories Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY SONY CSL AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL SONY CSL OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: altq_conf.c,v 1.10 2002/10/23 09:10:25 jdolecek Exp $");
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include "opt_altq.h"
#if (__FreeBSD__ != 2)
#include "opt_inet.h"
#ifdef __FreeBSD__
#include "opt_inet6.h"
#endif
#endif
#endif /* __FreeBSD__ || __NetBSD__ */
/*
* altq device interface.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/socket.h>
#include <sys/kernel.h>
#include <sys/proc.h>
#include <sys/errno.h>
#if defined(__FreeBSD__) && (__FreeBSD_version < 400000) && defined(DEVFS)
#include <sys/devfsext.h>
#endif /*DEVFS*/
#include <net/if.h>
#include <altq/altq.h>
#include <altq/altqconf.h>
#include <altq/altq_conf.h>
#ifdef ALTQ_CBQ
altqdev_decl(cbq);
#endif
#ifdef ALTQ_WFQ
altqdev_decl(wfq);
#endif
#ifdef ALTQ_AFMAP
altqdev_decl(afm);
#endif
#ifdef ALTQ_FIFOQ
altqdev_decl(fifoq);
#endif
#ifdef ALTQ_RED
altqdev_decl(red);
#endif
#ifdef ALTQ_RIO
altqdev_decl(rio);
#endif
#ifdef ALTQ_LOCALQ
altqdev_decl(localq);
#endif
#ifdef ALTQ_HFSC
altqdev_decl(hfsc);
#endif
#ifdef ALTQ_CDNR
altqdev_decl(cdnr);
#endif
#ifdef ALTQ_BLUE
altqdev_decl(blue);
#endif
#ifdef ALTQ_PRIQ
altqdev_decl(priq);
#endif
/*
* altq minor device (discipline) table
*/
static struct altqsw altqsw[] = { /* minor */
{"noq", noopen, noclose, noioctl}, /* 0 (reserved) */
#ifdef ALTQ_CBQ
{"cbq", cbqopen, cbqclose, cbqioctl}, /* 1 */
#else
{"noq", noopen, noclose, noioctl}, /* 1 */
#endif
#ifdef ALTQ_WFQ
{"wfq", wfqopen, wfqclose, wfqioctl}, /* 2 */
#else
{"noq", noopen, noclose, noioctl}, /* 2 */
#endif
#ifdef ALTQ_AFMAP
{"afm", afmopen, afmclose, afmioctl}, /* 3 */
#else
{"noq", noopen, noclose, noioctl}, /* 3 */
#endif
#ifdef ALTQ_FIFOQ
{"fifoq", fifoqopen, fifoqclose, fifoqioctl}, /* 4 */
#else
{"noq", noopen, noclose, noioctl}, /* 4 */
#endif
#ifdef ALTQ_RED
{"red", redopen, redclose, redioctl}, /* 5 */
#else
{"noq", noopen, noclose, noioctl}, /* 5 */
#endif
#ifdef ALTQ_RIO
{"rio", rioopen, rioclose, rioioctl}, /* 6 */
#else
{"noq", noopen, noclose, noioctl}, /* 6 */
#endif
#ifdef ALTQ_LOCALQ
{"localq",localqopen, localqclose, localqioctl}, /* 7 (local use) */
#else
{"noq", noopen, noclose, noioctl}, /* 7 (local use) */
#endif
#ifdef ALTQ_HFSC
{"hfsc",hfscopen, hfscclose, hfscioctl}, /* 8 */
#else
{"noq", noopen, noclose, noioctl}, /* 8 */
#endif
#ifdef ALTQ_CDNR
{"cdnr",cdnropen, cdnrclose, cdnrioctl}, /* 9 */
#else
{"noq", noopen, noclose, noioctl}, /* 9 */
#endif
#ifdef ALTQ_BLUE
{"blue",blueopen, blueclose, blueioctl}, /* 10 */
#else
{"noq", noopen, noclose, noioctl}, /* 10 */
#endif
#ifdef ALTQ_PRIQ
{"priq",priqopen, priqclose, priqioctl}, /* 11 */
#else
{"noq", noopen, noclose, noioctl}, /* 11 */
#endif
};
/*
* altq major device support
*/
int naltqsw = sizeof (altqsw) / sizeof (altqsw[0]);
#if defined(__NetBSD__)
dev_type_open(altqopen);
dev_type_close(altqclose);
dev_type_ioctl(altqioctl);
#endif
#if defined(__OpenBSD__)
static d_open_t altqopen;
static d_close_t altqclose;
static d_ioctl_t altqioctl;
#endif
#ifdef __FreeBSD__
static void altq_drvinit __P((void *));
#else
void altqattach __P((int));
#endif
#if defined(__FreeBSD__)
#define CDEV_MAJOR 96 /* FreeBSD official number */
#elif defined(__OpenBSD__)
#if defined(__i386__)
#define CDEV_MAJOR 74 /* OpenBSD i386 (official) */
#elif defined(__alpha__)
#define CDEV_MAJOR 53 /* OpenBSD alpha (official) */
#else
#error arch not supported
#endif
#endif
#if defined(__FreeBSD__)
#if (__FreeBSD_version < 400000)
static struct cdevsw altq_cdevsw =
{ altqopen, altqclose, noread, nowrite,
altqioctl, nostop, nullreset, nodevtotty,
seltrue, nommap, NULL, "altq", NULL, -1 };
#else
static struct cdevsw altq_cdevsw =
{ altqopen, altqclose, noread, nowrite,
altqioctl, seltrue, nommap, nostrategy,
"altq", CDEV_MAJOR, nodump, nopsize, 0, -1 };
#endif
#endif
#if defined(__NetBSD__)
const struct cdevsw altq_cdevsw = {
altqopen, altqclose, noread, nowrite, altqioctl,
nostop, notty, nopoll, nommap, nokqfilter
};
#endif
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
static
#endif
int
altqopen(dev, flag, fmt, p)
dev_t dev;
int flag, fmt;
struct proc *p;
{
int unit = minor(dev);
if (unit == 0)
return (0);
if (unit < naltqsw)
return (*altqsw[unit].d_open)(dev, flag, fmt, p);
return ENXIO;
}
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
static
#endif
int
altqclose(dev, flag, fmt, p)
dev_t dev;
int flag, fmt;
struct proc *p;
{
int unit = minor(dev);
if (unit == 0)
return (0);
if (unit < naltqsw)
return (*altqsw[unit].d_close)(dev, flag, fmt, p);
return ENXIO;
}
#if !defined(__NetBSD__) && !defined(__OpenBSD__)
static
#endif
int
altqioctl(dev, cmd, addr, flag, p)
dev_t dev;
ioctlcmd_t cmd;
caddr_t addr;
int flag;
struct proc *p;
{
int unit = minor(dev);
if (unit == 0) {
struct ifnet *ifp;
struct altqreq *typereq;
struct tbrreq *tbrreq;
int error;
switch (cmd) {
case ALTQGTYPE:
case ALTQTBRGET:
break;
default:
#if (__FreeBSD_version > 400000)
if ((error = suser(p)) != 0)
return (error);
#else
if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
return (error);
#endif
break;
}
switch (cmd) {
case ALTQGTYPE:
typereq = (struct altqreq *)addr;
if ((ifp = ifunit(typereq->ifname)) == NULL)
return (EINVAL);
typereq->arg = (u_long)ifp->if_snd.altq_type;
return (0);
case ALTQTBRSET:
tbrreq = (struct tbrreq *)addr;
if ((ifp = ifunit(tbrreq->ifname)) == NULL)
return (EINVAL);
return tbr_set(&ifp->if_snd, &tbrreq->tb_prof);
case ALTQTBRGET:
tbrreq = (struct tbrreq *)addr;
if ((ifp = ifunit(tbrreq->ifname)) == NULL)
return (EINVAL);
return tbr_get(&ifp->if_snd, &tbrreq->tb_prof);
default:
return (EINVAL);
}
}
if (unit < naltqsw)
return (*altqsw[unit].d_ioctl)(dev, cmd, addr, flag, p);
return ENXIO;
}
#if !defined(__NetBSD__)
static int altq_devsw_installed = 0;
#endif
#ifdef __FreeBSD__
#if (__FreeBSD_version < 400000)
#ifdef DEVFS
static void *altq_devfs_token[sizeof (altqsw) / sizeof (altqsw[0])];
#endif
static void
altq_drvinit(unused)
void *unused;
{
dev_t dev;
#ifdef DEVFS
int i;
#endif
if (!altq_devsw_installed) {
dev = makedev(CDEV_MAJOR,0);
cdevsw_add(&dev,&altq_cdevsw,NULL);
altq_devsw_installed = 1;
#ifdef DEVFS
for (i=0; i<naltqsw; i++)
altq_devfs_token[i] =
devfs_add_devswf(&altq_cdevsw, i, DV_CHR,
0, 0, 0644, altqsw[i].d_name);
#endif
printf("altq: major number is %d\n", CDEV_MAJOR);
}
}
#else /* FreeBSD 4.x */
static void
altq_drvinit(unused)
void *unused;
{
int unit;
cdevsw_add(&altq_cdevsw);
altq_devsw_installed = 1;
printf("altq: major number is %d\n", CDEV_MAJOR);
/* create minor devices */
for (unit = 0; unit < naltqsw; unit++)
make_dev(&altq_cdevsw, unit, 0, 0, 0644,
altqsw[unit].d_name);
}
#endif /* FreeBSD 4.x */
SYSINIT(altqdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,altq_drvinit,NULL)
#endif
#ifdef ALTQ_KLD
/*
* KLD support
*/
static int altq_module_register __P((struct altq_module_data *));
static int altq_module_deregister __P((struct altq_module_data *));
static struct altq_module_data *altq_modules[ALTQT_MAX];
static struct altqsw noqdisc = {"noq", noopen, noclose, noioctl};
void altq_module_incref(type)
int type;
{
if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
return;
altq_modules[type]->ref++;
}
void altq_module_declref(type)
int type;
{
if (type < 0 || type >= ALTQT_MAX || altq_modules[type] == NULL)
return;
altq_modules[type]->ref--;
}
static int
altq_module_register(mdata)
struct altq_module_data *mdata;
{
int type = mdata->type;
if (type < 0 || type >= ALTQT_MAX)
return (EINVAL);
if (altqsw[type].d_open != noopen)
return (EBUSY);
altqsw[type] = *mdata->altqsw; /* set discipline functions */
altq_modules[type] = mdata; /* save module data pointer */
return (0);
}
static int
altq_module_deregister(mdata)
struct altq_module_data *mdata;
{
int type = mdata->type;
if (type < 0 || type >= ALTQT_MAX)
return (EINVAL);
if (mdata != altq_modules[type])
return (EINVAL);
if (altq_modules[type]->ref > 0)
return (EBUSY);
altqsw[type] = noqdisc;
altq_modules[type] = NULL;
return (0);
}
int
altq_module_handler(mod, cmd, arg)
module_t mod;
int cmd;
void * arg;
{
struct altq_module_data *data = (struct altq_module_data *)arg;
int error = 0;
switch (cmd) {
case MOD_LOAD:
error = altq_module_register(data);
break;
case MOD_UNLOAD:
error = altq_module_deregister(data);
break;
default:
error = EINVAL;
break;
}
return(error);
}
#endif /* ALTQ_KLD */