From 327b288e5ce5515e6914ef443418cf2401384fe7 Mon Sep 17 00:00:00 2001 From: Julian Elischer Date: Fri, 25 Jun 2004 19:22:05 +0000 Subject: [PATCH] Convert Netgraph to use mbuf tags to pass its meta information around. Thanks to Sam for importing tags in a way that allowed this to be done. Submitted by: Gleb Smirnoff Also allow the sr and ar drivers to create netgraph versions of their modules. Document the change to the ksocket node. --- share/man/man4/ng_ksocket.4 | 23 +++++++++++-- sys/dev/ar/if_ar.c | 11 +++---- sys/dev/cp/if_cp.c | 14 +++++--- sys/dev/ctau/if_ct.c | 14 +++++--- sys/dev/cx/if_cx.c | 14 +++++--- sys/dev/sr/if_sr.c | 11 +++---- sys/dev/usb/udbp.c | 12 +++---- sys/modules/ar/Makefile | 13 ++++++-- sys/modules/sr/Makefile | 11 ++++++- sys/netgraph/atm/uni/ng_uni_cust.h | 1 + sys/netgraph/netgraph.h | 18 ++++++++-- sys/netgraph/ng_ksocket.c | 53 +++++++++--------------------- sys/netgraph/ng_ksocket.h | 10 ++++-- sys/netgraph/ng_lmi.c | 26 +++++++-------- sys/netgraph/ng_parse.c | 1 + 15 files changed, 139 insertions(+), 93 deletions(-) diff --git a/share/man/man4/ng_ksocket.4 b/share/man/man4/ng_ksocket.4 index 3f2d3b2309dd..373a25ee960e 100644 --- a/share/man/man4/ng_ksocket.4 +++ b/share/man/man4/ng_ksocket.4 @@ -34,7 +34,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 15, 1999 +.Dd June 8, 2004 .Dt NG_KSOCKET 4 .Os .Sh NAME @@ -88,6 +88,24 @@ well. For example .Dv inet/dgram/udp is a more readable but equivalent version of .Dv 2/2/17 . +.Pp +Data received into socket is sent out via hook. +Data received on hook is sent out from socket, if the latter is +connected (an +.Dv NGM_KSOCKET_CONNECT +was sent to node before). +If socket is not connected, destination +.Dv "struct sockaddr" +must be supplied in an mbuf tag with cookie +.Dv NGM_KSOCKET_COOKIE +and type +.Dv NG_KSOCKET_TAG_SOCKADDR +attached to data. +Otherwise +.Nm +will return +.Dv ENOTCONN +to sender. .Sh CONTROL MESSAGES This node type supports the generic control messages, plus the following: .Bl -tag -width foo @@ -190,7 +208,8 @@ Shutdown of the node closes the associated socket. .Xr socket 2 , .Xr netgraph 4 , .Xr ng_socket 4 , -.Xr ngctl 8 +.Xr ngctl 8 , +.Xr mbuf_tags 9 .Sh HISTORY The .Nm diff --git a/sys/dev/ar/if_ar.c b/sys/dev/ar/if_ar.c index 0ac2af4ed17b..0b98b7a6b565 100644 --- a/sys/dev/ar/if_ar.c +++ b/sys/dev/ar/if_ar.c @@ -2228,10 +2228,9 @@ ngar_rcvdata(hook_p hook, item_p item) struct ar_softc * sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct ifqueue *xmitq_p; struct mbuf *m; - meta_p meta; + struct ng_tag_prio *ptag; NGI_GET_M(item, m); - NGI_GET_META(item, meta); NG_FREE_ITEM(item); /* * data doesn't come in from just anywhere (e.g control hook) @@ -2244,11 +2243,12 @@ ngar_rcvdata(hook_p hook, item_p item) /* * Now queue the data for when it can be sent */ - if (meta && meta->priority > 0) { + if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, + NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) xmitq_p = (&sc->xmitq_hipri); - } else { + else xmitq_p = (&sc->xmitq); - } + s = splimp(); IF_LOCK(xmitq_p); if (_IF_QFULL(xmitq_p)) { @@ -2270,7 +2270,6 @@ ngar_rcvdata(hook_p hook, item_p item) * check if we need to free the mbuf, and then return the error */ NG_FREE_M(m); - NG_FREE_META(meta); return (error); } diff --git a/sys/dev/cp/if_cp.c b/sys/dev/cp/if_cp.c index dfb4a7e662d7..728df8026bd4 100644 --- a/sys/dev/cp/if_cp.c +++ b/sys/dev/cp/if_cp.c @@ -2261,7 +2261,7 @@ static int ng_cp_rcvdata (hook_p hook, item_p item) { drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); struct mbuf *m; - meta_p meta; + struct ng_tag_prio *ptag; #else static int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) { @@ -2273,18 +2273,23 @@ static int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) CP_DEBUG2 (d, ("Rcvdata\n")); #if __FreeBSD_version >= 500000 NGI_GET_M (item, m); - NGI_GET_META (item, meta); NG_FREE_ITEM (item); if (! NG_HOOK_PRIVATE (hook) || ! d) { NG_FREE_M (m); - NG_FREE_META (meta); #else if (! hook->private || ! d) { NG_FREE_DATA (m,meta); #endif return ENETDOWN; } - q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue; + + /* Check for high priority data */ + if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, + NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) + q = &d->hi_queue; + else + q = &d->queue; + s = splimp (); #if __FreeBSD_version >= 500000 IF_LOCK (q); @@ -2293,7 +2298,6 @@ static int ng_cp_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) IF_UNLOCK (q); splx (s); NG_FREE_M (m); - NG_FREE_META (meta); return ENOBUFS; } _IF_ENQUEUE (q, m); diff --git a/sys/dev/ctau/if_ct.c b/sys/dev/ctau/if_ct.c index f4cf7b1e6a7c..67eb83a3b1d0 100644 --- a/sys/dev/ctau/if_ct.c +++ b/sys/dev/ctau/if_ct.c @@ -2187,7 +2187,7 @@ static int ng_ct_rcvdata (hook_p hook, item_p item) { drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); struct mbuf *m; - meta_p meta; + struct ng_tag_prio *ptag; #else static int ng_ct_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) { @@ -2201,18 +2201,23 @@ static int ng_ct_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) #if __FreeBSD_version >= 500000 NGI_GET_M (item, m); - NGI_GET_META (item, meta); NG_FREE_ITEM (item); if (! NG_HOOK_PRIVATE (hook) || ! d) { NG_FREE_M (m); - NG_FREE_META (meta); #else if (! hook->private || ! d) { NG_FREE_DATA (m,meta); #endif return ENETDOWN; } - q = (meta && meta->priority > 0) ? &d->hi_queue : &d->queue; + + /* Check for high priority data */ + if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, + NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) + q = &d->hi_queue; + else + q = &d->queue; + s = splimp (); #if __FreeBSD_version >= 500000 IF_LOCK (q); @@ -2221,7 +2226,6 @@ static int ng_ct_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) IF_UNLOCK (q); splx (s); NG_FREE_M (m); - NG_FREE_META (meta); return ENOBUFS; } _IF_ENQUEUE (q, m); diff --git a/sys/dev/cx/if_cx.c b/sys/dev/cx/if_cx.c index f7e57fa4b8d5..7354bc233082 100644 --- a/sys/dev/cx/if_cx.c +++ b/sys/dev/cx/if_cx.c @@ -2705,7 +2705,7 @@ static int ng_cx_rcvdata (hook_p hook, item_p item) { drv_t *d = NG_NODE_PRIVATE (NG_HOOK_NODE(hook)); struct mbuf *m; - meta_p meta; + struct ng_tag_prio *ptag; #else static int ng_cx_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) { @@ -2716,18 +2716,23 @@ static int ng_cx_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) #if __FreeBSD_version >= 500000 NGI_GET_M (item, m); - NGI_GET_META (item, meta); NG_FREE_ITEM (item); if (! NG_HOOK_PRIVATE (hook) || ! d) { NG_FREE_M (m); - NG_FREE_META (meta); #else if (! hook->private || ! d) { NG_FREE_DATA (m,meta); #endif return ENETDOWN; } - q = (meta && meta->priority > 0) ? &d->hi_queue : &d->lo_queue; + + /* Check for high priority data */ + if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, + NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) + q = &d->hi_queue; + else + q = &d->lo_queue; + s = splhigh (); #if __FreeBSD_version >= 500000 IF_LOCK (q); @@ -2736,7 +2741,6 @@ static int ng_cx_rcvdata (hook_p hook, struct mbuf *m, meta_p meta) IF_UNLOCK (q); splx (s); NG_FREE_M (m); - NG_FREE_META (meta); return ENOBUFS; } _IF_ENQUEUE (q, m); diff --git a/sys/dev/sr/if_sr.c b/sys/dev/sr/if_sr.c index 45eaf5060050..5f60aef31eb4 100644 --- a/sys/dev/sr/if_sr.c +++ b/sys/dev/sr/if_sr.c @@ -2830,10 +2830,9 @@ ngsr_rcvdata(hook_p hook, item_p item) struct sr_softc * sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct ifqueue *xmitq_p; struct mbuf *m; - meta_p meta; + struct ng_tag_prio *ptag; NGI_GET_M(item, m); - NGI_GET_META(item, meta); NG_FREE_ITEM(item); /* * data doesn't come in from just anywhere (e.g control hook) @@ -2846,11 +2845,12 @@ ngsr_rcvdata(hook_p hook, item_p item) /* * Now queue the data for when it can be sent */ - if (meta && meta->priority > 0) { + if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, + NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) xmitq_p = (&sc->xmitq_hipri); - } else { + else xmitq_p = (&sc->xmitq); - } + s = splimp(); IF_LOCK(xmitq_p); if (_IF_QFULL(xmitq_p)) { @@ -2872,7 +2872,6 @@ ngsr_rcvdata(hook_p hook, item_p item) * check if we need to free the mbuf, and then return the error */ NG_FREE_M(m); - NG_FREE_META(meta); return (error); } diff --git a/sys/dev/usb/udbp.c b/sys/dev/usb/udbp.c index 533a799f484d..1a126ec1a03c 100644 --- a/sys/dev/usb/udbp.c +++ b/sys/dev/usb/udbp.c @@ -729,19 +729,20 @@ ng_udbp_rcvdata(hook_p hook, item_p item) struct ifqueue *xmitq_p; int s; struct mbuf *m; - meta_p meta; + struct ng_tag_prio *ptag; NGI_GET_M(item, m); - NGI_GET_META(item, meta); NG_FREE_ITEM(item); + /* * Now queue the data for when it can be sent */ - if (meta && meta->priority > 0) { + if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE, + NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) ) xmitq_p = (&sc->xmitq_hipri); - } else { + else xmitq_p = (&sc->xmitq); - } + s = splusb(); IF_LOCK(xmitq_p); if (_IF_QFULL(xmitq_p)) { @@ -763,7 +764,6 @@ ng_udbp_rcvdata(hook_p hook, item_p item) * check if we need to free the mbuf, and then return the error */ NG_FREE_M(m); - NG_FREE_META(meta); return (error); } diff --git a/sys/modules/ar/Makefile b/sys/modules/ar/Makefile index 3951fd46fb9f..fae9452ef414 100644 --- a/sys/modules/ar/Makefile +++ b/sys/modules/ar/Makefile @@ -1,8 +1,17 @@ # $FreeBSD$ - + .PATH: ${.CURDIR}/../../dev/ar KMOD = if_ar SRCS = if_ar.c if_ar_isa.c if_ar_pci.c SRCS += device_if.h bus_if.h pci_if.h isa_if.h opt_netgraph.h - + +NETGRAPH?= 0 + +opt_netgraph.h: +.if ${NETGRAPH} != 0 + echo "#define NETGRAPH ${NETGRAPH}" > opt_netgraph.h +.else + echo "" > opt_netgraph.h +.endif + .include diff --git a/sys/modules/sr/Makefile b/sys/modules/sr/Makefile index 7b173ab26ad1..b49d21edbdbe 100644 --- a/sys/modules/sr/Makefile +++ b/sys/modules/sr/Makefile @@ -4,5 +4,14 @@ KMOD = if_sr SRCS = if_sr.c if_sr_isa.c if_sr_pci.c SRCS += device_if.h bus_if.h pci_if.h isa_if.h opt_netgraph.h - + +NETGRAPH?= 0 + +opt_netgraph.h: +.if ${NETGRAPH} != 0 + echo "#define NETGRAPH ${NETGRAPH}" > opt_netgraph.h +.else + echo "" > opt_netgraph.h +.endif + .include diff --git a/sys/netgraph/atm/uni/ng_uni_cust.h b/sys/netgraph/atm/uni/ng_uni_cust.h index 84e63e89e87e..121d7ab8d588 100644 --- a/sys/netgraph/atm/uni/ng_uni_cust.h +++ b/sys/netgraph/atm/uni/ng_uni_cust.h @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/sys/netgraph/netgraph.h b/sys/netgraph/netgraph.h index 99adc60d0da4..90d2056e4d51 100644 --- a/sys/netgraph/netgraph.h +++ b/sys/netgraph/netgraph.h @@ -1137,10 +1137,24 @@ struct callout_handle ng_item_fn *fn, void * arg1, int arg2); /* - * prototypes the user should DEFINITLY not use directly + * prototypes the user should DEFINITELY not use directly */ void ng_free_item(item_p item); /* Use NG_FREE_ITEM instead */ int ng_mod_event(module_t mod, int what, void *arg); -#endif /* _NETGRAPH_NETGRAPH_H_ */ +/* + * Tag definitions and constants + */ +#define NG_TAG_PRIO 1 + +struct ng_tag_prio { + struct m_tag tag; + char priority; + char discardability; +}; + +#define NG_PRIO_CUTOFF 32 +#define NG_PRIO_LINKSTATE 64 + +#endif /* _NETGRAPH_NETGRAPH_H_ */ diff --git a/sys/netgraph/ng_ksocket.c b/sys/netgraph/ng_ksocket.c index 458bbdee41e9..715baa961811 100644 --- a/sys/netgraph/ng_ksocket.c +++ b/sys/netgraph/ng_ksocket.c @@ -893,9 +893,9 @@ ng_ksocket_rcvdata(hook_p hook, item_p item) const priv_p priv = NG_NODE_PRIVATE(node); struct socket *const so = priv->so; struct sockaddr *sa = NULL; - meta_p meta; int error; struct mbuf *m; + struct sa_tag *stag; /* Avoid reentrantly sending on the socket */ if ((priv->flags & KSF_SENDING) != 0) { @@ -903,35 +903,20 @@ ng_ksocket_rcvdata(hook_p hook, item_p item) return (EDEADLK); } - /* Extract data and meta information */ + /* Extract data */ NGI_GET_M(item, m); - NGI_GET_META(item, meta); NG_FREE_ITEM(item); - /* If any meta info, look for peer socket address */ - if (meta != NULL) { - struct meta_field_header *field; - - /* Look for peer socket address */ - for (field = &meta->options[0]; - (caddr_t)field < (caddr_t)meta + meta->used_len; - field = (struct meta_field_header *) - ((caddr_t)field + field->len)) { - if (field->cookie != NGM_KSOCKET_COOKIE - || field->type != NG_KSOCKET_META_SOCKADDR) - continue; - sa = (struct sockaddr *)field->data; - break; - } - } + /* Look if socket address is stored in packet tags */ + if ((stag = (struct sa_tag *)m_tag_locate(m, NGM_KSOCKET_COOKIE, + NG_KSOCKET_TAG_SOCKADDR, NULL)) != NULL) + sa = &stag->sa; /* Send packet */ priv->flags |= KSF_SENDING; error = (*so->so_proto->pr_usrreqs->pru_sosend)(so, sa, 0, m, 0, 0, td); priv->flags &= ~KSF_SENDING; - /* Clean up and exit */ - NG_FREE_META(meta); return (error); } @@ -1103,7 +1088,6 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag) flags = MSG_DONTWAIT; while (1) { struct sockaddr *sa = NULL; - meta_p meta = NULL; struct mbuf *n; /* Try to get next packet from socket */ @@ -1124,30 +1108,23 @@ ng_ksocket_incoming2(node_p node, hook_p hook, void *arg1, int waitflag) for (n = m, m->m_pkthdr.len = 0; n != NULL; n = n->m_next) m->m_pkthdr.len += n->m_len; - /* Put peer's socket address (if any) into a meta info blob */ + /* Put peer's socket address (if any) into a tag */ if (sa != NULL) { - struct meta_field_header *mhead; - u_int len; + struct sa_tag *stag; - len = sizeof(*meta) + sizeof(*mhead) + sa->sa_len; - MALLOC(meta, meta_p, len, M_NETGRAPH_META, - M_NOWAIT | M_ZERO); - if (meta == NULL) { + stag = (struct sa_tag *)m_tag_alloc(NGM_KSOCKET_COOKIE, + NG_KSOCKET_TAG_SOCKADDR, sa->sa_len, M_NOWAIT); + if (stag == NULL) { FREE(sa, M_SONAME); goto sendit; } - mhead = &meta->options[0]; - meta->allocated_len = len; - meta->used_len = len; - mhead->cookie = NGM_KSOCKET_COOKIE; - mhead->type = NG_KSOCKET_META_SOCKADDR; - mhead->len = sizeof(*mhead) + sa->sa_len; - bcopy(sa, mhead->data, sa->sa_len); + bcopy(sa, &stag->sa, sa->sa_len); FREE(sa, M_SONAME); + m_tag_prepend(m, &stag->tag); } -sendit: /* Forward data with optional peer sockaddr as meta info */ - NG_SEND_DATA(error, priv->hook, m, meta); +sendit: /* Forward data with optional peer sockaddr as packet tag */ + NG_SEND_DATA_ONLY(error, priv->hook, m); } /* diff --git a/sys/netgraph/ng_ksocket.h b/sys/netgraph/ng_ksocket.h index cad516425ddf..d9d193224702 100644 --- a/sys/netgraph/ng_ksocket.h +++ b/sys/netgraph/ng_ksocket.h @@ -94,7 +94,13 @@ enum { NGM_KSOCKET_GETOPT, }; -/* Meta information ID's */ -#define NG_KSOCKET_META_SOCKADDR 1 /* data is struct sockaddr */ +/* Structure for sockaddr tag */ +struct sa_tag { + struct m_tag tag; + struct sockaddr sa; +}; + +/* Tag information ID's */ +#define NG_KSOCKET_TAG_SOCKADDR 1 /* data is struct sockaddr */ #endif /* _NETGRAPH_NG_KSOCKET_H_ */ diff --git a/sys/netgraph/ng_lmi.c b/sys/netgraph/ng_lmi.c index cb6fbb149f4a..368d2015bcb0 100644 --- a/sys/netgraph/ng_lmi.c +++ b/sys/netgraph/ng_lmi.c @@ -306,14 +306,13 @@ nglmi_startup(sc_p sc) sc->handle = timeout(LMI_ticker, sc, hz); } -#define META_PAD 16 static void nglmi_inquire(sc_p sc, int full) { struct mbuf *m; + struct ng_tag_prio *ptag; char *cptr, *start; int error; - meta_p meta = NULL; if (sc->lmi_channel == NULL) return; @@ -323,17 +322,18 @@ nglmi_inquire(sc_p sc, int full) return; } m->m_pkthdr.rcvif = NULL; - /* Allocate a meta struct (and leave some slop for options to be - * added by other modules). */ - MALLOC(meta, meta_p, sizeof(*meta) + META_PAD, M_NETGRAPH_META, M_NOWAIT); - if (meta != NULL) { /* if it failed, well, it was optional anyhow */ - meta->used_len = (u_short) sizeof(struct ng_meta); - meta->allocated_len - = (u_short) sizeof(struct ng_meta) + META_PAD; - meta->flags = 0; - meta->priority = NG_LMI_LMI_PRIORITY; - meta->discardability = -1; + + /* Attach a tag to packet, marking it of link level state priority, so + * that device driver would put it in the beginning of queue */ + + ptag = (struct ng_tag_prio *)m_tag_alloc(NGM_GENERIC_COOKIE, NG_TAG_PRIO, + (sizeof(struct ng_tag_prio) - sizeof(struct m_tag)), M_NOWAIT); + if (ptag != NULL) { /* if it failed, well, it was optional anyhow */ + ptag->priority = NG_PRIO_LINKSTATE; + ptag->discardability = -1; + m_tag_prepend(m, &ptag->tag); } + m->m_data += 4; /* leave some room for a header */ cptr = start = mtod(m, char *); /* add in the header for an LMI inquiry. */ @@ -371,7 +371,7 @@ nglmi_inquire(sc_p sc, int full) /* Send it */ m->m_len = m->m_pkthdr.len = cptr - start; - NG_SEND_DATA(error, sc->lmi_channel, m, meta); + NG_SEND_DATA_ONLY(error, sc->lmi_channel, m); /* If we've been sending requests for long enough, and there has * been no response, then mark as DOWN, any DLCIs that are UP. */ diff --git a/sys/netgraph/ng_parse.c b/sys/netgraph/ng_parse.c index 37c5cc415fcd..69090beaf00a 100644 --- a/sys/netgraph/ng_parse.c +++ b/sys/netgraph/ng_parse.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include