Discussion:
Routing socket and interrupt levels
(too old to reply)
Andrew Doran
2008-03-25 22:33:02 UTC
Permalink
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 *);


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Matt Thomas
2008-03-25 23:08:45 UTC
Permalink
Post by Andrew Doran
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 *);
static void route_enqueue(struct mbuf *, int);
Post by Andrew Doran
/* 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);
route_enqueue(m, sa ? sa->sa_family : 0);
Post by Andrew Doran
}
/*
@@ -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);
route_enqueue(m, 0);
Post by Andrew Doran
#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);
route_enqueue(m, 0);
Post by Andrew Doran
#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);
route_enqueue(m, sa ? sa->sa_family : 0);
Post by Andrew Doran
}
}
@@ -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);
route_enqueue(m, 0);
Post by Andrew Doran
}
/*
@@ -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);
route_enqueue(m, 0);
Post by Andrew Doran
}
/*
@@ -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;
Make route_proto a local;

route_proto.sp_family = (uintptr_t) M_GETCTX(m);
Post by Andrew Doran
+ 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 family
Post by Andrew Doran
+{
+ int s, wasempty;
+
+ s = splnet();
+ if (IF_QFULL(&route_intrq)) {
+ IF_DROP(&route_intrq);
+ m_freem(m);
+ } else {
+ wasempty = IF_IS_EMPTY(&route_intrq);
M_SETCTX(m, family);
Post by Andrew Doran
+ 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.
*/
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Jason Thorpe
2008-04-15 23:38:26 UTC
Permalink
Post by Andrew Doran
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?
No objections from me.
Post by Andrew Doran
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 *);
-- thorpej


--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de
Loading...