Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys Avoid storing a pointer of an interface in a mbuf



details:   https://anonhg.NetBSD.org/src/rev/cf659ba12485
branches:  trunk
changeset: 815981:cf659ba12485
user:      ozaki-r <ozaki-r%NetBSD.org@localhost>
date:      Fri Jun 10 13:31:43 2016 +0000

description:
Avoid storing a pointer of an interface in a mbuf

Having a pointer of an interface in a mbuf isn't safe if we remove big
kernel locks; an interface object (ifnet) can be destroyed anytime in any
packet processing and accessing such object via a pointer is racy. Instead
we have to get an object from the interface collection (ifindex2ifnet) via
an interface index (if_index) that is stored to a mbuf instead of an
pointer.

The change provides two APIs: m_{get,put}_rcvif_psref that use psref(9)
for sleep-able critical sections and m_{get,put}_rcvif that use
pserialize(9) for other critical sections. The change also adds another
API called m_get_rcvif_NOMPSAFE, that is NOT MP-safe and for transition
moratorium, i.e., it is intended to be used for places where are not
planned to be MP-ified soon.

The change adds some overhead due to psref to performance sensitive paths,
however the overhead is not serious, 2% down at worst.

Proposed on tech-kern and tech-net.

diffstat:

 sys/altq/altq_cdnr.c                     |   6 +-
 sys/dev/pci/if_lmc.c                     |   6 +-
 sys/dist/pf/net/if_pfsync.c              |   6 +-
 sys/external/bsd/ipf/netinet/ip_compat.h |   5 +-
 sys/kern/uipc_mbuf.c                     |   8 +-
 sys/net/bpf.c                            |  12 ++--
 sys/net/if.c                             |  26 ++++++++-
 sys/net/if.h                             |  16 +++--
 sys/net/if_bridge.c                      |  29 ++++++---
 sys/net/if_mpls.c                        |   8 +-
 sys/net/if_pppoe.c                       |  34 ++++++++---
 sys/net/if_stf.c                         |   8 +-
 sys/netatalk/ddp_input.c                 |   8 +-
 sys/netinet/if_arp.c                     |  51 ++++++++++++------
 sys/netinet/igmp.c                       |  26 +++++---
 sys/netinet/in_gif.c                     |  13 +++-
 sys/netinet/ip_carp.c                    |  34 ++++++-----
 sys/netinet/ip_flow.c                    |  19 ++++--
 sys/netinet/ip_icmp.c                    |  36 ++++++++----
 sys/netinet/ip_input.c                   |  67 ++++++++++++++++-------
 sys/netinet/sctp_input.c                 |  10 +-
 sys/netinet/sctp_output.c                |  21 +++----
 sys/netinet/tcp_input.c                  |  35 ++++++++---
 sys/netinet/udp_usrreq.c                 |  10 +-
 sys/netinet6/icmp6.c                     |  66 +++++++++++++++++++----
 sys/netinet6/in6_gif.c                   |  12 ++-
 sys/netinet6/ip6_forward.c               |  58 ++++++++++----------
 sys/netinet6/ip6_input.c                 |  23 +++++---
 sys/netinet6/ip6_mroute.c                |  12 ++--
 sys/netinet6/ip6_var.h                   |   4 +-
 sys/netinet6/mld6.c                      |  19 +++--
 sys/netinet6/nd6_nbr.c                   |  28 ++++++++-
 sys/netinet6/nd6_rtr.c                   |  32 ++++++++--
 sys/netinet6/raw_ip6.c                   |  43 +++++++++-----
 sys/netinet6/sctp6_usrreq.c              |   8 +-
 sys/netinet6/udp6_output.c               |   7 +-
 sys/netinet6/udp6_usrreq.c               |   6 +-
 sys/netipsec/ipsec_input.c               |   7 +-
 sys/netipsec/key_debug.c                 |   6 +-
 sys/netipsec/xform_ipip.c                |   8 +-
 sys/netmpls/mpls_ttl.c                   |   6 +-
 sys/netnatm/natm.c                       |   6 +-
 sys/sys/mbuf.h                           |  89 ++++++++++++++++++++++++++++---
 43 files changed, 619 insertions(+), 315 deletions(-)

diffs (truncated from 3189 to 300 lines):

diff -r c2c8ef121618 -r cf659ba12485 sys/altq/altq_cdnr.c
--- a/sys/altq/altq_cdnr.c      Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/altq/altq_cdnr.c      Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: altq_cdnr.c,v 1.20 2011/11/19 22:51:18 tls Exp $       */
+/*     $NetBSD: altq_cdnr.c,v 1.21 2016/06/10 13:31:43 ozaki-r Exp $   */
 /*     $KAME: altq_cdnr.c,v 1.15 2005/04/13 03:44:24 suz Exp $ */
 
 /*
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: altq_cdnr.c,v 1.20 2011/11/19 22:51:18 tls Exp $");
+__KERNEL_RCSID(0, "$NetBSD: altq_cdnr.c,v 1.21 2016/06/10 13:31:43 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_altq.h"
@@ -139,7 +139,7 @@
        struct cdnr_block       *cb;
        struct cdnr_pktinfo     pktinfo;
 
-       ifp = m->m_pkthdr.rcvif;
+       ifp = m_get_rcvif_NOMPSAFE(m);
        if (!ALTQ_IS_CNDTNING(&ifp->if_snd))
                /* traffic conditioner is not enabled on this interface */
                return (1);
diff -r c2c8ef121618 -r cf659ba12485 sys/dev/pci/if_lmc.c
--- a/sys/dev/pci/if_lmc.c      Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/dev/pci/if_lmc.c      Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_lmc.c,v 1.60 2016/06/10 13:27:14 ozaki-r Exp $ */
+/* $NetBSD: if_lmc.c,v 1.61 2016/06/10 13:31:43 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 2002-2006 David Boggs. <boggs%boggs.palo-alto.ca.us@localhost>
@@ -74,7 +74,7 @@
  */
 
 # include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_lmc.c,v 1.60 2016/06/10 13:27:14 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_lmc.c,v 1.61 2016/06/10 13:31:43 ozaki-r Exp $");
 # include <sys/param.h>        /* OS version */
 # include "opt_inet.h" /* INET6, INET */
 # include "opt_altq_enabled.h" /* ALTQ */
@@ -4279,7 +4279,7 @@
       MGETHDR(new_mbuf, M_DONTWAIT, MT_DATA);
       if (new_mbuf)
         {
-        m_set_rcvif(new_mbuf, first_mbuf->m_pkthdr.rcvif);
+        m_copy_rcvif(new_mbuf, first_mbuf);
         new_mbuf->m_pkthdr.len   = first_mbuf->m_pkthdr.len;
         new_mbuf->m_len          = first_mbuf->m_len;
         memcpy(new_mbuf->m_data,   first_mbuf->m_data,
diff -r c2c8ef121618 -r cf659ba12485 sys/dist/pf/net/if_pfsync.c
--- a/sys/dist/pf/net/if_pfsync.c       Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/dist/pf/net/if_pfsync.c       Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_pfsync.c,v 1.13 2016/06/10 13:27:15 ozaki-r Exp $   */
+/*     $NetBSD: if_pfsync.c,v 1.14 2016/06/10 13:31:44 ozaki-r Exp $   */
 /*     $OpenBSD: if_pfsync.c,v 1.83 2007/06/26 14:44:12 mcbride Exp $  */
 
 /*
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_pfsync.c,v 1.13 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_pfsync.c,v 1.14 2016/06/10 13:31:44 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_inet.h"
@@ -374,7 +374,7 @@
                goto done;
 
        /* verify that the packet came in on the right interface */
-       if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
+       if (sc->sc_sync_ifp->if_index != m->m_pkthdr.rcvif_index) {
                PFSYNC_STATINC(PFSYNC_STAT_BADIF);
                goto done;
        }
diff -r c2c8ef121618 -r cf659ba12485 sys/external/bsd/ipf/netinet/ip_compat.h
--- a/sys/external/bsd/ipf/netinet/ip_compat.h  Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/external/bsd/ipf/netinet/ip_compat.h  Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ip_compat.h,v 1.9 2016/06/10 13:27:15 ozaki-r Exp $    */
+/*     $NetBSD: ip_compat.h,v 1.10 2016/06/10 13:31:44 ozaki-r Exp $   */
 
 /*
  * Copyright (C) 2012 by Darren Reed.
@@ -1964,8 +1964,7 @@
                                                if (_o->m_flags & M_PKTHDR) { \
                                                        (m)->m_pkthdr.len += \
                                                            _o->m_pkthdr.len; \
-                                                       m_set_rcvif((m), \
-                                                           _o->m_pkthdr.rcvif); \
+                                                       m_copy_rcvif((m), _o); \
                                                } \
                                        } while (0)
 # endif
diff -r c2c8ef121618 -r cf659ba12485 sys/kern/uipc_mbuf.c
--- a/sys/kern/uipc_mbuf.c      Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/kern/uipc_mbuf.c      Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: uipc_mbuf.c,v 1.166 2016/06/10 13:27:15 ozaki-r Exp $  */
+/*     $NetBSD: uipc_mbuf.c,v 1.167 2016/06/10 13:31:44 ozaki-r Exp $  */
 
 /*-
  * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.166 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uipc_mbuf.c,v 1.167 2016/06/10 13:31:44 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_mbuftrace.h"
@@ -1171,7 +1171,7 @@
                if (n == NULL)
                        return NULL;
                MCLAIM(n, m0->m_owner);
-               m_set_rcvif(n, m0->m_pkthdr.rcvif);
+               m_copy_rcvif(n, m0);
                n->m_pkthdr.len = m0->m_pkthdr.len - len0;
                len_save = m0->m_pkthdr.len;
                m0->m_pkthdr.len = len0;
@@ -1783,7 +1783,7 @@
                snprintb(buf, sizeof(buf), M_CSUM_BITS, m->m_pkthdr.csum_flags);
                (*pr)("  pktlen=%d, rcvif=%p, csum_flags=0x%s, csum_data=0x%"
                    PRIx32 ", segsz=%u\n",
-                   m->m_pkthdr.len, m->m_pkthdr.rcvif,
+                   m->m_pkthdr.len, m_get_rcvif_NOMPSAFE(m),
                    buf, m->m_pkthdr.csum_data, m->m_pkthdr.segsz);
        }
        if ((m->m_flags & M_EXT)) {
diff -r c2c8ef121618 -r cf659ba12485 sys/net/bpf.c
--- a/sys/net/bpf.c     Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/net/bpf.c     Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: bpf.c,v 1.197 2016/06/10 13:27:15 ozaki-r Exp $        */
+/*     $NetBSD: bpf.c,v 1.198 2016/06/10 13:31:44 ozaki-r Exp $        */
 
 /*
  * Copyright (c) 1990, 1991, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.197 2016/06/10 13:27:15 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.198 2016/06/10 13:31:44 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_bpf.h"
@@ -1469,7 +1469,7 @@
        struct mbuf mb;
 
        /* Skip outgoing duplicate packets. */
-       if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
+       if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif_index == 0) {
                m->m_flags &= ~M_PROMISC;
                return;
        }
@@ -1486,7 +1486,7 @@
        mb.m_data = data;
        mb.m_len = dlen;
 
-       bpf_deliver(bp, bpf_mcpy, &mb, pktlen, 0, m->m_pkthdr.rcvif != NULL);
+       bpf_deliver(bp, bpf_mcpy, &mb, pktlen, 0, m->m_pkthdr.rcvif_index != 0);
 }
 
 /*
@@ -1500,7 +1500,7 @@
        void *marg;
 
        /* Skip outgoing duplicate packets. */
-       if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif == NULL) {
+       if ((m->m_flags & M_PROMISC) != 0 && m->m_pkthdr.rcvif_index == 0) {
                m->m_flags &= ~M_PROMISC;
                return;
        }
@@ -1517,7 +1517,7 @@
                buflen = 0;
        }
 
-       bpf_deliver(bp, cpfn, marg, pktlen, buflen, m->m_pkthdr.rcvif != NULL);
+       bpf_deliver(bp, cpfn, marg, pktlen, buflen, m->m_pkthdr.rcvif_index != 0);
 }
 
 /*
diff -r c2c8ef121618 -r cf659ba12485 sys/net/if.c
--- a/sys/net/if.c      Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/net/if.c      Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.337 2016/05/31 04:05:01 ozaki-r Exp $ */
+/*     $NetBSD: if.c,v 1.338 2016/06/10 13:31:44 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@@ -90,7 +90,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.337 2016/05/31 04:05:01 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.338 2016/06/10 13:31:44 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -1245,7 +1245,7 @@
                KASSERT((m->m_flags & M_PKTHDR) != 0);
 
                next = m->m_nextpkt;
-               if (m->m_pkthdr.rcvif != ifp) {
+               if (m->m_pkthdr.rcvif_index != ifp->if_index) {
                        prev = m;
                        continue;
                }
@@ -2223,6 +2223,26 @@
        return ifp;
 }
 
+/*
+ * XXX unsafe
+ */
+void
+if_acquire_unsafe(struct ifnet *ifp, struct psref *psref)
+{
+
+       KASSERT(ifp->if_index != 0);
+       KASSERT(if_byindex(ifp->if_index) != NULL);
+       psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
+}
+
+bool
+if_held(struct ifnet *ifp)
+{
+
+       return psref_held(&ifp->if_psref, ifnet_psref_class);
+}
+
+
 /* common */
 int
 ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)
diff -r c2c8ef121618 -r cf659ba12485 sys/net/if.h
--- a/sys/net/if.h      Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/net/if.h      Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.h,v 1.206 2016/05/16 01:16:24 ozaki-r Exp $ */
+/*     $NetBSD: if.h,v 1.207 2016/06/10 13:31:44 ozaki-r Exp $ */
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -890,16 +890,20 @@
 extern int (*ifioctl)(struct socket *, u_long, void *, struct lwp *);
 int    ifioctl_common(struct ifnet *, u_long, void *);
 int    ifpromisc(struct ifnet *, int);
+int    if_addr_init(ifnet_t *, struct ifaddr *, bool);
+int    if_do_dad(struct ifnet *);
+int    if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *);
+int    if_flags_set(struct ifnet *, const short);
+int    if_clone_list(int, char *, int *);
+
 struct ifnet *ifunit(const char *);
 struct ifnet *if_get(const char *, struct psref *);
 ifnet_t *if_byindex(u_int);
 ifnet_t *if_get_byindex(u_int, struct psref *);
 void   if_put(const struct ifnet *, struct psref *);
-int    if_addr_init(ifnet_t *, struct ifaddr *, bool);
-int    if_do_dad(struct ifnet *);
-int    if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *);
-int    if_flags_set(struct ifnet *, const short);
-int    if_clone_list(int, char *, int *);
+void   if_acquire_unsafe(struct ifnet *, struct psref *);
+
+bool   if_held(struct ifnet *);
 
 void   if_input(struct ifnet *, struct mbuf *);
 
diff -r c2c8ef121618 -r cf659ba12485 sys/net/if_bridge.c
--- a/sys/net/if_bridge.c       Fri Jun 10 13:27:10 2016 +0000
+++ b/sys/net/if_bridge.c       Fri Jun 10 13:31:43 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_bridge.c,v 1.124 2016/06/10 13:27:16 ozaki-r Exp $  */
+/*     $NetBSD: if_bridge.c,v 1.125 2016/06/10 13:31:44 ozaki-r Exp $  */
 
 /*
  * Copyright 2001 Wasabi Systems, Inc.
@@ -80,7 +80,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.124 2016/06/10 13:27:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.125 2016/06/10 13:31:44 ozaki-r Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_bridge_ipf.h"
@@ -1610,12 +1610,18 @@
        struct ifnet *src_if, *dst_if;
        struct ether_header *eh;



Home | Main Index | Thread Index | Old Index