diff --git a/src/contrib/pf/pfctl/pfctl_altq.c b/src/contrib/pf/pfctl/pfctl_altq.c index 64e00be..bceb082 100644 --- a/src/contrib/pf/pfctl/pfctl_altq.c +++ b/src/contrib/pf/pfctl/pfctl_altq.c @@ -169,6 +169,10 @@ print_altq(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw, return; } +#ifdef __FreeBSD__ + if (a->local_flags & PFALTQ_FLAG_IF_REMOVED) + printf("INACTIVE "); +#endif printf("altq on %s ", a->ifname); switch (a->scheduler) { @@ -203,6 +207,10 @@ print_queue(const struct pf_altq *a, unsigned level, struct node_queue_bw *bw, { unsigned i; +#ifdef __FreeBSD__ + if (a->local_flags & PFALTQ_FLAG_IF_REMOVED) + printf("INACTIVE "); +#endif printf("queue "); for (i = 0; i < level; ++i) printf(" "); @@ -1164,7 +1172,11 @@ getifmtu(char *ifname) sizeof(ifr.ifr_name)) errx(1, "getifmtu: strlcpy"); if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) == -1) +#ifdef __FreeBSD__ + ifr.ifr_mtu = 1500; +#else err(1, "SIOCGIFMTU"); +#endif if (shutdown(s, SHUT_RDWR) == -1) err(1, "shutdown"); if (close(s)) diff --git a/src/contrib/pf/pfctl/pfctl_qstats.c b/src/contrib/pf/pfctl/pfctl_qstats.c index 3eb2987..e29f8e9 100644 --- a/src/contrib/pf/pfctl/pfctl_qstats.c +++ b/src/contrib/pf/pfctl/pfctl_qstats.c @@ -118,6 +118,10 @@ pfctl_show_altq(int dev, const char *iface, int opts, int verbose2) for (node = root; node != NULL; node = node->next) { if (iface != NULL && strcmp(node->altq.ifname, iface)) continue; +#ifdef __FreeBSD__ + if (node->altq.local_flags & PFALTQ_FLAG_IF_REMOVED) + continue; +#endif pfctl_print_altq_node(dev, node, 0, opts); } } @@ -157,7 +161,12 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root) warn("DIOCGETALTQ"); return (-1); } +#ifdef __FreeBSD__ + if (pa.altq.qid > 0 && + !(pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED)) { +#else if (pa.altq.qid > 0) { +#endif pq.nr = nr; pq.ticket = pa.ticket; pq.buf = &qstats.data; @@ -175,6 +184,19 @@ pfctl_update_qstats(int dev, struct pf_altq_node **root) pfctl_insert_altq_node(root, pa.altq, qstats); } } +#ifdef __FreeBSD__ + else if (pa.altq.local_flags & PFALTQ_FLAG_IF_REMOVED) { + memset(&qstats.data, 0, sizeof(qstats.data)); + if ((node = pfctl_find_altq_node(*root, pa.altq.qname, + pa.altq.ifname)) != NULL) { + memcpy(&node->qstats.data, &qstats.data, + sizeof(qstats.data)); + update_avg(node); + } else { + pfctl_insert_altq_node(root, pa.altq, qstats); + } + } +#endif } return (mnr); } @@ -280,6 +302,10 @@ pfctl_print_altq_nodestat(int dev, const struct pf_altq_node *a) { if (a->altq.qid == 0) return; +#ifdef __FreeBSD__ + if (a->altq.local_flags & PFALTQ_FLAG_IF_REMOVED) + return; +#endif switch (a->altq.scheduler) { case ALTQT_CBQ: diff --git a/src/sys/amd64/conf/ALTQ b/src/sys/amd64/conf/ALTQ new file mode 100644 index 0000000..2b5a119 --- /dev/null +++ b/src/sys/amd64/conf/ALTQ @@ -0,0 +1,14 @@ +include GENERIC +ident ALTQ + +options ALTQ +options ALTQ_CBQ # Class Based Queueing +options ALTQ_RED # Random Early Detection +options ALTQ_RIO # RED In/Out +options ALTQ_HFSC # Hierarchical Packet Scheduler +options ALTQ_CDNR # Traffic conditioner +options ALTQ_PRIQ # Priority Queueing +options ALTQ_NOPCC # Required if the TSC is unusable + +device pf +device pflog diff --git a/src/sys/contrib/pf/net/pf_if.c b/src/sys/contrib/pf/net/pf_if.c index 6e624e4..f56784d 100644 --- a/src/sys/contrib/pf/net/pf_if.c +++ b/src/sys/contrib/pf/net/pf_if.c @@ -240,6 +240,9 @@ pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp) { PF_LOCK(); pfi_attach_ifnet(ifp); +#ifdef ALTQ + pf_altq_ifnet_event(ifp, 0); +#endif PF_UNLOCK(); } @@ -248,6 +251,9 @@ pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp) { PF_LOCK(); pfi_detach_ifnet(ifp); +#ifdef ALTQ + pf_altq_ifnet_event(ifp, 1); +#endif PF_UNLOCK(); } #endif /* __FreeBSD__ */ diff --git a/src/sys/contrib/pf/net/pf_ioctl.c b/src/sys/contrib/pf/net/pf_ioctl.c index ed45e5a..d3af899 100644 --- a/src/sys/contrib/pf/net/pf_ioctl.c +++ b/src/sys/contrib/pf/net/pf_ioctl.c @@ -1043,7 +1043,12 @@ pf_begin_altq(u_int32_t *ticket) /* Purge the old altq list */ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) { TAILQ_REMOVE(pf_altqs_inactive, altq, entries); +#ifdef __FreeBSD__ + if (altq->qname[0] == 0 && + (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) { +#else if (altq->qname[0] == 0) { +#endif /* detach and destroy the discipline */ error = altq_remove(altq); } else @@ -1068,7 +1073,12 @@ pf_rollback_altq(u_int32_t ticket) /* Purge the old altq list */ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) { TAILQ_REMOVE(pf_altqs_inactive, altq, entries); +#ifdef __FreeBSD__ + if (altq->qname[0] == 0 && + (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) { +#else if (altq->qname[0] == 0) { +#endif /* detach and destroy the discipline */ error = altq_remove(altq); } else @@ -1098,7 +1108,12 @@ pf_commit_altq(u_int32_t ticket) /* Attach new disciplines */ TAILQ_FOREACH(altq, pf_altqs_active, entries) { +#ifdef __FreeBSD__ + if (altq->qname[0] == 0 && + (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) { +#else if (altq->qname[0] == 0) { +#endif /* attach the discipline */ error = altq_pfattach(altq); if (error == 0 && pf_altq_running) @@ -1113,7 +1128,12 @@ pf_commit_altq(u_int32_t ticket) /* Purge the old altq list */ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) { TAILQ_REMOVE(pf_altqs_inactive, altq, entries); +#ifdef __FreeBSD__ + if (altq->qname[0] == 0 && + (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) { +#else if (altq->qname[0] == 0) { +#endif /* detach and destroy the discipline */ if (pf_altq_running) error = pf_disable_altq(altq); @@ -1199,6 +1219,76 @@ pf_disable_altq(struct pf_altq *altq) return (error); } + +#ifdef __FreeBSD__ +void +pf_altq_ifnet_event(struct ifnet *ifp, int remove) +{ + struct ifnet *ifp1; + struct pf_altq *a1, *a2, *a3; + u_int32_t ticket; + int error = 0; + + /* Interrupt userland queue modifications */ + if (altqs_inactive_open) + pf_rollback_altq(ticket_altqs_inactive); + + /* Start new altq ruleset */ + if (pf_begin_altq(&ticket)) + return; + + /* Copy the current active set */ + TAILQ_FOREACH(a1, pf_altqs_active, entries) { + a2 = pool_get(&pf_altq_pl, PR_NOWAIT); + if (a2 == NULL) { + error = ENOMEM; + break; + } + bcopy(a1, a2, sizeof(struct pf_altq)); + + if (a2->qname[0] != 0) { + if ((a2->qid = pf_qname2qid(a2->qname)) == 0) { + error = EBUSY; + pool_put(&pf_altq_pl, a2); + break; + } + a2->altq_disc = NULL; + TAILQ_FOREACH(a3, pf_altqs_inactive, entries) { + if (strncmp(a3->ifname, a2->ifname, + IFNAMSIZ) == 0 && a3->qname[0] == 0) { + a2->altq_disc = a3->altq_disc; + break; + } + } + } + /* Deactivate the interface in question */ + a2->local_flags &= ~PFALTQ_FLAG_IF_REMOVED; + if ((ifp1 = ifunit(a2->ifname)) == NULL || + (remove && ifp1 == ifp)) { + a2->local_flags |= PFALTQ_FLAG_IF_REMOVED; + } else { + PF_UNLOCK(); + error = altq_add(a2); + PF_LOCK(); + + if (ticket != ticket_altqs_inactive) + error = EBUSY; + + if (error) { + pool_put(&pf_altq_pl, a2); + break; + } + } + + TAILQ_INSERT_TAIL(pf_altqs_inactive, a2, entries); + } + + if (error != 0) + pf_rollback_altq(ticket); + else + pf_commit_altq(ticket); +} +#endif #endif /* ALTQ */ int @@ -2234,7 +2324,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p) /* enable all altq interfaces on active list */ TAILQ_FOREACH(altq, pf_altqs_active, entries) { +#ifdef __FreeBSD__ + if (altq->qname[0] == 0 && (altq->local_flags & + PFALTQ_FLAG_IF_REMOVED) == 0) { +#else if (altq->qname[0] == 0) { +#endif error = pf_enable_altq(altq); if (error != 0) break; @@ -2251,7 +2346,12 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p) /* disable all altq interfaces on active list */ TAILQ_FOREACH(altq, pf_altqs_active, entries) { +#ifdef __FreeBSD__ + if (altq->qname[0] == 0 && (altq->local_flags & + PFALTQ_FLAG_IF_REMOVED) == 0) { +#else if (altq->qname[0] == 0) { +#endif error = pf_disable_altq(altq); if (error != 0) break; @@ -2277,6 +2377,9 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } bcopy(&pa->altq, altq, sizeof(struct pf_altq)); +#ifdef __FreeBSD__ + altq->local_flags = 0; +#endif /* * if this is for a queue, find the discipline and @@ -2288,6 +2391,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p) pool_put(&pf_altq_pl, altq); break; } + altq->altq_disc = NULL; TAILQ_FOREACH(a, pf_altqs_inactive, entries) { if (strncmp(a->ifname, altq->ifname, IFNAMSIZ) == 0 && a->qname[0] == 0) { @@ -2298,11 +2402,17 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p) } #ifdef __FreeBSD__ - PF_UNLOCK(); + struct ifnet *ifp; + + if ((ifp = ifunit(altq->ifname)) == NULL) { + altq->local_flags |= PFALTQ_FLAG_IF_REMOVED; + } else { + PF_UNLOCK(); #endif error = altq_add(altq); #ifdef __FreeBSD__ - PF_LOCK(); + PF_LOCK(); + } #endif if (error) { pool_put(&pf_altq_pl, altq); @@ -2375,6 +2485,10 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct proc *p) break; } #ifdef __FreeBSD__ + if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) { + error = ENXIO; + break; + } PF_UNLOCK(); #endif error = altq_getqstats(altq, pq->buf, &nbytes); diff --git a/src/sys/contrib/pf/net/pfvar.h b/src/sys/contrib/pf/net/pfvar.h index 7317566..5d92b5d 100644 --- a/src/sys/contrib/pf/net/pfvar.h +++ b/src/sys/contrib/pf/net/pfvar.h @@ -1212,6 +1212,10 @@ struct pf_altq { u_int32_t parent_qid; /* parent queue id */ u_int32_t bandwidth; /* queue bandwidth */ u_int8_t priority; /* priority */ +#ifdef __FreeBSD__ + u_int8_t local_flags; /* dynamic interface */ +#define PFALTQ_FLAG_IF_REMOVED 0x01 +#endif u_int16_t qlimit; /* queue size limit */ u_int16_t flags; /* misc flags */ union { @@ -1519,6 +1523,9 @@ extern void pf_tbladdr_remove(struct pf_addr_wrap *); extern void pf_tbladdr_copyout(struct pf_addr_wrap *); extern void pf_calc_skip_steps(struct pf_rulequeue *); #ifdef __FreeBSD__ +#ifdef ALTQ +extern void pf_altq_ifnet_event(struct ifnet *, int); +#endif extern uma_zone_t pf_src_tree_pl, pf_rule_pl; extern uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl; extern uma_zone_t pfr_ktable_pl, pfr_kentry_pl, pfr_kentry_pl2;