tech-net archive

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

Routing socket and interrupt levels



Messages can be sent through the routing socket from device interrupt
handlers at IPL_VM. The one I saw was notification of link state change. The
socket code operates at a much lower level, IPL_SOFTNET, and shouldn't be
called from a higher level. The below fixes it by enqueuing routing messages
to a soft interrupt. Any objections?

Thanks,
Andrew

Index: rtsock.c
===================================================================
RCS file: /cvsroot/src/sys/net/rtsock.c,v
retrieving revision 1.98
diff -u -r1.98 rtsock.c
--- rtsock.c    20 Feb 2008 17:05:53 -0000      1.98
+++ rtsock.c    25 Mar 2008 22:25:27 -0000
@@ -75,6 +75,7 @@
 #include <sys/protosw.h>
 #include <sys/sysctl.h>
 #include <sys/kauth.h>
+#include <sys/intr.h>
 #ifdef RTSOCK_DEBUG
 #include <netinet/in.h>
 #endif /* RTSOCK_DEBUG */
@@ -91,6 +92,10 @@
 struct sockaddr route_src = { .sa_len = 2, .sa_family = PF_ROUTE, };
 struct sockproto route_proto = { .sp_family = PF_ROUTE, };
 
+int    route_maxqlen = IFQ_MAXLEN;
+static struct  ifqueue route_intrq;
+static void    *route_sih;
+
 struct walkarg {
        int     w_op;
        int     w_arg;
@@ -111,6 +116,7 @@
 static int sysctl_iflist(int, struct walkarg *, int);
 static int sysctl_rtable(SYSCTLFN_PROTO);
 static inline void rt_adjustcount(int, int);
+static void route_enqueue(struct mbuf *);
 
 /* Sleazy use of local variables throughout file, warning!!!! */
 #define dst    info.rti_info[RTAX_DST]
@@ -460,7 +466,7 @@
        if (family)
                route_proto.sp_protocol = family;
        if (m)
-               raw_input(m, &route_proto, &route_src, &route_dst);
+               route_enqueue(m);
        if (rp)
                rp->rcb_proto.sp_family = PF_ROUTE;
     }
@@ -712,7 +718,7 @@
                return;
        mtod(m, struct rt_msghdr *)->rtm_addrs = rtinfo->rti_addrs;
        route_proto.sp_protocol = sa ? sa->sa_family : 0;
-       raw_input(m, &route_proto, &route_src, &route_dst);
+       route_enqueue(m);
 }
 
 /*
@@ -741,7 +747,7 @@
        if (m == NULL)
                return;
        route_proto.sp_protocol = 0;
-       raw_input(m, &route_proto, &route_src, &route_dst);
+       route_enqueue(m);
 #ifdef COMPAT_14
        memset(&info, 0, sizeof(info));
        memset(&oifm, 0, sizeof(oifm));
@@ -770,7 +776,7 @@
        if (m == NULL)
                return;
        route_proto.sp_protocol = 0;
-       raw_input(m, &route_proto, &route_src, &route_dst);
+       route_enqueue(m);
 #endif
 }
 
@@ -833,7 +839,7 @@
                        mtod(m, struct rt_msghdr *)->rtm_addrs = info.rti_addrs;
                }
                route_proto.sp_protocol = sa ? sa->sa_family : 0;
-               raw_input(m, &route_proto, &route_src, &route_dst);
+               route_enqueue(m);
        }
 }
 
@@ -867,7 +873,7 @@
        if (m == NULL)
                return;
        route_proto.sp_protocol = 0;
-       raw_input(m, &route_proto, &route_src, &route_dst);
+       route_enqueue(m);
 }
 
 /*
@@ -910,7 +916,7 @@
                m->m_pkthdr.len += data_len;
        mtod(m, struct if_announcemsghdr *)->ifan_msglen += data_len;
        route_proto.sp_protocol = 0;
-       raw_input(m, &route_proto, &route_src, &route_dst);
+       route_enqueue(m);
 }
 
 /*
@@ -1164,6 +1170,54 @@
 }
 
 /*
+ * Routing message software interrupt routine
+ */
+static void
+route_intr(void *cookie)
+{
+       int s;
+       struct mbuf *m;
+
+       while (!IF_IS_EMPTY(&route_intrq)) {
+               s = splnet();
+               IF_DEQUEUE(&route_intrq, m);
+               splx(s);
+               if (m == NULL)
+                       break;
+               raw_input(m, &route_proto, &route_src, &route_dst);
+       }
+}
+
+/*
+ * Enqueue a message to the software interrupt routine.
+ */
+static void
+route_enqueue(struct mbuf *m)
+{
+       int s, wasempty;
+
+       s = splnet();
+       if (IF_QFULL(&route_intrq)) {
+               IF_DROP(&route_intrq);
+               m_freem(m);
+       } else {
+               wasempty = IF_IS_EMPTY(&route_intrq);
+               IF_ENQUEUE(&route_intrq, m);
+               if (wasempty)
+                       softint_schedule(route_sih);
+       }
+       splx(s);
+}
+
+void
+rt_init(void)
+{
+
+       route_intrq.ifq_maxlen = route_maxqlen;
+       route_sih = softint_establish(SOFTINT_NET, route_intr, NULL);
+}
+
+/*
  * Definitions of protocols supported in the ROUTE domain.
  */
 
Index: route.c
===================================================================
RCS file: /cvsroot/src/sys/net/route.c,v
retrieving revision 1.105
diff -u -r1.105 route.c
--- route.c     21 Jan 2008 09:11:24 -0000      1.105
+++ route.c     25 Mar 2008 22:25:27 -0000
@@ -1,7 +1,7 @@
 /*     $NetBSD: route.c,v 1.105 2008/01/21 09:11:24 dyoung Exp $       */
 
 /*-
- * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -229,6 +229,7 @@
 route_init(void)
 {
 
+       rt_init();
        rn_init();      /* initialize all zeroes, all ones, mask table */
        rtable_init((void **)rt_tables);
 }
Index: route.h
===================================================================
RCS file: /cvsroot/src/sys/net/route.h,v
retrieving revision 1.69
diff -u -r1.69 route.h
--- route.h     20 Feb 2008 17:05:53 -0000      1.69
+++ route.h     25 Mar 2008 22:25:29 -0000
@@ -303,6 +303,7 @@
 int     route_output(struct mbuf *, ...);
 int     route_usrreq(struct socket *,
            int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *);
+void    rt_init(void);
 void    rt_ifannouncemsg(struct ifnet *, int);
 void    rt_ieee80211msg(struct ifnet *, int, void *, size_t);
 void    rt_ifmsg(struct ifnet *);



Home | Main Index | Thread Index | Old Index