This clears out my outstanding netgraph changes.
There is a netgraph change of design in the offing and this is to some
extent a superset of soem of the new functionality and some of the old
functionality that may be removed.

This code works as before, but allows some new features that I want to
work with and evaluate. It is the basis for a version of netgraph
with integral locking for SMP use.

This is running on my test machine with no new problems :-)
This commit is contained in:
Julian Elischer 2000-12-12 18:52:14 +00:00
parent 1ec5afb81e
commit 859a4d166c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=69922
37 changed files with 660 additions and 283 deletions

View File

@ -138,6 +138,11 @@ characters (including NUL byte).
A hook is always connected to another hook. That is, hooks are
created at the time they are connected, and breaking an edge by
removing either hook destroys both hooks.
.It
A hook can be set into a state where incoming packets are always queued
by the input queuing system, rather than being delivered directly. This
is used when the two joined nodes need to be decoupled, e.g. if they are
running at different processor priority levels. (spl)
.El
.Pp
A node may decide to assign special meaning to some hooks.
@ -165,26 +170,41 @@ and
generic control messages below). Nodes are not required to support
these conversions.
.Pp
There are two ways to address a control message. If
There are three ways to address a control message. If
there is a sequence of edges connecting the two nodes, the message
may be
.Dq source routed
by specifying the corresponding sequence
of hooks as the destination address for the message (relative
addressing). Otherwise, the recipient node global
of
.Tn ASCII
hook names as the destination address for the message (relative
addressing). If the destination is adjacent to the source, then the source
node may simply specify (as a pointer in the code) the hook across which the
message should be sent. Otherwise, the recipient node global
.Tn ASCII
name
(or equivalent ID based name) is used as the destination address
for the message (absolute addressing). The two types of addressing
for the message (absolute addressing). The two types of
.Tn ASCII
addressing
may be combined, by specifying an absolute start node and a sequence
of hooks.
of hooks. Only the
.Tn ASCII
addressing modes are available to control programs outside the kernel,
as use of direct pointers is limited of course to kernel modules.
.Pp
Messages often represent commands that are followed by a reply message
in the reverse direction. To facilitate this, the recipient of a
control message is supplied with a
.Dq return address
that is suitable
for addressing a reply.
that is suitable for addressing a reply.
In addition, depending on the topology of
the graph and whether the source has requested it, a pointer to a
pointer that can be read by the source node may also be supplied.
This allows the destination node to directly respond in a
synchronous manner when control returns to the source node, by
simply pointing the supplied pointer to the response message.
Such synchronous message responses are more efficient but are not always possible.
.Pp
Each control message contains a 32 bit value called a
.Em typecookie
@ -193,10 +213,20 @@ Typically each type defines a unique typecookie for the messages
that it understands. However, a node may choose to recognize and
implement more than one type of message.
.Pp
If message is delivered to an address that implies that it arrived
at that node through a particular hook, that hook is identified to the
If a message is delivered to an address that implies that it arrived
at that node through a particular hook, (as opposed to having been directly
addressed using its ID or global name), then that hook is identified to the
receiving node. This allows a message to be rerouted or passed on, should
a node decide that this is required.
a node decide that this is required, in much the same way that data packets
are passed around between nodes. A set of standard
messages for flow control and link management purposes are
defined by the base system that are usually
passed around in this manner. Flow control message would usually travel
in the opposite direction to the data to which they pertain.
.Pp
Since flow control packets can also result from data being sent, it is also
possible to return a synchronous message response to a data packet being
sent between nodes. (See later).
.Sh Netgraph is Functional
In order to minimize latency, most
.Nm
@ -209,14 +239,16 @@ generic
data delivery function. This function in turn locates
node B and calls B's
.Dq receive data
method.
method. There are exceptions to this.
.Pp
It is allowable for nodes to reject a data packet, or to pass it back to the
caller in a modified or completely replaced form. The caller can notify the
node being called that it does not wish to receive any such packets
by using the
.Fn NG_SEND_DATA
macro, in which case, the second node should just discard rejected packets.
and
.Fn NG_SEND_DATA_ONLY
macros, in which case, the second node should just discard rejected packets.
If the sender knows how to handle returned packets, it must use the
.Fn NG_SEND_DATA_RET
macro, which will adjust the parameters to point to the returned data
@ -237,12 +269,12 @@ message before the original delivery function call returns.
Netgraph nodes and support routines generally run at
.Fn splnet .
However, some nodes may want to send data and control messages
from a different priority level. Netgraph supplies queueing routines which
utilize the NETISR system to move message delivery to
from a different priority level. Netgraph supplies a mechanism which
utilizes the NETISR system to move message and data delivery to
.Fn splnet .
Nodes that run at other priorities (e.g. interfaces) can be directly
linked to other nodes so that the combination runs at the other priority,
however any interaction with nodes running at splnet MUST be achievd via the
however any interaction with nodes running at splnet MUST be achieved via the
queueing functions, (which use the
.Fn netisr
feature of the kernel).
@ -303,7 +335,10 @@ it needs, or may reject the connection, based on the name of the hook.
After both ends have accepted their
hooks, and the links have been made, the nodes get a chance to
find out who their peer is across the link and can then decide to reject
the connection. Tear-down is automatic.
the connection. Tear-down is automatic. This is also the time at which
a node may decide whether to set a particular hook (or its peer) into
.Em queuing
mode.
.It Destruction of a hook
The node is notified of a broken connection. The node may consider some hooks
to be critical to operation and others to be expendable: the disconnection
@ -320,7 +355,7 @@ in that a shutdown breaks all edges and resets the node,
but doesn't remove it, in which case the generic destructor is not called.
.El
.Sh Sending and Receiving Data
Three other methods are also supported by all nodes:
Two other methods are also supported by all nodes:
.Bl -tag -width xxx
.It Receive data message
An mbuf chain is passed to the node.
@ -342,7 +377,7 @@ structure describing meta-data about the message
.Dv NULL
if there is no additional information. The format for this information is
described in
.Pa netgraph.h .
.Pa sys/netgraph/netgraph.h .
The memory for meta-data must allocated via
.Fn malloc
with type
@ -361,23 +396,30 @@ and if it is different, the original must be freed.
.Pp
The receiving node may decide to defer the data by queueing it in the
.Nm
NETISR system (see below).
NETISR system (see below). It achieves this by setting the
.Dv HK_QUEUE
flag in the flags word of the hook on which that data will arrive.
The infrastructure will respect that bit and queue the data for delivery at
a later time, rather than deliver it directly. A node may decide to set
the bit on the
.Em peer
node, so that it's own output packets are queued. This is used
by device drivers running at different processor priorities to transfer
packet delivery to the splnet() level at which the bulk of
.Nm
runs.
.Pp
The structure and use of meta-data is still experimental, but is presently used in
frame-relay to indicate that management packets should be queued for transmission
The structure and use of meta-data is still experimental, but is
presently used in frame-relay to indicate that management packets
should be queued for transmission
at a higher priority than data packets. This is required for
conformance with Frame Relay standards.
.Pp
.It Receive queued data message
Usually this will be the same function as
.Em Receive data message.
This is the entry point called when a data message is being handed to
the node after having been queued in the NETISR system.
This allows a node to decide in the
.Em Receive data message
method that a message should be deferred and queued,
and be sure that when it is processed from the queue,
it will not be queued again.
The node may also receive information allowing it to send a synchronous
message response to one of the originators of the data. it is envisionned
that such a message would contain error or flow-control information.
Standard messages for these purposes have been defined in
.Pa sys/netgraph/netgraph.h .
.It Receive control message
This method is called when a control message is addressed to the node.
A return address is always supplied, giving the address of the node
@ -445,7 +487,7 @@ Here are some examples of valid netgraph addresses:
foo:
.:hook1
foo:hook1.hook2
[f057cd80]:hook1
[d80]:hook1
.Ed
.Pp
Consider the following set of nodes might be created for a site with
@ -497,6 +539,25 @@ the next routing decision. So when B receives a frame on hook
.Dq data
it decodes the frame relay header to determine the DLCI,
and then forwards the unwrapped frame to either C or D.
.Pp
In a similar way, flow control messages may be routed in the reverse
direction to outgoing data. For example a "buffer nearly full" message from
.Em "Frame1:
would be passed to node
.Em B
which might decide to send similar messages to both nodes
.Em C
and
.Em D .
The nodes would use
.Em "Direct hook pointer"
addressing to route the messages. The message may have travelled from
.Em "Frame1:
to
.Em B
as a synchronous reply, saving time and cycles.
.Pp
A similar graph might be used to represent multi-link PPP running
over an ISDN line:
@ -512,7 +573,12 @@ over an ISDN line:
[ (no name) ] [ (no name) ]
.Ed
.Sh Netgraph Structures
Interesting members of the node and hook structures are shown below:
Interesting members of the node and hook structures are shown below
however you should
check
.Pa sys/netgraph/netgraph.h
on your system for more up-to-date versions.
.Bd -literal
struct ng_node {
char *name; /* Optional globally unique name */
@ -547,7 +613,7 @@ incrementing
From a hook you can obtain the corresponding node, and from
a node the list of all active hooks.
.Pp
Node types are described by these structures:
Node types are described by the structures below:
.Bd -literal
/** How to convert a control message from binary <-> ASCII */
struct ng_cmdlist {
@ -570,22 +636,23 @@ struct ng_type {
/** Methods using the node **/
int (*rcvmsg)(node_p node, /* Receive control message */
struct ng_mesg *msg, /* The message */
const char *retaddr, /* Return address */
struct ng_mesg **resp /* Synchronous response */
hook_p lasthook); /* last hook traversed */
struct ng_mesg *msg, /* The message */
const char *retaddr, /* Return address */
struct ng_mesg **resp /* Synchronous response */
hook_p lasthook); /* last hook traversed */
int (*shutdown)(node_p node); /* Shutdown this node */
int (*newhook)(node_p node, /* create a new hook */
hook_p hook, /* Pre-allocated struct */
const char *name); /* Name for new hook */
hook_p hook, /* Pre-allocated struct */
const char *name); /* Name for new hook */
/** Methods using the hook **/
int (*connect)(hook_p hook); /* Confirm new hook attachment */
int (*rcvdata)(hook_p hook, /* Receive data on a hook */
struct mbuf *m, /* The data in an mbuf */
meta_p meta, /* Meta-data, if any */
struct mbuf **ret_m, /* return data here */
meta_p *ret_meta); /* return Meta-data here */
struct mbuf *m, /* The data in an mbuf */
meta_p meta, /* Meta-data, if any */
struct mbuf **ret_m, /* return data here */
meta_p *ret_meta, /* return Meta-data here */
struct ng_message **resp); /* Synchronous reply info */
int (*disconnect)(hook_p hook); /* Notify disconnection of hook */
/** How to convert control messages binary <-> ASCII */
@ -611,7 +678,7 @@ struct ng_mesg {
char data[0]; /* Start of cmd/resp data */
};
#define NG_VERSION 1 /* Netgraph version */
#define NG_VERSION 3 /* Netgraph version */
#define NGF_ORIG 0x0000 /* Command */
#define NGF_RESP 0x0001 /* Response */
.Ed
@ -828,6 +895,23 @@ header fields filled in, plus the NUL-terminated string version of
the arguments in the arguments field. If successful, the reply
contains the binary version of the control message.
.El
.Sh Flow Control Messages
In addition to the control messages that affect nodes with respect to the
graph, there are also a number of
.Em Flow-control
messages defined. At present these are
.Em NOT
handled automatically by the system, so
nodes need to handle them if they are going to be used in a graph utilising
flow control, and will be in the likely path of these messages. The
default action of a node that doesn't understand these messages should
be to pass them onto the next node. Hopefully some helper functions
will assist in this eventually. These messages are also defined in
.Pa sys/netgraph/ng_message.h
and have a separate cookie
.Em NG_FLOW_COOKIE
to help identify them. They will not be covered in depth here.
.Sh Metadata
Data moving through the
.Nm
@ -993,7 +1077,38 @@ The interfaces are named
.Em ng0 ,
.Em ng1 ,
etc.
.It ONE2MANY
This node implements a simple round-robin multiplexer. It can be used
for example to make several LAN ports act together to get a higher speed
link between two machines.
.It Various PPP related nodes.
There is a full multilink PPP implementation that runs in Netgraph.
The
.Em Mpd
port can use these modules to make a very low latency high
capacity ppp system. It also supports
.Em PPTP
vpns using the
.Em PPTP
node.
.It PPPOE
A server and client side implememtation of PPPoE. Used in conjunction with
either
.Xr ppp 8
or the
.Em mpd port.
.It BRIDGE
This node, togther with the ethernet nodes allows a very flexible
bridging system to be implemented.
.It KSOCKET
This intriguing node looks like a socket to the system but diverts
all data to and from the netgraph system for further processing. This allows
such things as UDP tunnels to be almost trivially implemented from the
command line.
.El
.Pp
Refer to the section at the end of this man page for more nodes types.
.Sh NOTES
Whether a named node exists can be checked by trying to send a control message
to it (e.g.,
@ -1074,14 +1189,20 @@ node type is also useful for debugging, especially in conjunction with
.Xr ngctl 8
and
.Xr nghook 8 .
.Pp
Also look in /usr/share/examples/netgraph for solutions to several
common networking problems, solved using
.Nm .
.Sh SEE ALSO
.Xr socket 2 ,
.Xr netgraph 3 ,
.Xr ng_async 4 ,
.Xr ng_bridge 4 ,
.Xr ng_bpf 4 ,
.Xr ng_cisco 4 ,
.Xr ng_ether 4 ,
.Xr ng_echo 4 ,
.Xr ng_ether 4 ,
.Xr ng_frame_relay 4 ,
.Xr ng_hole 4 ,
.Xr ng_iface 4 ,
@ -1090,6 +1211,7 @@ and
.Xr ng_mppc 4 ,
.Xr ng_ppp 4 ,
.Xr ng_pppoe 4 ,
.Xr ng_pptpgre 4 ,
.Xr ng_rfc1490 4 ,
.Xr ng_socket 4 ,
.Xr ng_tee 4 ,

View File

@ -285,7 +285,6 @@ static struct ng_type typestruct = {
NULL,
ngar_connect,
ngar_rcvdata,
ngar_rcvdata,
ngar_disconnect,
NULL
};
@ -1732,6 +1731,9 @@ ar_get_packets(struct ar_softc *sc)
int i;
int len;
u_char rxstat;
#ifdef NETGRAPH
int error;
#endif
while(ar_packet_avail(sc, &len, &rxstat)) {
TRC(printf("apa: len %d, rxstat %x\n", len, rxstat));
@ -1765,7 +1767,7 @@ ar_get_packets(struct ar_softc *sc)
sppp_input(&sc->ifsppp.pp_if, m);
sc->ifsppp.pp_if.if_ipackets++;
#else /* NETGRAPH */
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->ipackets++;
#endif /* NETGRAPH */
@ -2283,7 +2285,7 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -2350,6 +2352,8 @@ ngar_rmnode(node_p node)
static int
ngar_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -285,7 +285,6 @@ static struct ng_type typestruct = {
NULL,
ngar_connect,
ngar_rcvdata,
ngar_rcvdata,
ngar_disconnect,
NULL
};
@ -1732,6 +1731,9 @@ ar_get_packets(struct ar_softc *sc)
int i;
int len;
u_char rxstat;
#ifdef NETGRAPH
int error;
#endif
while(ar_packet_avail(sc, &len, &rxstat)) {
TRC(printf("apa: len %d, rxstat %x\n", len, rxstat));
@ -1765,7 +1767,7 @@ ar_get_packets(struct ar_softc *sc)
sppp_input(&sc->ifsppp.pp_if, m);
sc->ifsppp.pp_if.if_ipackets++;
#else /* NETGRAPH */
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->ipackets++;
#endif /* NETGRAPH */
@ -2283,7 +2285,7 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -2350,6 +2352,8 @@ ngar_rmnode(node_p node)
static int
ngar_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -184,7 +184,6 @@ static struct ng_type typestruct = {
NULL,
ng_lmc_connect,
ng_lmc_rcvdata,
ng_lmc_rcvdata,
ng_lmc_disconnect,
ng_lmc_cmdlist
};
@ -623,9 +622,11 @@ lmc_rx_intr(lmc_softc_t * const sc)
}
}
if (accept) {
int error;
ms->m_pkthdr.len = total_len;
ms->m_pkthdr.rcvif = NULL;
ng_queue_data(sc->lmc_hook, ms, NULL);
NG_SEND_DATA_ONLY(error, sc->lmc_hook, ms);
}
ms = m0;
}
@ -1396,7 +1397,7 @@ ng_lmc_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_lmc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -1462,6 +1463,8 @@ ng_lmc_rmnode(node_p node)
static int
ng_lmc_connect(hook_p hook)
{
/* We are probably not at splnet.. force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -2408,6 +2408,8 @@ sr_get_packets(struct sr_softc *sc)
sca_descriptor *rxdesc; /* descriptor in memory */
#ifndef NETGRAPH
struct ifnet *ifp; /* network intf ctl table */
#else
int error;
#endif /* NETGRAPH */
struct mbuf *m = NULL; /* message buffer */
@ -2533,7 +2535,7 @@ sr_get_packets(struct sr_softc *sc)
bp[9], bp[10], bp[11]);
}
#endif
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->ipackets++;
#endif /* NETGRAPH */
/*
@ -3239,7 +3241,7 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -3306,6 +3308,8 @@ ngsr_rmnode(node_p node)
static int
ngsr_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -2408,6 +2408,8 @@ sr_get_packets(struct sr_softc *sc)
sca_descriptor *rxdesc; /* descriptor in memory */
#ifndef NETGRAPH
struct ifnet *ifp; /* network intf ctl table */
#else
int error;
#endif /* NETGRAPH */
struct mbuf *m = NULL; /* message buffer */
@ -2533,7 +2535,7 @@ sr_get_packets(struct sr_softc *sc)
bp[9], bp[10], bp[11]);
}
#endif
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->ipackets++;
#endif /* NETGRAPH */
/*
@ -3239,7 +3241,7 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -3306,6 +3308,8 @@ ngsr_rmnode(node_p node)
static int
ngsr_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -195,7 +195,6 @@ Static struct ng_type ng_udbp_typestruct = {
NULL,
ng_udbp_connect,
ng_udbp_rcvdata,
ng_udbp_rcvdata,
ng_udbp_disconnect,
ng_udbp_cmdlist
};
@ -485,7 +484,6 @@ udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
udbp_p sc = priv; /* XXX see priv above */
int s;
int len;
meta_p meta = NULL;
struct mbuf *m;
if (err) {
@ -506,7 +504,7 @@ udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
if (sc->hook) {
/* get packet from device and send on */
m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
NG_SEND_DATAQ(err, sc->hook, m, meta);
NG_SEND_DATA_ONLY(err, sc->hook, m);
}
splx(s);
@ -723,7 +721,7 @@ ng_udbp_rcvmsg(node_p node,
*/
Static int
ng_udbp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const udbp_p sc = hook->node->private;
int error;
@ -793,6 +791,8 @@ ng_udbp_rmnode(node_p node)
Static int
ng_udbp_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -285,7 +285,6 @@ static struct ng_type typestruct = {
NULL,
ngar_connect,
ngar_rcvdata,
ngar_rcvdata,
ngar_disconnect,
NULL
};
@ -1732,6 +1731,9 @@ ar_get_packets(struct ar_softc *sc)
int i;
int len;
u_char rxstat;
#ifdef NETGRAPH
int error;
#endif
while(ar_packet_avail(sc, &len, &rxstat)) {
TRC(printf("apa: len %d, rxstat %x\n", len, rxstat));
@ -1765,7 +1767,7 @@ ar_get_packets(struct ar_softc *sc)
sppp_input(&sc->ifsppp.pp_if, m);
sc->ifsppp.pp_if.if_ipackets++;
#else /* NETGRAPH */
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->ipackets++;
#endif /* NETGRAPH */
@ -2283,7 +2285,7 @@ ngar_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ngar_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -2350,6 +2352,8 @@ ngar_rmnode(node_p node)
static int
ngar_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -2408,6 +2408,8 @@ sr_get_packets(struct sr_softc *sc)
sca_descriptor *rxdesc; /* descriptor in memory */
#ifndef NETGRAPH
struct ifnet *ifp; /* network intf ctl table */
#else
int error;
#endif /* NETGRAPH */
struct mbuf *m = NULL; /* message buffer */
@ -2533,7 +2535,7 @@ sr_get_packets(struct sr_softc *sc)
bp[9], bp[10], bp[11]);
}
#endif
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->ipackets++;
#endif /* NETGRAPH */
/*
@ -3239,7 +3241,7 @@ ngsr_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ngsr_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int s;
int error = 0;
@ -3306,6 +3308,8 @@ ngsr_rmnode(node_p node)
static int
ngsr_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
/* be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -464,6 +464,7 @@ ing_rx_data_rdy(int unit)
{
register struct ing_softc *sc = &ing_softc[unit];
register struct mbuf *m;
int error;
if((m = *isdn_linktab[unit]->rx_mbuf) == NULL)
return;
@ -476,7 +477,7 @@ ing_rx_data_rdy(int unit)
sc->sc_inpkt++;
ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
}
/*---------------------------------------------------------------------------*
@ -744,7 +745,7 @@ ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
#if defined(__FreeBSD_version) && __FreeBSD_version >= 500000
static int
ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
#else
static int
ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
@ -829,6 +830,8 @@ ng_ing_rmnode(node_p node)
static int
ng_ing_connect(hook_p hook)
{
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
return (0);
}

View File

@ -67,6 +67,7 @@ typedef struct ng_hook *hook_p;
/* Flags for a hook */
#define HK_INVALID 0x0001 /* don't trust it! */
#define HK_QUEUE 0x0002 /* queue for later delivery */
/*
* Structure of a node
@ -139,7 +140,7 @@ typedef int ng_newhook_t(node_p node, hook_p hook, const char *name);
typedef hook_p ng_findhook_t(node_p node, const char *name);
typedef int ng_connect_t(hook_p hook);
typedef int ng_rcvdata_t(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta);
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp);
typedef int ng_disconnect_t(hook_p hook);
/*
@ -158,6 +159,16 @@ struct ng_cmdlist {
/*
* Structure of a node type
* If data is sent to the "rcvdata()" entrypoint then the system
* may decide to defer it until later by queing it with the normal netgraph
* input queuing system. This is decidde by the HK_QUEUE flag being set in
* the flags word of the peer (receiving) hook. The dequeuing mechanism will
* ensure it is not requeued again.
* Note the input queueing system is to allow modules
* to 'release the stack' or to pass data across spl layers.
* The data will be redelivered as soon as the NETISR code runs
* which may be almost immediatly. A node may also do it's own queueing
* for other reasons (e.g. device output queuing).
*/
struct ng_type {
@ -170,8 +181,7 @@ struct ng_type {
ng_newhook_t *newhook; /* first notification of new hook */
ng_findhook_t *findhook; /* only if you have lots of hooks */
ng_connect_t *connect; /* final notification of new hook */
ng_rcvdata_t *rcvdata; /* date comes here */
ng_rcvdata_t *rcvdataq; /* or here if being queued */
ng_rcvdata_t *rcvdata; /* data comes here */
ng_disconnect_t *disconnect; /* notify on disconnect */
const struct ng_cmdlist *cmdlist; /* commands we can convert */
@ -182,47 +192,64 @@ struct ng_type {
};
/* Send data packet with meta-data */
#define NG_SEND_DATA(error, hook, m, a) \
#define NG_SEND_DATA(err, hook, m, meta) \
do { \
(error) = ng_send_data((hook), (m), (a), NULL, NULL); \
(err) = ng_send_data((hook), (m), (meta), \
NULL, NULL, NULL); \
(m) = NULL; \
(a) = NULL; \
(meta) = NULL; \
} while (0)
/* Send queued data packet with meta-data */
#define NG_SEND_DATAQ(error, hook, m, a) \
/* Send data packet with no meta-data */
#define NG_SEND_DATA_ONLY(err, hook, m) \
do { \
(error) = ng_send_dataq((hook), (m), (a), NULL, NULL); \
(err) = ng_send_data((hook), (m), NULL, \
NULL, NULL, NULL); \
(m) = NULL; \
(a) = NULL; \
} while (0)
#define NG_SEND_DATA_RET(error, hook, m, a) \
/* Send data packet including a possible sync response pointer */
#define NG_SEND_DATA_RESP(err, hook, m, meta, rmsg) \
do { \
(err) = ng_send_data((hook), (m), (meta), \
NULL, NULL, rmsg); \
(m) = NULL; \
(meta) = NULL; \
} while (0)
/*
* Send data packet including a possible sync response pointer
* Allow the callee to replace the data and pass it back
* or to simply 'reject it' or 'keep it'
*/
#define NG_SEND_DATA_RET(err, hook, m, meta, rmsg) \
do { \
struct mbuf *rm = NULL; \
meta_p ra = NULL; \
(error) = ng_send_data((hook), (m), (a), &rm, &ra); \
meta_p rmeta = NULL; \
(err) = ng_send_data((hook), (m), (meta), \
&rm, &rmeta, (rmsg)); \
(m) = rm; \
(a) = ra; \
(meta) = rmeta; \
} while (0)
/* Free metadata */
#define NG_FREE_META(a) \
#define NG_FREE_META(meta) \
do { \
if ((a)) { \
FREE((a), M_NETGRAPH); \
a = NULL; \
if ((meta)) { \
FREE((meta), M_NETGRAPH); \
meta = NULL; \
} \
} while (0)
/* Free any data packet and/or meta-data */
#define NG_FREE_DATA(m, a) \
#define NG_FREE_DATA(m, meta) \
do { \
if ((m)) { \
m_freem((m)); \
m = NULL; \
} \
NG_FREE_META((a)); \
NG_FREE_META((meta)); \
} while (0)
/*
@ -268,19 +295,18 @@ int ng_mod_event(module_t mod, int what, void *arg);
int ng_name_node(node_p node, const char *name);
int ng_newtype(struct ng_type *tp);
ng_ID_t ng_node2ID(node_p node);
int ng_path2node(node_p here, const char *path, node_p *dest, char **rtnp,
hook_p *lasthook);
int ng_path2node(node_p here, const char *path,
node_p *dest, hook_p *lasthook);
int ng_path_parse(char *addr, char **node, char **path, char **hook);
int ng_queue_data(hook_p hook, struct mbuf *m, meta_p meta);
int ng_queue_msg(node_p here, struct ng_mesg *msg, const char *address);
int ng_queue_msg(node_p here, struct ng_mesg *msg, const char *address,
hook_p hook, char *retaddr);
void ng_release_node(node_p node);
void ng_rmnode(node_p node);
int ng_send_data(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta);
int ng_send_dataq(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta);
int ng_send_msg(node_p here, struct ng_mesg *msg,
const char *address, struct ng_mesg **resp);
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp);
int ng_send_msg(node_p here, struct ng_mesg *msg, const char *address,
hook_p hook, char *retaddr, struct ng_mesg **resp);
void ng_unname(node_p node);
void ng_unref(node_p node);
int ng_wait_node(node_p node, char *msg);

View File

@ -87,7 +87,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ng_UI_rcvdata,
ng_UI_rcvdata,
ng_UI_disconnect,
NULL
};
@ -151,6 +150,22 @@ static int
ng_UI_rcvmsg(node_p node, struct ng_mesg *msg,
const char *raddr, struct ng_mesg **rp, hook_p lasthook)
{
const priv_p priv = node->private;
if ((msg->header.typecookie == NGM_FLOW_COOKIE) && lasthook) {
if (lasthook == priv->downlink) {
if (priv->uplink) {
return (ng_send_msg(node, msg, NULL,
priv->uplink, raddr, rp));
}
} else {
if (priv->downlink) {
return (ng_send_msg(node, msg, NULL,
priv->downlink, raddr, rp));
}
}
}
FREE(msg, M_NETGRAPH);
return (EINVAL);
}
@ -163,7 +178,7 @@ ng_UI_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_UI_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;

View File

@ -158,7 +158,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
nga_rcvdata,
nga_rcvdata,
nga_disconnect,
nga_cmdlist
};
@ -232,7 +231,7 @@ nga_newhook(node_p node, hook_p hook, const char *name)
*/
static int
nga_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const sc_p sc = hook->node->private;

View File

@ -85,6 +85,9 @@ static int ng_generic_msg(node_p here, struct ng_mesg *msg,
hook_p hook);
static ng_ID_t ng_decodeidname(const char *name);
static int ngb_mod_event(module_t mod, int event, void *data);
static int ng_send_data_dont_queue(hook_p hook, struct mbuf *m,
meta_p meta, struct mbuf **ret_m, meta_p *ret_meta,
struct ng_mesg **resp);
static void ngintr(void);
/* Our own netgraph malloc type */
@ -321,7 +324,7 @@ ng_make_node(const char *typename, node_p *nodepp)
int error;
/* Not found, try to load it as a loadable module */
snprintf(filename, sizeof(filename), "ng_%s", typename);
snprintf(filename, sizeof(filename), "/boot/kernel/ng_%s", typename);
error = linker_load_file(filename, &lf);
if (error != 0)
return (error);
@ -1028,10 +1031,8 @@ ng_path_parse(char *addr, char **nodep, char **pathp, char **hookp)
* return the destination node. Compute the "return address" if desired.
*/
int
ng_path2node(node_p here, const char *address, node_p *destp, char **rtnp,
hook_p *lasthook)
ng_path2node(node_p here, const char *address, node_p *destp, hook_p *lasthook)
{
const node_p start = here;
char fullpath[NG_PATHLEN + 1];
char *nodename, *path, pbuf[2];
node_p node;
@ -1039,8 +1040,6 @@ ng_path2node(node_p here, const char *address, node_p *destp, char **rtnp,
hook_p hook = NULL;
/* Initialize */
if (rtnp)
*rtnp = NULL;
if (destp == NULL)
return EINVAL;
*destp = NULL;
@ -1111,19 +1110,6 @@ ng_path2node(node_p here, const char *address, node_p *destp, char **rtnp,
return (ENXIO);
}
/* Now compute return address, i.e., the path to the sender */
if (rtnp != NULL) {
MALLOC(*rtnp, char *, NG_NODELEN + 2, M_NETGRAPH, M_NOWAIT);
if (*rtnp == NULL) {
TRAP_ERROR;
return (ENOMEM);
}
if (start->name != NULL)
sprintf(*rtnp, "%s:", start->name);
else
sprintf(*rtnp, "[%x]:", ng_node2ID(start));
}
/* Done */
*destp = node;
if (lasthook != NULL)
@ -1160,22 +1146,49 @@ do { \
/*
* Send a control message to a node
* Send a control message to a node.
* If hook is supplied, use it in preference to the address.
* If the return address is not supplied it will be set to this node.
*/
int
ng_send_msg(node_p here, struct ng_mesg *msg, const char *address,
struct ng_mesg **rptr)
hook_p hook, char *retaddr, struct ng_mesg **rptr)
{
node_p dest = NULL;
char *retaddr = NULL;
int error;
hook_p lasthook;
/* Find the target node */
error = ng_path2node(here, address, &dest, &retaddr, &lasthook);
if (error) {
FREE(msg, M_NETGRAPH);
return error;
/*
* Find the target node.
* If there is a HOOK argument, then use that in preference
* to the address.
*/
if (hook) {
lasthook = hook->peer;
dest = lasthook->node;
} else {
error = ng_path2node(here, address, &dest, &lasthook);
if (error) {
FREE(msg, M_NETGRAPH);
return (error);
}
}
/* If the user didn't supply a return addres, assume it's "here". */
if (retaddr == NULL) {
/*
* Now fill out the return address,
* i.e. the name/ID of the sender. (If we didn't get one)
*/
MALLOC(retaddr, char *, NG_NODELEN + 2, M_NETGRAPH, M_NOWAIT);
if (retaddr == NULL) {
TRAP_ERROR;
return (ENOMEM);
}
if (here->name != NULL)
sprintf(retaddr, "%s:", here->name);
else
sprintf(retaddr, "[%x]:", ng_node2ID(here));
}
/* Make sure the resp field is null before we start */
@ -1242,7 +1255,7 @@ ng_generic_msg(node_p here, struct ng_mesg *msg, const char *retaddr,
con->path[sizeof(con->path) - 1] = '\0';
con->ourhook[sizeof(con->ourhook) - 1] = '\0';
con->peerhook[sizeof(con->peerhook) - 1] = '\0';
error = ng_path2node(here, con->path, &node2, NULL, NULL);
error = ng_path2node(here, con->path, &node2, NULL);
if (error)
break;
error = ng_con_nodes(here, con->ourhook, node2, con->peerhook);
@ -1632,65 +1645,54 @@ ng_generic_msg(node_p here, struct ng_mesg *msg, const char *retaddr,
/*
* Send a data packet to a node. If the recipient has no
* 'receive data' method, then silently discard the packet.
* The receiving node may elect to put the data onto the netgraph
* NETISR queue for later delivery. It may do this because it knows there
* is some recursion and wishes to unwind the stack, or because it has
* some suspicion that it is being called at (say) splimp instead of
* splnet.
*/
int
ng_send_data(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
ng_rcvdata_t *rcvdata;
int error;
CHECK_DATA_MBUF(m);
if (hook && (hook->flags & HK_INVALID) == 0) {
rcvdata = hook->peer->node->type->rcvdata;
if (rcvdata != NULL)
error = (*rcvdata)(hook->peer, m, meta,
ret_m, ret_meta);
else {
error = 0;
NG_FREE_DATA(m, meta);
}
} else {
if ((hook == NULL)
|| ((hook->flags & HK_INVALID) != 0)
|| ((rcvdata = hook->peer->node->type->rcvdata) == NULL)) {
TRAP_ERROR;
error = ENOTCONN;
NG_FREE_DATA(m, meta);
return (ENOTCONN);
}
return (error);
if (hook->peer->flags & HK_QUEUE) {
return (ng_queue_data(hook, m, meta));
}
return ( (*rcvdata)(hook->peer, m, meta, ret_m, ret_meta, resp));
}
/*
* Send a queued data packet to a node. If the recipient has no
* 'receive queued data' method, then try the 'receive data' method above.
* Send a queued data packet to a node.
*
* This is meant for data that is being dequeued and should therefore NOT
* be queued again. It ignores the queue flag and should NOT be called
* outside of this file. (thus it is static)
*/
int
ng_send_dataq(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
static int
ng_send_data_dont_queue(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
ng_rcvdata_t *rcvdata;
int error;
CHECK_DATA_MBUF(m);
if (hook && (hook->flags & HK_INVALID) == 0) {
rcvdata = hook->peer->node->type->rcvdataq;
if (rcvdata != NULL)
error = (*rcvdata)(hook->peer, m, meta,
ret_m, ret_meta);
else {
rcvdata = hook->peer->node->type->rcvdata;
if (rcvdata != NULL) {
error = (*rcvdata)(hook->peer, m, meta,
ret_m, ret_meta);
} else {
error = 0;
NG_FREE_DATA(m, meta);
}
}
} else {
if ((hook == NULL)
|| ((hook->flags & HK_INVALID) != 0)
|| ((rcvdata = hook->peer->node->type->rcvdata) == NULL)) {
TRAP_ERROR;
error = ENOTCONN;
NG_FREE_DATA(m, meta);
}
return (error);
return (ENOTCONN);
}
return ((*rcvdata)(hook->peer, m, meta, ret_m, ret_meta, resp));
}
/*
@ -1821,8 +1823,8 @@ struct ng_queue_entry {
struct {
struct ng_mesg *msg_msg;
node_p msg_node;
void *msg_retaddr;
hook_p msg_lasthook;
char *msg_retaddr;
} msg;
} body;
};
@ -1928,23 +1930,50 @@ ng_queue_data(hook_p hook, struct mbuf *m, meta_p meta)
/*
* Running at a raised (but we don't know which) processor priority level,
* put the msg onto a queue to be picked up by another PPL (probably splnet)
* Either specify an address, or a hook to traverse.
* The return address can be specified, or it will be pointed at this node.
*/
int
ng_queue_msg(node_p here, struct ng_mesg *msg, const char *address)
ng_queue_msg(node_p here, struct ng_mesg *msg, const char *address, hook_p hook,char *retaddr)
{
register struct ng_queue_entry *q;
int s;
node_p dest = NULL;
char *retaddr = NULL;
int error;
hook_p lasthook = NULL;
/* Find the target node. */
error = ng_path2node(here, address, &dest, &retaddr, &lasthook);
if (error) {
FREE(msg, M_NETGRAPH);
return (error);
/*
* Find the target node.
* If there is a HOOK argument, then use that in preference
* to the address.
*/
if (hook) {
lasthook = hook->peer;
dest = lasthook->node;
} else {
error = ng_path2node(here, address, &dest, &lasthook);
if (error) {
FREE(msg, M_NETGRAPH);
return (error);
}
}
if (retaddr == NULL) {
/*
* Now fill out the return address,
* i.e. the name/ID of the sender. (If we didn't get one)
*/
MALLOC(retaddr, char *, NG_NODELEN + 2, M_NETGRAPH, M_NOWAIT);
if (retaddr == NULL) {
TRAP_ERROR;
return (ENOMEM);
}
if (here->name != NULL)
sprintf(retaddr, "%s:", here->name);
else
sprintf(retaddr, "[%x]:", ng_node2ID(here));
}
if ((q = ng_getqblk()) == NULL) {
FREE(msg, M_NETGRAPH);
if (retaddr)
@ -1957,8 +1986,8 @@ ng_queue_msg(node_p here, struct ng_mesg *msg, const char *address)
q->next = NULL;
q->body.msg.msg_node = dest;
q->body.msg.msg_msg = msg;
q->body.msg.msg_retaddr = retaddr;
q->body.msg.msg_lasthook = lasthook;
q->body.msg.msg_retaddr = retaddr; /* XXX malloc'd, give it away */
q->body.msg.msg_lasthook = lasthook; /* XXX needs reference */
s = splhigh(); /* protect refs and queue */
dest->refs++; /* don't let it go away while on the queue */
if (lasthook)
@ -2011,7 +2040,10 @@ ngintr(void)
m = ngq->body.data.da_m;
meta = ngq->body.data.da_meta;
RETURN_QBLK(ngq);
NG_SEND_DATAQ(error, hook, m, meta);
ng_send_data_dont_queue(hook, m, meta,
NULL, NULL, NULL);
m = NULL;
meta = NULL;
ng_unref_hook(hook);
break;
case NGQF_MESG:

View File

@ -196,7 +196,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ng_bpf_rcvdata,
ng_bpf_rcvdata,
ng_bpf_disconnect,
ng_bpf_cmdlist
};
@ -375,7 +374,7 @@ ng_bpf_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ng_bpf_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const hinfo_p hip = hook->private;
int totlen = m->m_pkthdr.len;

View File

@ -276,7 +276,6 @@ static struct ng_type ng_bridge_typestruct = {
NULL,
NULL,
ng_bridge_rcvdata,
ng_bridge_rcvdata,
ng_bridge_disconnect,
ng_bridge_cmdlist,
};
@ -511,7 +510,7 @@ ng_bridge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ng_bridge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;

View File

@ -181,7 +181,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
cisco_rcvdata,
cisco_rcvdata,
cisco_disconnect,
ng_cisco_cmdlist
};
@ -351,7 +350,7 @@ cisco_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
cisco_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const sc_p sc = hook->node->private;
struct protoent *pep;
@ -502,8 +501,8 @@ cisco_input(sc_p sc, struct mbuf *m, meta_p meta)
NGM_CISCO_GET_IPADDR, 0, M_NOWAIT);
if (msg == NULL)
goto nomsg;
ng_send_msg(sc->node, msg,
NG_CISCO_HOOK_INET, &resp);
ng_send_msg(sc->node, msg, NULL,
sc->inet.hook, NULL, &resp);
if (resp != NULL)
cisco_rcvmsg(sc->node, resp, ".",
NULL, NULL);

View File

@ -71,7 +71,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
nge_rcvdata,
nge_rcvdata,
nge_disconnect,
NULL
};
@ -98,7 +97,7 @@ nge_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
nge_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
int error = 0;

View File

@ -100,6 +100,7 @@ static ng_constructor_t ng_ether_constructor;
static ng_rcvmsg_t ng_ether_rcvmsg;
static ng_shutdown_t ng_ether_rmnode;
static ng_newhook_t ng_ether_newhook;
static ng_connect_t ng_ether_connect;
static ng_rcvdata_t ng_ether_rcvdata;
static ng_disconnect_t ng_ether_disconnect;
static int ng_ether_mod_event(module_t mod, int event, void *data);
@ -187,8 +188,7 @@ static struct ng_type ng_ether_typestruct = {
ng_ether_rmnode,
ng_ether_newhook,
NULL,
NULL,
ng_ether_rcvdata,
ng_ether_connect,
ng_ether_rcvdata,
ng_ether_disconnect,
ng_ether_cmdlist,
@ -242,7 +242,7 @@ ng_ether_input_orphan(struct ifnet *ifp,
}
/*
* Handle a packet that has come in on an interface.
* Handle a packet that has come in on an ethernet interface.
* The Ethernet header has already been detached from the mbuf,
* so we have to put it back.
*
@ -252,7 +252,6 @@ static void
ng_ether_input2(node_p node, struct mbuf **mp, struct ether_header *eh)
{
const priv_p priv = node->private;
meta_p meta = NULL;
int error;
/* Glue Ethernet header back on */
@ -260,7 +259,7 @@ ng_ether_input2(node_p node, struct mbuf **mp, struct ether_header *eh)
return;
/* Send out lower/orphan hook */
(void)ng_queue_data(priv->lower, *mp, meta);
NG_SEND_DATA_ONLY(error, priv->lower, *mp);
*mp = NULL;
}
@ -281,7 +280,7 @@ ng_ether_output(struct ifnet *ifp, struct mbuf **mp)
return (0);
/* Send it out "upper" hook */
NG_SEND_DATA_RET(error, priv->upper, *mp, meta);
NG_SEND_DATA_RET(error, priv->upper, *mp, meta, NULL);
/* If we got a reflected packet back, handle it */
if (error == 0 && *mp != NULL) {
@ -480,6 +479,18 @@ ng_ether_newhook(node_p node, hook_p hook, const char *name)
return (0);
}
/*
* Hooks are attached, adjust to force queueing.
* We don't really care which hook it is.
* they should all be queuing for outgoing data.
*/
static int
ng_ether_connect(hook_p hook)
{
hook->peer->flags |= HK_QUEUE;
return (0);
}
/*
* Receive an incoming control message.
*/
@ -591,7 +602,7 @@ ng_ether_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ng_ether_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;

View File

@ -147,7 +147,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ngfrm_rcvdata,
ngfrm_rcvdata,
ngfrm_disconnect,
NULL
};
@ -337,7 +336,7 @@ ngfrm_addrlen(char *hdr)
*/
static int
ngfrm_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
struct ctxinfo *const ctxp = hook->private;
int error = 0;

View File

@ -67,7 +67,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ngh_rcvdata,
ngh_rcvdata,
ngh_disconnect,
NULL
};
@ -78,7 +77,7 @@ NETGRAPH_INIT(hole, &typestruct);
*/
static int
ngh_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
NG_FREE_DATA(m, meta);
return 0;

View File

@ -191,7 +191,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ng_iface_rcvdata,
ng_iface_rcvdata,
ng_iface_disconnect,
ng_iface_cmds
};
@ -721,7 +720,7 @@ ng_iface_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_iface_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const priv_p priv = hook->node->private;
const iffam_p iffam = get_iffam_from_hook(priv, hook);

View File

@ -469,7 +469,6 @@ static struct ng_type ng_ksocket_typestruct = {
NULL,
NULL,
ng_ksocket_rcvdata,
ng_ksocket_rcvdata,
ng_ksocket_disconnect,
ng_ksocket_cmds
};
@ -782,7 +781,7 @@ ng_ksocket_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_ksocket_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
struct proc *p = curproc ? curproc : &proc0; /* XXX broken */
const node_p node = hook->node;

View File

@ -108,7 +108,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
nglmi_rcvdata,
nglmi_rcvdata,
nglmi_disconnect,
NULL
};
@ -559,7 +558,7 @@ nglmi_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
nglmi_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
sc_p sc = hook->node->private;
u_char *data;

View File

@ -83,7 +83,7 @@ struct ng_mesg {
}
/* Negraph type binary compatibility field */
#define NG_VERSION 3
#define NG_VERSION 4
/* Flags field flags */
#define NGF_ORIG 0x0000 /* the msg is the original request */
@ -117,6 +117,34 @@ struct ng_mesg {
#define NGM_ASCII2BINARY 13 /* convert ascii to struct ng_mesg */
#define NGM_TEXT_CONFIG 14 /* (optional) get/set text config */
/*
* Flow control and intra node control messages.
* These are routed between nodes to allow flow control and to allow
* events to be passed around the graph.
* There will be some form of default handling for these but I
* do not yet know what it is..
*/
/* Generic message type cookie */
#define NGM_FLOW_COOKIE 851672669 /* temp for debugging */
/* Upstream messages */
#define NGM_LINK_IS_UP 32 /* e.g. carrier found - no data */
#define NGM_LINK_IS_DOWN 33 /* carrier lost, includes queue state */
#define NGM_HIGH_WATER_PASSED 34 /* includes queue state */
#define NGM_LOW_WATER_PASSED 35 /* includes queue state */
#define NGM_SYNC_QUEUE_STATE 36 /* sync response from sending packet */
/* Downstream messages */
#define NGM_DROP_LINK 41 /* drop DTR, etc. - stay in the graph */
#define NGM_RAISE LINK 42 /* if you previously dropped it */
#define NGM_FLUSH_QUEUE 43 /* no data */
#define NGM_GET_BANDWIDTH 44 /* either real or measured */
#define NGM_SET_XMIT_Q_LIMITS 45 /* includes queue state */
#define NGM_GET_XMIT_Q_LIMITS 46 /* returns queue state */
#define NGM_MICROMANAGE 47 /* We want sync. queue state reply
for each packet sent down */
#define NGM_SET_FLOW_MANAGER 48 /* send flow control here */
/* Structure used for NGM_MKPEER */
struct ngm_mkpeer {
char type[NG_TYPELEN + 1]; /* peer type */
@ -271,6 +299,69 @@ struct typelist {
} \
}
struct ngm_bandwidth {
u_int64_t nominal_in;
u_int64_t seen_in;
u_int64_t nominal_out;
u_int64_t seen_out;
};
/* Keep this in sync with the above structure definition */
#define NG_GENERIC_BANDWIDTH_INFO() { \
{ \
{ "nominal_in", &ng_parse_uint64_type }, \
{ "seen_in", &ng_parse_uint64_type }, \
{ "nominal_out", &ng_parse_uint64_type }, \
{ "seen_out", &ng_parse_uint64_type }, \
{ NULL }, \
} \
}
/*
* Information about a node's 'output' queue.
* This is NOT the netgraph input queueing mechanism,
* but rather any queue the node may implement internally
* This has to consider ALTQ if we are to work with it.
* As far as I can see, ALTQ counts PACKETS, not bytes.
* If ALTQ has several queues and one has passed a watermark
* we should have the priority of that queue be real (and not -1)
* XXX ALTQ stuff is just an idea.....
*/
struct ngm_queue_state {
u_int queue_priority; /* maybe only low-pri is full. -1 = all*/
u_int max_queuelen_bytes;
u_int max_queuelen_packets;
u_int low_watermark;
u_int high_watermark;
u_int current;
};
/* Keep this in sync with the above structure definition */
#define NG_GENERIC_QUEUE_INFO() { \
{ \
{ "max_queuelen_bytes", &ng_parse_uint_type }, \
{ "max_queuelen_packets", &ng_parse_uint_type }, \
{ "high_watermark", &ng_parse_uint_type }, \
{ "low_watermark", &ng_parse_uint_type }, \
{ "current", &ng_parse_uint_type }, \
{ NULL }, \
} \
}
/* Tell a node who to send async flow control info to. */
struct flow_manager {
ng_ID_t id; /* unique identifier */
};
/* Keep this in sync with the above structure definition */
#define NG_GENERIC_FLOW_MANAGER_INFO() { \
{ \
{ "id", &ng_parse_hint32_type }, \
{ NULL }, \
} \
}
/*
* For netgraph nodes that are somehow associated with file descriptors
* (e.g., a device that has a /dev entry and is also a netgraph node),

View File

@ -153,7 +153,6 @@ static struct ng_type ng_mppc_typestruct = {
NULL,
NULL,
ng_mppc_rcvdata,
ng_mppc_rcvdata,
ng_mppc_disconnect,
NULL
};
@ -347,7 +346,7 @@ ng_mppc_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_mppc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;
@ -385,7 +384,9 @@ ng_mppc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
NGM_MPPC_RESETREQ, 0, M_NOWAIT);
if (msg == NULL)
return (error);
ng_send_msg(node, msg, priv->ctrlpath, NULL);
/* XXX can we use a hook instead of ctrlpath? */
ng_send_msg(node, msg, priv->ctrlpath,
NULL, NULL, NULL);
}
return (error);
}

View File

@ -172,7 +172,6 @@ static struct ng_type ng_one2many_typestruct = {
NULL,
NULL,
ng_one2many_rcvdata,
ng_one2many_rcvdata,
ng_one2many_disconnect,
ng_one2many_cmdlist,
};
@ -383,7 +382,7 @@ ng_one2many_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_one2many_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;

View File

@ -352,7 +352,6 @@ static struct ng_type ng_ppp_typestruct = {
NULL,
NULL,
ng_ppp_rcvdata,
ng_ppp_rcvdata,
ng_ppp_disconnect,
ng_ppp_cmds
};
@ -559,12 +558,15 @@ ng_ppp_rcvmsg(node_p node, struct ng_mesg *msg,
char path[NG_PATHLEN + 1];
node_p origNode;
if ((error = ng_path2node(node,
raddr, &origNode, NULL, NULL)) != 0)
if ((error = ng_path2node(node, raddr, &origNode, NULL)) != 0)
ERROUT(error);
snprintf(path, sizeof(path), "[%lx]:%s",
(long)node, NG_PPP_HOOK_VJC_IP);
return ng_send_msg(origNode, msg, path, rptr);
return ng_send_msg(origNode, msg, path, NULL, NULL, rptr);
/* XXX Archie, looks like you are using the wrong value for the ID here..
you can't use a node address as a node-ID any more..
But it may be that you can use the new 'hook' arg for ng_send_msg()
to achieve a more efficient resuld than an ID anyhow. */
}
default:
error = EINVAL;
@ -585,7 +587,7 @@ ng_ppp_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;
@ -781,9 +783,9 @@ ng_ppp_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
}
/* Send packet out hook */
NG_SEND_DATA_RET(error, outHook, m, meta);
NG_SEND_DATA_RET(error, outHook, m, meta, resp);
if (m != NULL || meta != NULL)
return ng_ppp_rcvdata(outHook, m, meta, NULL, NULL);
return ng_ppp_rcvdata(outHook, m, meta, NULL, NULL, resp);
return (error);
}

View File

@ -115,6 +115,13 @@ static const struct ng_cmdlist ng_pppoe_cmds[] = {
&ngpppoe_init_data_state_type,
NULL
},
{
NGM_PPPOE_COOKIE,
NGM_PPPOE_SERVICE,
"pppoe_service",
&ngpppoe_init_data_state_type,
NULL
},
{
NGM_PPPOE_COOKIE,
NGM_PPPOE_SUCCESS,
@ -151,7 +158,6 @@ static struct ng_type typestruct = {
NULL,
ng_pppoe_connect,
ng_pppoe_rcvdata,
ng_pppoe_rcvdata,
ng_pppoe_disconnect,
ng_pppoe_cmds
};
@ -524,10 +530,6 @@ AAA
* with a single reference for us.. we transfer it to the
* private structure.. when we free the private struct we must
* unref the node so it gets freed too.
*
* If this were a device node than this work would be done in the attach()
* routine and the constructor would return EINVAL as you should not be able
* to creatednodes that depend on hardware (unless you can add the hardware :)
*/
static int
ng_pppoe_constructor(node_p *nodep)
@ -561,6 +563,7 @@ AAA
* The following hook names are special:
* Ethernet: the hook that should be connected to a NIC.
* debug: copies of data sent out here (when I write the code).
* All other hook names need only be unique. (the framework checks this).
*/
static int
ng_pppoe_newhook(node_p node, hook_p hook, const char *name)
@ -618,6 +621,7 @@ AAA
case NGM_PPPOE_CONNECT:
case NGM_PPPOE_LISTEN:
case NGM_PPPOE_OFFER:
case NGM_PPPOE_SERVICE:
ourmsg = (struct ngpppoe_init_data *)msg->data;
if (msg->header.arglen < sizeof(*ourmsg)) {
printf("pppoe: init data too small\n");
@ -653,6 +657,14 @@ AAA
LEAVE(EINVAL);
}
sp = hook->private;
/*
* PPPOE_SERVICE advertisments are set up
* on sessions that are in PRIMED state.
*/
if (msg->header.cmd == NGM_PPPOE_SERVICE) {
break;
}
if (sp->state |= PPPOE_SNONE) {
printf("pppoe: Session already active\n");
LEAVE(EISCONN);
@ -735,7 +747,6 @@ AAA
* Store the originator of this message so we can send
* a success of fail message to them later.
* Move the hook to 'LISTENING'
*/
neg->service.hdr.tag_type = PTT_SRV_NAME;
neg->service.hdr.tag_len =
@ -771,6 +782,25 @@ AAA
*/
sp->state = PPPOE_PRIMED;
break;
case NGM_PPPOE_SERVICE:
/*
* Check the session is primed.
* for now just allow ONE service to be advertised.
* If you do it twice you just overwrite.
*/
if (sp->state |= PPPOE_PRIMED) {
printf("pppoe: Session not primed\n");
LEAVE(EISCONN);
}
neg->service.hdr.tag_type = PTT_SRV_NAME;
neg->service.hdr.tag_len =
htons((u_int16_t)ourmsg->data_len);
if (ourmsg->data_len)
bcopy(ourmsg->data, neg->service.data,
ourmsg->data_len);
neg->service_len = ourmsg->data_len;
break;
default:
LEAVE(EINVAL);
}
@ -828,7 +858,7 @@ AAA
*/
static int
ng_pppoe_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
node_p node = hook->node;
const priv_p privp = node->private;
@ -1268,10 +1298,20 @@ AAA
insert_tag(sp, &neg->ac_name.hdr); /* AC_NAME */
if ((tag = get_tag(ph, PTT_SRV_NAME)))
insert_tag(sp, tag); /* return service */
/*
* If we have a NULL service request
* and have an extra service defined in this hook,
* then also add a tag for the extra service.
* XXX this is a hack. eventually we should be able
* to support advertising many services, not just one
*/
if (((tag == NULL) || (tag->tag_len == 0))
&& (neg->service.hdr.tag_len != 0)) {
insert_tag(sp, &neg->service.hdr); /* SERVICE */
}
if ((tag = get_tag(ph, PTT_HOST_UNIQ)))
insert_tag(sp, tag); /* returned hostunique */
insert_tag(sp, &uniqtag.hdr);
/* XXX maybe put the tag in the session store */
scan_tags(sp, ph);
make_packet(sp);
sendpacket(sp);
@ -1583,8 +1623,10 @@ pppoe_send_event(sessp sp, enum cmd cmdid)
AAA
NG_MKMESSAGE(msg, NGM_PPPOE_COOKIE, cmdid,
sizeof(struct ngpppoe_sts), M_NOWAIT);
if (msg == NULL)
return (ENOMEM);
sts = (struct ngpppoe_sts *)msg->data;
strncpy(sts->hook, sp->hook->name, NG_HOOKLEN + 1);
error = ng_send_msg(sp->hook->node, msg, sp->creator, NULL);
error = ng_send_msg(sp->hook->node, msg, sp->creator, NULL, NULL, NULL);
return (error);
}

View File

@ -255,7 +255,6 @@ static struct ng_type ng_pptpgre_typestruct = {
NULL,
NULL,
ng_pptpgre_rcvdata,
ng_pptpgre_rcvdata,
ng_pptpgre_disconnect,
ng_pptpgre_cmdlist
};
@ -394,7 +393,7 @@ ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;

View File

@ -106,7 +106,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ng_rfc1490_rcvdata,
ng_rfc1490_rcvdata,
ng_rfc1490_disconnect,
NULL
};
@ -215,7 +214,7 @@ ng_rfc1490_rcvmsg(node_p node, struct ng_mesg *msg,
static int
ng_rfc1490_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = node->private;

View File

@ -65,7 +65,6 @@ static ng_shutdown_t ng_xxx_rmnode;
static ng_newhook_t ng_xxx_newhook;
static ng_connect_t ng_xxx_connect;
static ng_rcvdata_t ng_xxx_rcvdata; /* note these are both ng_rcvdata_t */
static ng_rcvdata_t ng_xxx_rcvdataq; /* note these are both ng_rcvdata_t */
static ng_disconnect_t ng_xxx_disconnect;
/* Parse type for struct ngxxxstat */
@ -107,7 +106,6 @@ static struct ng_type typestruct = {
NULL,
ng_xxx_connect,
ng_xxx_rcvdata,
ng_xxx_rcvdataq,
ng_xxx_disconnect,
ng_xxx_cmdlist
};
@ -318,34 +316,13 @@ ng_xxx_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
* if we use up this data or abort we must free BOTH of these.
*
* If we want, we may decide to force this data to be queued and reprocessed
* at the netgraph NETISR time. (at which time it will be entered using ng_xxx_rcvdataq().
* at the netgraph NETISR time.
* We would do that by setting the HK_QUEUE flag on our hook. We would do that
* in the connect() method.
*/
static int
ng_xxx_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
{
int dlci = -2;
if (hook->private) {
/*
* If it's dlci 1023, requeue it so that it's handled
* at a lower priority. This is how a node decides to
* defer a data message.
*/
dlci = ((struct XXX_hookinfo *) hook->private)->dlci;
if (dlci == 1023) {
return(ng_queue_data(hook->peer, m, meta));
}
}
return(ng_xxx_rcvdataq(hook, m, meta));
}
/*
* Always accept the data. This version of rcvdata is called from the dequeueing routine.
*/
static int
ng_xxx_rcvdataq(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const xxx_p xxxp = hook->node->private;
int chan = -2;
@ -362,7 +339,7 @@ ng_xxx_rcvdataq(hook_p hook, struct mbuf *m, meta_p meta,
* the front here */
/* M_PREPEND(....) ; */
/* mtod(m, xxxxxx)->dlci = dlci; */
error = ng_send_data(xxxp->downstream_hook.hook,
NG_SEND_DATA(error, xxxp->downstream_hook.hook,
m, meta);
xxxp->packets_out++;
} else {
@ -406,13 +383,15 @@ ng_xxx_rcvdataq(hook_p hook, struct mbuf *m, meta_p meta,
*/
devintr()
{
meta_p meta = NULL; /* whatever metadata we might imagine goes
int error;
* here */
/* get packet from device and send on */
m = MGET(blah blah)
error = ng_queueit(upstream, m, meta); /* see note above in
* xxx_rcvdata() */
NG_SEND_DATA_ONLY(error, xxxp->upstream_hook.hook, m);
/* see note above in xxx_rcvdata() */
/* and ng_xxx_connect() */
}
#endif /* 0 */
@ -449,7 +428,35 @@ ng_xxx_rmnode(node_p node)
static int
ng_xxx_connect(hook_p hook)
{
/* be really amiable and just say "YUP that's OK by me! " */
#if 0
/*
* If we were a driver running at other than splnet then
* we should set the QUEUE bit on the edge so that we
* will deliver by queing.
*/
if /*it is the upstream hook */
hook->peer->flags |= HK_QUEUE;
#endif
#if 0
/*
* If for some reason we want incoming date to be queued
* by the NETISR system and delivered later we can set the same bit on
* OUR hook. (maybe to allow unwinding of the stack)
*/
if (hook->private) {
int dlci;
/*
* If it's dlci 1023, requeue it so that it's handled
* at a lower priority. This is how a node decides to
* defer a data message.
*/
dlci = ((struct XXX_hookinfo *) hook->private)->dlci;
if (dlci == 1023) {
hook->flags |= HK_QUEUE;
}
#endif
/* otherwise be really amiable and just say "YUP that's OK by me! " */
return (0);
}

View File

@ -130,7 +130,6 @@ static struct ng_type typestruct = {
NULL,
NULL,
ngs_rcvdata,
ngs_rcvdata,
ngs_disconnect,
NULL
};
@ -239,7 +238,7 @@ ngc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
/* The callee will free the msg when done. The addr is our business. */
error = ng_send_msg(pcbp->sockdata->node,
(struct ng_mesg *) msg, path, &resp);
(struct ng_mesg *) msg, path, NULL, NULL, &resp);
/* If the callee responded with a synchronous response, then put it
* back on the receive side of the socket; sap is source address. */
@ -307,7 +306,6 @@ ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
{
struct ngpcb *const pcbp = sotongpcb(so);
struct sockaddr_ng *const sap = (struct sockaddr_ng *) addr;
meta_p mp = NULL;
int len, error;
hook_p hook = NULL;
char hookname[NG_HOOKLEN + 1];
@ -359,7 +357,7 @@ ngd_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
}
/* Send data (OK if hook is NULL) */
NG_SEND_DATA(error, hook, m, mp); /* makes m NULL */
NG_SEND_DATA_ONLY(error, hook, m); /* makes m NULL */
release:
if (control != NULL)
@ -394,7 +392,7 @@ ng_setsockaddr(struct socket *so, struct sockaddr **addr)
s = splnet();
pcbp = sotongpcb(so);
if (pcbp == 0) {
if ((pcbp == NULL) || (pcbp->sockdata == NULL)) {
splx(s);
return (EINVAL);
}
@ -608,7 +606,7 @@ ng_connect_data(struct sockaddr *nam, struct ngpcb *pcbp)
/* Find the target (victim) and check it doesn't already have a data
* socket. Also check it is a 'socket' type node. */
sap = (struct sockaddr_ng *) nam;
if ((error = ng_path2node(NULL, sap->sg_data, &farnode, NULL, NULL)))
if ((error = ng_path2node(NULL, sap->sg_data, &farnode, NULL)))
return (error);
if (strcmp(farnode->type->name, NG_SOCKET_NODE_TYPE) != 0)
@ -668,7 +666,10 @@ ng_bind(struct sockaddr *nam, struct ngpcb *pcbp)
TRAP_ERROR;
return (EINVAL);
}
if (sap->sg_len < 3 || sap->sg_data[sap->sg_len - 3] != '\0') {
if ((sap->sg_len < 4)
|| (sap->sg_len > (NG_NODELEN + 3))
|| (sap->sg_data[0] == '\0')
|| (sap->sg_data[sap->sg_len - 3] != '\0')) {
TRAP_ERROR;
return (EINVAL);
}
@ -792,7 +793,7 @@ ngs_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ngs_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
struct ngsock *const sockdata = hook->node->private;
struct ngpcb *const pcbp = sockdata->datasock;

View File

@ -138,7 +138,6 @@ static struct ng_type ng_tee_typestruct = {
NULL,
NULL,
ngt_rcvdata,
ngt_rcvdata,
ngt_disconnect,
ng_tee_cmds
};
@ -275,7 +274,7 @@ ngt_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
*/
static int
ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const sc_p sc = hook->node->private;
struct hookinfo *const hinfo = (struct hookinfo *) hook->private;

View File

@ -134,6 +134,7 @@ static ng_constructor_t ngt_constructor;
static ng_rcvmsg_t ngt_rcvmsg;
static ng_shutdown_t ngt_shutdown;
static ng_newhook_t ngt_newhook;
static ng_connect_t ngt_connect;
static ng_rcvdata_t ngt_rcvdata;
static ng_disconnect_t ngt_disconnect;
static int ngt_mod_event(module_t mod, int event, void *data);
@ -166,8 +167,7 @@ static struct ng_type typestruct = {
ngt_shutdown,
ngt_newhook,
NULL,
NULL,
ngt_rcvdata,
ngt_connect,
ngt_rcvdata,
ngt_disconnect,
NULL
@ -394,7 +394,7 @@ ngt_input(int c, struct tty *tp)
/* Ship off mbuf if it's time */
if (sc->hotchar == -1 || c == sc->hotchar || m->m_len >= MHLEN) {
m->m_data = m->m_pktdat;
error = ng_queue_data(sc->hook, m, NULL);
NG_SEND_DATA_ONLY(error, sc->hook, m);
sc->m = NULL;
}
done:
@ -520,6 +520,16 @@ ngt_newhook(node_p node, hook_p hook, const char *name)
return (error);
}
/*
* set the hooks into queueing mode (for outgoing packets)
*/
static int
ngt_connect(hook_p hook)
{
hook->peer->flags |= HK_QUEUE;
return (0);
}
/*
* Disconnect the hook
*/
@ -567,7 +577,7 @@ ngt_shutdown(node_p node)
*/
static int
ngt_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const sc_p sc = hook->node->private;
int s, error = 0;

View File

@ -232,7 +232,6 @@ static struct ng_type ng_vjc_typestruct = {
NULL,
NULL,
ng_vjc_rcvdata,
ng_vjc_rcvdata,
ng_vjc_disconnect,
ng_vjc_cmds
};
@ -412,7 +411,7 @@ ng_vjc_rcvmsg(node_p node, struct ng_mesg *msg,
*/
static int
ng_vjc_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
const node_p node = hook->node;
const priv_p priv = (priv_p) node->private;

View File

@ -497,7 +497,7 @@ mn_fmt_ts(char *p, u_int32_t ts)
static int
ngmn_rcvdata(hook_p hook, struct mbuf *m, meta_p meta,
struct mbuf **ret_m, meta_p *ret_meta)
struct mbuf **ret_m, meta_p *ret_meta, struct ng_mesg **resp)
{
struct mbuf *m2;
struct trxd *dp, *dp2;
@ -653,6 +653,8 @@ ngmn_connect(hook_p hook)
if (!(u & 1))
printf("%s: init chan %d stat %08x\n", sc->name, chan, u);
sc->m32x->stat = 1;
/* probably not at splnet, force outward queueing */
hook->peer->flags |= HK_QUEUE;
return (0);
}
@ -1030,9 +1032,9 @@ mn_rx_intr(struct softc *sc, u_int32_t vector)
m->m_pkthdr.len = m->m_len = (dp->status >> 16) & 0x1fff;
err = (dp->status >> 8) & 0xff;
if (!err) {
ng_queue_data(sch->hook, m, NULL);
int error;
NG_SEND_DATA_ONLY(error, sch->hook, m);
sch->last_recv = time_second;
m = 0;
/* we could be down by now... */
if (sch->state != UP)
return;