diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/altq/altq_cbq.c | 332 | ||||
-rw-r--r-- | sys/altq/altq_cbq.h | 18 | ||||
-rw-r--r-- | sys/altq/altq_red.c | 44 | ||||
-rw-r--r-- | sys/altq/altq_subr.c | 38 | ||||
-rw-r--r-- | sys/altq/altq_var.h | 12 |
5 files changed, 395 insertions, 49 deletions
diff --git a/sys/altq/altq_cbq.c b/sys/altq/altq_cbq.c index 6800608635d..97864cbffa1 100644 --- a/sys/altq/altq_cbq.c +++ b/sys/altq/altq_cbq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: altq_cbq.c,v 1.5 2002/10/05 02:57:58 kjc Exp $ */ +/* $OpenBSD: altq_cbq.c,v 1.6 2002/10/11 09:30:30 kjc Exp $ */ /* $KAME: altq_cbq.c,v 1.9 2000/12/14 08:12:45 thorpej Exp $ */ /* @@ -46,6 +46,7 @@ #include <net/if_types.h> #include <netinet/in.h> +#include <net/pfvar.h> #include <altq/altq.h> #include <altq/altq_conf.h> #include <altq/altq_cbq.h> @@ -65,7 +66,7 @@ static int cbq_modify_class(struct cbq_modify_class *); static int cbq_class_create(cbq_state_t *, struct cbq_add_class *, struct rm_class *, struct rm_class *); static int cbq_class_destroy(cbq_state_t *, struct rm_class *); -static struct rm_class *clh_to_clp(cbq_state_t *, u_long); +static struct rm_class *clh_to_clp(cbq_state_t *, u_int32_t); static int cbq_add_filter(struct cbq_add_filter *); static int cbq_delete_filter(struct cbq_delete_filter *); @@ -173,7 +174,7 @@ cbq_modify_class(acp) /* * struct rm_class * * cbq_class_create(cbq_mod_state_t *cbqp, struct cbq_add_class *acp, - * u_long handle, struct rm_class *parent, + * u_int32_t handle, struct rm_class *parent, * struct rm_class *borrow) * * This function create a new traffic class in the CBQ class hierarchy of @@ -189,7 +190,7 @@ cbq_class_create(cbqp, acp, parent, borrow) { struct rm_class *cl; cbq_class_spec_t *spec = &acp->cbq_class; - u_long chandle; + u_int32_t chandle; int i; /* @@ -220,7 +221,7 @@ cbq_class_create(cbqp, acp, parent, borrow) break; if (i == CBQ_MAX_CLASSES) return (ENOSPC); - chandle = (u_long)i; + chandle = (u_int32_t)i; break; default: /* more than two flags bits set */ @@ -282,7 +283,7 @@ cbq_class_destroy(cbqp, cl) cbq_state_t *cbqp; struct rm_class *cl; { - u_long chandle; + u_int32_t chandle; chandle = cl->stats_.handle; @@ -317,7 +318,7 @@ cbq_class_destroy(cbqp, cl) static struct rm_class * clh_to_clp(cbqp, chandle) cbq_state_t *cbqp; - u_long chandle; + u_int32_t chandle; { switch (chandle) { case NULL_CLASS_HANDLE: @@ -564,6 +565,9 @@ cbq_getstats(gsp) case 2: cl = cbqp->ifnp.ctl_; stats.handle = CTL_CLASS_HANDLE; +#if 1 /* PFALTQ */ + if (cl != NULL) +#endif break; default: while ((cl = cbqp->cbq_class_tbl[chandle]) == NULL) @@ -585,6 +589,296 @@ cbq_getstats(gsp) return (error); } +#if 1 /* PFALTQ */ + +int +cbq_pfattach(struct pf_altq *a) +{ + struct ifnet *ifp; + int s, error; + + if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL) + return (EINVAL); + s = splimp(); + error = altq_attach(&ifp->if_snd, ALTQT_CBQ, a->altq_disc, + cbq_enqueue, cbq_dequeue, cbq_request, NULL, NULL); + splx(s); + return (error); +} + +int +cbq_add_altq(struct pf_altq *a) +{ + cbq_state_t *cbqp; + struct ifnet *ifp; + + if ((ifp = ifunit(a->ifname)) == NULL) + return (ENXIO); + if (!ALTQ_IS_READY(&ifp->if_snd)) + return (ENXIO); + + /* allocate and initialize cbq_state_t */ + MALLOC(cbqp, cbq_state_t *, sizeof(cbq_state_t), M_DEVBUF, M_WAITOK); + if (cbqp == NULL) + return (ENOMEM); + bzero(cbqp, sizeof(cbq_state_t)); + CALLOUT_INIT(&cbqp->cbq_callout); + MALLOC(cbqp->cbq_class_tbl, struct rm_class **, + sizeof(struct rm_class *) * CBQ_MAX_CLASSES, M_DEVBUF, M_WAITOK); + if (cbqp->cbq_class_tbl == NULL) { + FREE(cbqp, M_DEVBUF); + return (ENOMEM); + } + bzero(cbqp->cbq_class_tbl, sizeof(struct rm_class *) * CBQ_MAX_CLASSES); + cbqp->cbq_qlen = 0; + cbqp->ifnp.ifq_ = &ifp->if_snd; /* keep the ifq */ + + /* keep the state in pf_altq */ + a->altq_disc = cbqp; + + /* prepend to the list of cbq_state_t's. */ + cbqp->cbq_next = cbq_list; + cbq_list = cbqp; + + return (0); +} + +int +cbq_remove_altq(struct pf_altq *a) +{ + cbq_state_t *cbqp; + + if ((cbqp = a->altq_disc) == NULL) + return (EINVAL); + a->altq_disc = NULL; + + cbq_clear_interface(cbqp); + + if (cbqp->ifnp.ctl_) + cbq_class_destroy(cbqp, cbqp->ifnp.ctl_); + if (cbqp->ifnp.default_) + cbq_class_destroy(cbqp, cbqp->ifnp.default_); + if (cbqp->ifnp.root_) + cbq_class_destroy(cbqp, cbqp->ifnp.root_); + + /* remove from the list of cbq_state_t's. */ + if (cbq_list == cbqp) + cbq_list = cbqp->cbq_next; + else { + cbq_state_t *cp; + + for (cp = cbq_list; cp != NULL; cp = cp->cbq_next) + if (cp->cbq_next == cbqp) { + cp->cbq_next = cbqp->cbq_next; + break; + } + ASSERT(cp != NULL); + } + + /* deallocate cbq_state_t */ + FREE(cbqp->cbq_class_tbl, M_DEVBUF); + FREE(cbqp, M_DEVBUF); + + return (0); +} + +int +cbq_add_queue(struct pf_altq *a) +{ + struct rm_class *borrow, *parent; + cbq_state_t *cbqp; + struct rm_class *cl; + struct cbq_opts *opts; + u_int32_t chandle; + int i; + + if ((cbqp = a->altq_disc) == NULL) + return (EINVAL); + + opts = &a->pq_u.cbq_opts; + /* check parameters */ + if (a->priority >= RM_MAXPRIO) + return (EINVAL); + + /* Get pointers to parent and borrow classes. */ + parent = clh_to_clp(cbqp, a->parent_qid); + if (opts->flags & CBQCLF_BORROW) + borrow = parent; + else + borrow = NULL; + + /* + * A class must borrow from it's parent or it can not + * borrow at all. Hence, borrow can be null. + */ + + if (parent == NULL && (opts->flags & CBQCLF_ROOTCLASS) == 0) { + printf("cbq_add_queue: no parent class!\n"); + return (EINVAL); + } + + if ((borrow != parent) && (borrow != NULL)) { + printf("cbq_add_class: borrow class != parent\n"); + return (EINVAL); + } + + /* + * allocate class handle + */ + switch (opts->flags & CBQCLF_CLASSMASK) { + case CBQCLF_ROOTCLASS: + if (parent != NULL) + return (EINVAL); + if (cbqp->ifnp.root_) + return (EINVAL); + chandle = ROOT_CLASS_HANDLE; + break; + case CBQCLF_DEFCLASS: + if (cbqp->ifnp.default_) + return (EINVAL); + chandle = DEFAULT_CLASS_HANDLE; + break; + case CBQCLF_CTLCLASS: + if (cbqp->ifnp.ctl_) + return (EINVAL); + chandle = CTL_CLASS_HANDLE; + break; + case 0: + /* find a free class slot */ +#if 1 /* PFALTQ */ + /* for now, reserve qid 0 */ + for (i = 1; i < CBQ_MAX_CLASSES; i++) +#else + for (i = 0; i < CBQ_MAX_CLASSES; i++) +#endif + if (cbqp->cbq_class_tbl[i] == NULL) + break; + if (i == CBQ_MAX_CLASSES) + return (ENOSPC); + chandle = (u_int32_t)i; + break; + default: + /* more than two flags bits set */ + return (EINVAL); + } + + /* + * create a class. if this is a root class, initialize the + * interface. + */ + if (chandle == ROOT_CLASS_HANDLE) { + rmc_init(cbqp->ifnp.ifq_, &cbqp->ifnp, opts->ns_per_byte, + cbqrestart, a->qlimit, RM_MAXQUEUED, + opts->maxidle, opts->minidle, opts->offtime, + opts->flags); + cl = cbqp->ifnp.root_; + } else { + cl = rmc_newclass(a->priority, + &cbqp->ifnp, opts->ns_per_byte, + rmc_delay_action, a->qlimit, parent, borrow, + opts->maxidle, opts->minidle, opts->offtime, + opts->pktsize, opts->flags); + } + if (cl == NULL) + return (ENOMEM); + + /* return handle to user space. */ + a->qid = chandle; + + cl->stats_.handle = chandle; + cl->stats_.depth = cl->depth_; + + /* save the allocated class */ + switch (chandle) { + case NULL_CLASS_HANDLE: + case ROOT_CLASS_HANDLE: + break; + case DEFAULT_CLASS_HANDLE: + cbqp->ifnp.default_ = cl; + break; + case CTL_CLASS_HANDLE: + cbqp->ifnp.ctl_ = cl; + break; + default: + cbqp->cbq_class_tbl[chandle] = cl; + break; + } + return (0); +} + +int +cbq_remove_queue(struct pf_altq *a) +{ + struct rm_class *cl; + cbq_state_t *cbqp; + + if ((cbqp = a->altq_disc) == NULL) + return (EINVAL); + + if ((cl = clh_to_clp(cbqp, a->qid)) == NULL) + return (EINVAL); + + /* if we are a parent class, then return an error. */ + if (is_a_parent_class(cl)) + return (EINVAL); + + /* delete the class */ + rmc_delete_class(&cbqp->ifnp, cl); + + /* + * free the class handle + */ + switch (a->qid) { + case ROOT_CLASS_HANDLE: + cbqp->ifnp.root_ = NULL; + break; + case DEFAULT_CLASS_HANDLE: + cbqp->ifnp.default_ = NULL; + break; + case CTL_CLASS_HANDLE: + cbqp->ifnp.ctl_ = NULL; + break; + case NULL_CLASS_HANDLE: + break; + default: + if (a->qid >= CBQ_MAX_CLASSES) + break; + cbqp->cbq_class_tbl[a->qid] = NULL; + } + + return (0); +} + +int +cbq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes) +{ + cbq_state_t *cbqp; + struct rm_class *cl; + class_stats_t stats; + int error = 0; + + if ((cbqp = altq_lookup(a->ifname, ALTQT_CBQ)) == NULL) + return (EBADF); + + if ((cl = clh_to_clp(cbqp, a->qid)) == NULL) + return (EINVAL); + + if (*nbytes < sizeof(stats)) + return (EINVAL); + + get_class_stats(&stats, cl); +#if 1 + stats.handle = a->qid; +#endif + + if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0) + return (error); + *nbytes = sizeof(stats); + return (0); +} + +#endif /* PFALTQ */ + static int cbq_ifattach(ifacep) struct cbq_interface *ifacep; @@ -707,9 +1001,25 @@ cbq_enqueue(ifq, m, pktattr) int len; /* grab class set by classifier */ - if (pktattr == NULL || (cl = pktattr->pattr_class) == NULL) - cl = cbqp->ifnp.default_; - cl->pktattr_ = pktattr; /* save proto hdr used by ECN */ + if (PFALTQ_IS_ACTIVE()) { + struct m_tag *t; + + t = m_tag_find(m, PACKET_TAG_PF_QID, NULL); + if (t == NULL || + (cl = clh_to_clp(cbqp, ((struct altq_tag *)(t+1))->qid)) + == NULL) { + cl = cbqp->ifnp.default_; + if (cl == NULL) { + m_freem(m); + return (ENOBUFS); + } + } + cl->pktattr_ = NULL; + } else { + if (pktattr == NULL || (cl = pktattr->pattr_class) == NULL) + cl = cbqp->ifnp.default_; + cl->pktattr_ = pktattr; /* save proto hdr used by ECN */ + } len = m_pktlen(m); if (rmc_queue_packet(cl, m) != 0) { @@ -797,6 +1107,8 @@ cbqopen(dev, flag, fmt, p) int flag, fmt; struct proc *p; { + if (PFALTQ_IS_ACTIVE()) + return (EBUSY); return (0); } diff --git a/sys/altq/altq_cbq.h b/sys/altq/altq_cbq.h index 6cc9d08185d..5c9ab0a96dc 100644 --- a/sys/altq/altq_cbq.h +++ b/sys/altq/altq_cbq.h @@ -1,4 +1,4 @@ -/* $OpenBSD: altq_cbq.h,v 1.2 2002/10/10 10:44:02 kjc Exp $ */ +/* $OpenBSD: altq_cbq.h,v 1.3 2002/10/11 09:30:30 kjc Exp $ */ /* $KAME: altq_cbq.h,v 1.5 2000/12/02 13:44:40 kjc Exp $ */ /* @@ -74,8 +74,8 @@ typedef struct cbq_class_spec { u_int maxidle; int minidle; u_int offtime; - u_long parent_class_handle; - u_long borrow_class_handle; + u_int32_t parent_class_handle; + u_int32_t borrow_class_handle; u_int pktsize; int flags; @@ -105,24 +105,24 @@ struct cbq_add_class { struct cbq_interface cbq_iface; cbq_class_spec_t cbq_class; - u_long cbq_class_handle; + u_int32_t cbq_class_handle; }; struct cbq_delete_class { struct cbq_interface cbq_iface; - u_long cbq_class_handle; + u_int32_t cbq_class_handle; }; struct cbq_modify_class { struct cbq_interface cbq_iface; cbq_class_spec_t cbq_class; - u_long cbq_class_handle; + u_int32_t cbq_class_handle; }; struct cbq_add_filter { - struct cbq_interface cbq_iface; - u_long cbq_class_handle; + struct cbq_interface cbq_iface; + u_int32_t cbq_class_handle; struct flow_filter cbq_filter; u_long cbq_filter_handle; @@ -134,7 +134,7 @@ struct cbq_delete_filter { }; typedef struct _cbq_class_stats_ { - u_int handle; + u_int32_t handle; u_int depth; struct pktcntr xmit_cnt; /* packets sent in this class */ diff --git a/sys/altq/altq_red.c b/sys/altq/altq_red.c index 33b6516fdb6..196989daac3 100644 --- a/sys/altq/altq_red.c +++ b/sys/altq/altq_red.c @@ -1,4 +1,4 @@ -/* $OpenBSD: altq_red.c,v 1.5 2002/06/14 21:34:58 todd Exp $ */ +/* $OpenBSD: altq_red.c,v 1.6 2002/10/11 09:30:30 kjc Exp $ */ /* $KAME: altq_red.c,v 1.10 2002/04/03 05:38:51 kjc Exp $ */ /* @@ -84,6 +84,7 @@ #include <netinet/ip6.h> #endif +#include <net/pfvar.h> #include <altq/altq.h> #include <altq/altq_conf.h> #include <altq/altq_red.h> @@ -817,29 +818,50 @@ mark_ecn(m, pktattr, flags) int flags; { struct mbuf *m0; + struct m_tag *t; + struct altq_tag *at; + void *hdr; + int af; + + if (PFALTQ_IS_ACTIVE()) { + t = m_tag_find(m, PACKET_TAG_PF_QID, NULL); + if (t == NULL) + return (0); + at = (struct altq_tag *)(t + 1); + + if (at == NULL) + return (0); + + af = at->af; + hdr = at->hdr; + } else { + if (pktattr == NULL) + return (0); + + af = pktattr->pattr_af; + hdr = pktattr->pattr_hdr; + } - if (pktattr == NULL || - (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6)) + if (af != AF_INET && af != AF_INET6) return (0); /* verify that pattr_hdr is within the mbuf data */ for (m0 = m; m0 != NULL; m0 = m0->m_next) - if ((pktattr->pattr_hdr >= m0->m_data) && - (pktattr->pattr_hdr < m0->m_data + m0->m_len)) + if (((caddr_t)hdr >= m0->m_data) && + ((caddr_t)hdr < m0->m_data + m0->m_len)) break; if (m0 == NULL) { - /* ick, pattr_hdr is stale */ - pktattr->pattr_af = AF_UNSPEC; + /* ick, tag info is stale */ return (0); } - switch (pktattr->pattr_af) { + switch (af) { case AF_INET: if (flags & REDF_ECN4) { - struct ip *ip = (struct ip *)pktattr->pattr_hdr; + struct ip *ip = hdr; u_int8_t otos; int sum; - + if (ip->ip_v != 4) return (0); /* version mismatch! */ @@ -869,7 +891,7 @@ mark_ecn(m, pktattr, flags) #ifdef INET6 case AF_INET6: if (flags & REDF_ECN6) { - struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr; + struct ip6_hdr *ip6 = hdr; u_int32_t flowlabel; flowlabel = ntohl(ip6->ip6_flow); diff --git a/sys/altq/altq_subr.c b/sys/altq/altq_subr.c index c8c26b832f0..042b4dbe343 100644 --- a/sys/altq/altq_subr.c +++ b/sys/altq/altq_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: altq_subr.c,v 1.8 2002/10/08 05:12:08 kjc Exp $ */ +/* $OpenBSD: altq_subr.c,v 1.9 2002/10/11 09:30:30 kjc Exp $ */ /* $KAME: altq_subr.c,v 1.11 2002/01/11 08:11:49 kjc Exp $ */ /* @@ -140,10 +140,15 @@ altq_attach(ifq, type, discipline, enqueue, dequeue, request, clfier, classify) { if (!ALTQ_IS_READY(ifq)) return ENXIO; - if (ALTQ_IS_ENABLED(ifq)) - return EBUSY; - if (ALTQ_IS_ATTACHED(ifq)) - return EEXIST; + + if (PFALTQ_IS_ACTIVE()) { + /* pfaltq can override the existing discipline */ + } else { + if (ALTQ_IS_ENABLED(ifq)) + return EBUSY; + if (ALTQ_IS_ATTACHED(ifq)) + return EEXIST; + } ifq->altq_type = type; ifq->altq_disc = discipline; ifq->altq_enqueue = enqueue; @@ -151,7 +156,11 @@ altq_attach(ifq, type, discipline, enqueue, dequeue, request, clfier, classify) ifq->altq_request = request; ifq->altq_clfier = clfier; ifq->altq_classify = classify; - ifq->altq_flags &= ALTQF_CANTCHANGE; + if (PFALTQ_IS_ACTIVE()) + ifq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED); + else + ifq->altq_flags &= ALTQF_CANTCHANGE; + #ifdef ALTQ_KLD altq_module_incref(type); #endif @@ -434,9 +443,7 @@ altq_pfattach(struct pf_altq *a) case ALTQT_NONE: break; case ALTQT_CBQ: -#if 0 /* notyet */ error = cbq_pfattach(a); -#endif break; default: error = EINVAL; @@ -496,9 +503,7 @@ altq_add(struct pf_altq *a) switch (a->scheduler) { case ALTQT_CBQ: -#if 0 /* notyet */ error = cbq_add_altq(a); -#endif break; default: error = EINVAL; @@ -520,9 +525,7 @@ altq_remove(struct pf_altq *a) switch (a->scheduler) { case ALTQT_CBQ: -#if 0 /* notyet */ error = cbq_remove_altq(a); -#endif break; default: error = EINVAL; @@ -541,9 +544,7 @@ altq_add_queue(struct pf_altq *a) switch (a->scheduler) { case ALTQT_CBQ: -#if 0 /* notyet */ error = cbq_add_queue(a); -#endif break; default: error = EINVAL; @@ -562,9 +563,7 @@ altq_remove_queue(struct pf_altq *a) switch (a->scheduler) { case ALTQT_CBQ: -#if 0 /* notyet */ error = cbq_remove_queue(a); -#endif break; default: error = EINVAL; @@ -583,9 +582,7 @@ altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes) switch (a->scheduler) { case ALTQT_CBQ: -#if 0 /* notyet */ error = cbq_getqstats(a, ubuf, nbytes); -#endif break; default: error = EINVAL; @@ -1065,6 +1062,10 @@ acc_discard_filters(classifier, class, all) struct acc_filter *afp; int i, s; +#if 1 /* PFALTQ */ + if (classifier == NULL) + return (0); +#endif s = splimp(); for (i = 0; i < ACC_FILTER_TABLESIZE; i++) { do { @@ -1529,6 +1530,7 @@ ip4f_free(fp) TAILQ_INSERT_TAIL(&ip4f_list, fp, ip4f_chain); } + /* * read and write diffserv field in IPv4 or IPv6 header */ diff --git a/sys/altq/altq_var.h b/sys/altq/altq_var.h index c462df60e60..f5e6a42b0fc 100644 --- a/sys/altq/altq_var.h +++ b/sys/altq/altq_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: altq_var.h,v 1.6 2002/10/08 05:12:08 kjc Exp $ */ +/* $OpenBSD: altq_var.h,v 1.7 2002/10/11 09:30:30 kjc Exp $ */ /* $KAME: altq_var.h,v 1.8 2001/02/09 09:44:41 kjc Exp $ */ /* @@ -232,6 +232,9 @@ typedef void (timeout_t)(void *); #define m_pktlen(m) ((m)->m_pkthdr.len) +/* define a macro to check pf/altq until the transition is complete */ +#define PFALTQ_IS_ACTIVE() (!TAILQ_EMPTY(pf_altqs_active)) + struct ifnet; struct mbuf; struct flowinfo; struct pf_altq; struct pf_qstats; @@ -255,5 +258,12 @@ int altq_add_queue(struct pf_altq *); int altq_remove_queue(struct pf_altq *); int altq_getqstats(struct pf_altq *, void *, int *); +int cbq_pfattach(struct pf_altq *); +int cbq_add_altq(struct pf_altq *); +int cbq_remove_altq(struct pf_altq *); +int cbq_add_queue(struct pf_altq *); +int cbq_remove_queue(struct pf_altq *); +int cbq_getqstats(struct pf_altq *, void *, int *); + #endif /* _KERNEL */ #endif /* _ALTQ_ALTQ_VAR_H_ */ |