Mon Jan 6 20:31:35 2020 UTC ()
Add missing packet filter hooks, byte accounting.


(christos)
diff -r1.114 -r1.115 src/sys/net/if_tap.c

cvs diff -r1.114 -r1.115 src/sys/net/if_tap.c (expand / switch to unified diff)

--- src/sys/net/if_tap.c 2019/10/16 06:53:34 1.114
+++ src/sys/net/if_tap.c 2020/01/06 20:31:35 1.115
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: if_tap.c,v 1.114 2019/10/16 06:53:34 knakahara Exp $ */ 1/* $NetBSD: if_tap.c,v 1.115 2020/01/06 20:31:35 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003, 2004, 2008, 2009 The NetBSD Foundation. 4 * Copyright (c) 2003, 2004, 2008, 2009 The NetBSD Foundation.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -23,27 +23,27 @@ @@ -23,27 +23,27 @@
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29/* 29/*
30 * tap(4) is a virtual Ethernet interface. It appears as a real Ethernet 30 * tap(4) is a virtual Ethernet interface. It appears as a real Ethernet
31 * device to the system, but can also be accessed by userland through a 31 * device to the system, but can also be accessed by userland through a
32 * character device interface, which allows reading and injecting frames. 32 * character device interface, which allows reading and injecting frames.
33 */ 33 */
34 34
35#include <sys/cdefs.h> 35#include <sys/cdefs.h>
36__KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.114 2019/10/16 06:53:34 knakahara Exp $"); 36__KERNEL_RCSID(0, "$NetBSD: if_tap.c,v 1.115 2020/01/06 20:31:35 christos Exp $");
37 37
38#if defined(_KERNEL_OPT) 38#if defined(_KERNEL_OPT)
39 39
40#include "opt_modular.h" 40#include "opt_modular.h"
41#endif 41#endif
42 42
43#include <sys/param.h> 43#include <sys/param.h>
44#include <sys/atomic.h> 44#include <sys/atomic.h>
45#include <sys/conf.h> 45#include <sys/conf.h>
46#include <sys/cprng.h> 46#include <sys/cprng.h>
47#include <sys/device.h> 47#include <sys/device.h>
48#include <sys/file.h> 48#include <sys/file.h>
49#include <sys/filedesc.h> 49#include <sys/filedesc.h>
@@ -515,26 +515,27 @@ tap_start(struct ifnet *ifp) @@ -515,26 +515,27 @@ tap_start(struct ifnet *ifp)
515{ 515{
516 struct tap_softc *sc = (struct tap_softc *)ifp->if_softc; 516 struct tap_softc *sc = (struct tap_softc *)ifp->if_softc;
517 struct mbuf *m0; 517 struct mbuf *m0;
518 518
519 mutex_enter(&sc->sc_lock); 519 mutex_enter(&sc->sc_lock);
520 if ((sc->sc_flags & TAP_INUSE) == 0) { 520 if ((sc->sc_flags & TAP_INUSE) == 0) {
521 /* Simply drop packets */ 521 /* Simply drop packets */
522 for (;;) { 522 for (;;) {
523 IFQ_DEQUEUE(&ifp->if_snd, m0); 523 IFQ_DEQUEUE(&ifp->if_snd, m0);
524 if (m0 == NULL) 524 if (m0 == NULL)
525 goto done; 525 goto done;
526 526
527 ifp->if_opackets++; 527 ifp->if_opackets++;
 528 ifp->if_obytes += m0->m_len;
528 bpf_mtap(ifp, m0, BPF_D_OUT); 529 bpf_mtap(ifp, m0, BPF_D_OUT);
529 530
530 m_freem(m0); 531 m_freem(m0);
531 } 532 }
532 } else if (!IFQ_IS_EMPTY(&ifp->if_snd)) { 533 } else if (!IFQ_IS_EMPTY(&ifp->if_snd)) {
533 ifp->if_flags |= IFF_OACTIVE; 534 ifp->if_flags |= IFF_OACTIVE;
534 cv_broadcast(&sc->sc_cv); 535 cv_broadcast(&sc->sc_cv);
535 selnotify(&sc->sc_rsel, 0, 1); 536 selnotify(&sc->sc_rsel, 0, 1);
536 if (sc->sc_flags & TAP_ASYNCIO) { 537 if (sc->sc_flags & TAP_ASYNCIO) {
537 kpreempt_disable(); 538 kpreempt_disable();
538 softint_schedule(sc->sc_sih); 539 softint_schedule(sc->sc_sih);
539 kpreempt_enable(); 540 kpreempt_enable();
540 } 541 }
@@ -883,26 +884,27 @@ tap_dev_close(struct tap_softc *sc) @@ -883,26 +884,27 @@ tap_dev_close(struct tap_softc *sc)
883 ifp = &sc->sc_ec.ec_if; 884 ifp = &sc->sc_ec.ec_if;
884 ifp->if_flags &= ~IFF_OACTIVE; 885 ifp->if_flags &= ~IFF_OACTIVE;
885 886
886 /* Purge output queue */ 887 /* Purge output queue */
887 if (!(IFQ_IS_EMPTY(&ifp->if_snd))) { 888 if (!(IFQ_IS_EMPTY(&ifp->if_snd))) {
888 struct mbuf *m; 889 struct mbuf *m;
889 890
890 for (;;) { 891 for (;;) {
891 IFQ_DEQUEUE(&ifp->if_snd, m); 892 IFQ_DEQUEUE(&ifp->if_snd, m);
892 if (m == NULL) 893 if (m == NULL)
893 break; 894 break;
894 895
895 ifp->if_opackets++; 896 ifp->if_opackets++;
 897 ifp->if_obytes += m->m_len;
896 bpf_mtap(ifp, m, BPF_D_OUT); 898 bpf_mtap(ifp, m, BPF_D_OUT);
897 m_freem(m); 899 m_freem(m);
898 } 900 }
899 } 901 }
900 splx(s); 902 splx(s);
901 903
902 if (sc->sc_sih != NULL) { 904 if (sc->sc_sih != NULL) {
903 softint_disestablish(sc->sc_sih); 905 softint_disestablish(sc->sc_sih);
904 sc->sc_sih = NULL; 906 sc->sc_sih = NULL;
905 } 907 }
906 sc->sc_flags &= ~(TAP_INUSE | TAP_ASYNCIO); 908 sc->sc_flags &= ~(TAP_INUSE | TAP_ASYNCIO);
907 909
908 return 0; 910 return 0;
@@ -969,27 +971,32 @@ tap_dev_read(int unit, struct uio *uio,  @@ -969,27 +971,32 @@ tap_dev_read(int unit, struct uio *uio,
969 } 971 }
970 } 972 }
971 973
972 IFQ_DEQUEUE(&ifp->if_snd, m); 974 IFQ_DEQUEUE(&ifp->if_snd, m);
973 mutex_exit(&sc->sc_lock); 975 mutex_exit(&sc->sc_lock);
974 976
975 ifp->if_flags &= ~IFF_OACTIVE; 977 ifp->if_flags &= ~IFF_OACTIVE;
976 if (m == NULL) { 978 if (m == NULL) {
977 error = 0; 979 error = 0;
978 goto out; 980 goto out;
979 } 981 }
980 982
981 ifp->if_opackets++; 983 ifp->if_opackets++;
 984 ifp->if_obytes += m->m_len; // XXX: only first in chain
982 bpf_mtap(ifp, m, BPF_D_OUT); 985 bpf_mtap(ifp, m, BPF_D_OUT);
 986 if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_OUT)) != 0)
 987 goto out;
 988 if (m == NULL)
 989 goto out;
983 990
984 /* 991 /*
985 * One read is one packet. 992 * One read is one packet.
986 */ 993 */
987 do { 994 do {
988 error = uiomove(mtod(m, void *), 995 error = uiomove(mtod(m, void *),
989 uimin(m->m_len, uio->uio_resid), uio); 996 uimin(m->m_len, uio->uio_resid), uio);
990 m = n = m_free(m); 997 m = n = m_free(m);
991 } while (m != NULL && uio->uio_resid > 0 && error == 0); 998 } while (m != NULL && uio->uio_resid > 0 && error == 0);
992 999
993 if (m != NULL) 1000 if (m != NULL)
994 m_freem(m); 1001 m_freem(m);
995 1002
@@ -1040,63 +1047,73 @@ tap_fops_write(file_t *fp, off_t *offp,  @@ -1040,63 +1047,73 @@ tap_fops_write(file_t *fp, off_t *offp,
1040 KERNEL_LOCK(1, NULL); 1047 KERNEL_LOCK(1, NULL);
1041 error = tap_dev_write(fp->f_devunit, uio, flags); 1048 error = tap_dev_write(fp->f_devunit, uio, flags);
1042 KERNEL_UNLOCK_ONE(NULL); 1049 KERNEL_UNLOCK_ONE(NULL);
1043 return error; 1050 return error;
1044} 1051}
1045 1052
1046static int 1053static int
1047tap_dev_write(int unit, struct uio *uio, int flags) 1054tap_dev_write(int unit, struct uio *uio, int flags)
1048{ 1055{
1049 struct tap_softc *sc = 1056 struct tap_softc *sc =
1050 device_lookup_private(&tap_cd, unit); 1057 device_lookup_private(&tap_cd, unit);
1051 struct ifnet *ifp; 1058 struct ifnet *ifp;
1052 struct mbuf *m, **mp; 1059 struct mbuf *m, **mp;
 1060 size_t len = 0;
1053 int error = 0; 1061 int error = 0;
1054 1062
1055 if (sc == NULL) 1063 if (sc == NULL)
1056 return ENXIO; 1064 return ENXIO;
1057 1065
1058 getnanotime(&sc->sc_mtime); 1066 getnanotime(&sc->sc_mtime);
1059 ifp = &sc->sc_ec.ec_if; 1067 ifp = &sc->sc_ec.ec_if;
1060 1068
1061 /* One write, one packet, that's the rule */ 1069 /* One write, one packet, that's the rule */
1062 MGETHDR(m, M_DONTWAIT, MT_DATA); 1070 MGETHDR(m, M_DONTWAIT, MT_DATA);
1063 if (m == NULL) { 1071 if (m == NULL) {
1064 ifp->if_ierrors++; 1072 ifp->if_ierrors++;
1065 return ENOBUFS; 1073 return ENOBUFS;
1066 } 1074 }
1067 m->m_pkthdr.len = uio->uio_resid; 1075 m->m_pkthdr.len = uio->uio_resid;
1068 1076
1069 mp = &m; 1077 mp = &m;
1070 while (error == 0 && uio->uio_resid > 0) { 1078 while (error == 0 && uio->uio_resid > 0) {
1071 if (*mp != m) { 1079 if (*mp != m) {
1072 MGET(*mp, M_DONTWAIT, MT_DATA); 1080 MGET(*mp, M_DONTWAIT, MT_DATA);
1073 if (*mp == NULL) { 1081 if (*mp == NULL) {
1074 error = ENOBUFS; 1082 error = ENOBUFS;
1075 break; 1083 break;
1076 } 1084 }
1077 } 1085 }
1078 (*mp)->m_len = uimin(MHLEN, uio->uio_resid); 1086 (*mp)->m_len = uimin(MHLEN, uio->uio_resid);
 1087 len += (*mp)->m_len;
1079 error = uiomove(mtod(*mp, void *), (*mp)->m_len, uio); 1088 error = uiomove(mtod(*mp, void *), (*mp)->m_len, uio);
1080 mp = &(*mp)->m_next; 1089 mp = &(*mp)->m_next;
1081 } 1090 }
1082 if (error) { 1091 if (error) {
1083 ifp->if_ierrors++; 1092 ifp->if_ierrors++;
1084 m_freem(m); 1093 m_freem(m);
1085 return error; 1094 return error;
1086 } 1095 }
1087 1096
1088 m_set_rcvif(m, ifp); 1097 m_set_rcvif(m, ifp);
1089 1098
 1099 ifp->if_ipackets++;
 1100 ifp->if_ibytes += len;
 1101 bpf_mtap(ifp, m, BPF_D_IN);
 1102 if ((error = pfil_run_hooks(ifp->if_pfil, &m, ifp, PFIL_IN)) != 0)
 1103 return error;
 1104 if (m == NULL)
 1105 return 0;
 1106
1090 if_percpuq_enqueue(ifp->if_percpuq, m); 1107 if_percpuq_enqueue(ifp->if_percpuq, m);
1091 1108
1092 return 0; 1109 return 0;
1093} 1110}
1094 1111
1095static int 1112static int
1096tap_cdev_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 1113tap_cdev_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
1097{ 1114{
1098 1115
1099 return tap_dev_ioctl(minor(dev), cmd, data, l); 1116 return tap_dev_ioctl(minor(dev), cmd, data, l);
1100} 1117}
1101 1118
1102static int 1119static int