NetBSD port of the freebsd netgraph modules (taken from FreeBSD 4.3 tree) ------------------------------------------------------------------------- Barnim Dzwillo / jun 2001 Install: ------- The target platform is currently a i386 machine running the netbsd-current version 'NetBSD 1.5V (GENERIC_VMWARE)' (end of april'01). Most of the development is done under a vmware environment (conf file included), but the netgraph environment was also tested on real PC's and on powerpc embedded systems. There are very few changes to the netbsd core to add netgraph to the kernel, so it should be easy to add it to other netbsd versions. The port consists of the subtree located under 'src' containing the new files which have to be added to the kernel, and of some patchfiles in the 'patches' directory, which have to be applied to the existing kernel files. If NGPATH is the netgraph-patch-dir and NETBSD is the netbsd src-tree call: - 'cp -ri NGPATH/src NETBSD/usr/src' - 'patch -p0 NGPATH/patches/patch-*' in the NETBSD/usr/src directory This is currently a direct port of the freebsd netgraph modules without major changes, so most of the freebsd documentation should also apply to this port. (see: http://www.daemonnews.org/200003/netgraph.html and the man pages under sys/lkm/netgraph/* ) Some differences: ---------------- - Dynamic loading of netgraph modules doesn't work from kernel space, because the API's are missing. - It is necessary that the netgraph base functions (ng_base/ng_parse/ng_socket) are compiled into the kernel, because there is no way to share symbols between different LKM's under NetBSD (AFAIK). - To compile more netgraph into the kernel, the appropiate option has to be added to the kernel configuration file (see: "netgraph*" in sys/conf/files and "NETGRAPH*" in sys/arch/i386/conf/GENERIC_VMWARE) - It is possible to compile most of the netgraph modules as LKM and load/unload them from user level. ('make' in sys/lkm/netgraph) Dynamic loading/unloading of netgraph modules from userspace is done by calling 'make load'/'make unload' in the sys/lkm/netgraph/* subdirectories. (see also: ngload shell script) - The ether module uses currently the pfil-kernel-interface instead of the handmade hooks under freebsd. For that reason it is not possible to hook the ethernet interfaces from the 'upper' and 'lower' side at the same time (but is this really necessary?). - only the initial interfaces are currently monitored (no if_ethersubr attach/detach hook) - the ethernet module can't get unloaded (ref_cnt) until all attached interfaces are brought down. - All the sourcecode for the netgraph kernel modules is located under ../sys/netgraph in the NetBSD kernel source tree. The makefiles to compile single modules as LKM are located in ../sys/lkm/netgraph subtree. - All differences tagged with '#if defined(__NetBSD__)' for C code or '.if ${OSTYPE} == "netbsd"' for the makefiles. - All but the ng_bridge module compile unter NetBSD. This one was removed from the Makefile. Major porting issues: -------------------- - kernel socket API differences - ethernet hooking - protocol pr_usrreq vs. usrreq() - module interface vs. LKM interface - splnet/imp() vs. splsoftnet/splnet() - KASSERT - if_name/unit vs. if_xname - callout API vs. timeout/untimeout() - linesw struct issues for ng_tty Files: ----- - sys/sys/socket.h: AF_NETGRAPH - sys/lib/libkern/arch/i386/Makefile.inc: strtol.c stroul.c strtoq.c qsort.c - sys/lib/libkern/libkern.h: stroul.c strtoq.c qsort.c - sys/lib/libkern/strtol.c - sys/lib/libkern/strtoul.c - sys/lib/libkern/strtoq.c - sys/lib/libkern/qsort.c (for ng_ppp) - sys/kern/uipc_domain.c: ADDDOMAIN(netgraph) - sys/net/netisr.h: NETISR_NETGRAPH - sys/net/netisr_dispatch.h: DONETISR(NETISR_NETGRAPH,ngintr) - sys/conf/files: ng_base.c ng_parse.c ng_socket.c (for netgraph) - sys/arch/i386/conf/VMWARE_GENERIC: options NETGRAPH - sys/netgraph/* - sys/Makefile: netgraph netgraph_socket .. - sys/sys/ttycom.h: NETGRAPHDISC (for ng_tty) - sys/sys/lkm/Makefile - sys/sys/lkm/netgraph - lib/Makefile - lib/libnetgraph - usr.sbin/Makefile - usr.sbin/ngctl - usr.sbin/nghook Some working test cases: ----------------------- - The ngctl tool is used to setup a graph of a ksocket-node connected to an echo-node. The nodes are connected via an inet/dgram/udp hook which is bound & connected to a fixed ip-address. Each incoming udp-packet is echoed correctly back, if the bind & connect addresses of the sender match. Example for remote system with ip 10.1.1.1: > mkpeer echo dummy ldummy > name .:dummy lnode > mkpeer lnode: ksocket lhook inet/dgram/udp > msg lnode:lhook bind inet/0.0.0.0:4028 > msg lnode:lhook connect inet/10.1.1.1:4028 and to free resources: > shutdown lnode: TESTS: - ngctl, libnetgraph, ng_socket, ng_ksocket, ng_echo - The nghook tool is used to control an ethernet interface and dump each packet (avoid to use the interface which is used by the tty). - just load ng_ether TESTS: - nghook, libnetgraph, ng_socket, ng_ether - The ngctl tool is used to setup a point-to-point interface node on top of a ksocket udp node. This is used to tunnel packets (encapsulated in udp) between two hosts with such a configured interface. (see: http://www.daemonnews.org/200003/netgraph.html) Example for tunnel (1.1.1.0 <-> 1.1.2.0) over remote system with ip 10.1.1.1: > ngctl mkpeer iface dummy inet > ngctl msg ng0:inet bind inet/0.0.0.0:4028 > ngctl msg ng0:inet connect inet/10.1.1.1:4028 > ifconfig ng0 1.1.1.1 1.1.2.1 netmask 255.255.255.0 > route add -net 1.1.2.0 1.1.2.1 -iface to free resources: > ifconfig ng0 inet down delete > ngctl shutdown ng0: ping is not possible on a point-to-point interface, use other proto's TESTS: - ngctl, libnetgraph, ng_iface, ng_ksocket Possible TODO's: --------------- - Provide a generic mechanism for implicit flow control -> a module might add a flow-control-queue to a hook -> to allow flow-control transiting intermediate filter nodes, add a mechanism to define a relation between 'upper' and 'lower' nodes for non queueing nodes. (a.e: for simple non queuing 'filter' nodes with just one hook at each end, this might be completely hidden by a flag in the node struct -> like streams modules) -> make flow control available to applications via the ng_socket node -> is it necessary to keep the current global queue? -> perhaps try to make this behave similar to streams. - Check if it is really necessary to pass an extra meta data pointer for each mbuf (This is still labeled as experimental). Check if it is possible to use control mbuf's instead - Implement get/set operations in a way similar to getsockopt()/setsockopt() or ioctl (avoid to use different commands for get & set operation). - Remove the ascii message mode from the kernel (strings should still be available to an application via header files -> like sysctl()) - Is it really necessary to have a separate control & data socket instead of a single socket? (Control messages could be passed via getsockopt/setsockopt() or the cmsghdr part of sendmsg/recvmsg()). - Is it valuable to implement the netgraph modules as pluggable protocol modules, using struct protosw & PRU_XXX statements instead of ng_type? - There should be a way to create an instance of a module without a connection to a hook (mkpeer) - it could be somehow impractical to have dummy hook's just for that purpose. - When it comes to performance it could be better to translate paths (and hook-names?) only once into ID's and do all communication between netgraph nodes via these ID's.