| @@ -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 | |
1046 | static int | | 1053 | static int |
1047 | tap_dev_write(int unit, struct uio *uio, int flags) | | 1054 | tap_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 | |
1095 | static int | | 1112 | static int |
1096 | tap_cdev_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) | | 1113 | tap_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 | |
1102 | static int | | 1119 | static int |