Date: Mon, 18 Jan 1999 22:07:09 -0800 (PST) From: Julian Elischer <julian@whistle.com> To: Christian Kuhtz <ck@adsu.bellsouth.com> Cc: hackers@FreeBSD.ORG Subject: Re: protocol implementation Message-ID: <Pine.BSF.3.95.990118213616.9336B-100000@current1.whistle.com> In-Reply-To: <19990119000654.K5878@oreo.adsu.bellsouth.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 19 Jan 1999, Christian Kuhtz wrote: > > Hello: > > I am in the process of coding a new protocol stack and it is time to start > mating the higher layers to media access layer. > > The question is: How is this done best in FreeBSD? Each media-type driver needs to know how to detect that protocol. e,g for ethernet, the file if_ethersubr.c needs to be modified so that incoming packets of your protocol are recognised. The output routine there needs to know about your sockaddr type so that it can encode it witht eh right header before sending it. This is the only place where you need to actually edit code. The very existance of (your equivalent of) the following code will create the linkages needed fo rth ekernel to find your protocol stack from the socket end of things. (this is taken from some code here) Thisimplements a protocol family woth two different sub-protocols (e.g similar to udp and tcp as sub protocols of the ip family) /* * Control and data socket type descriptors */ static struct pr_usrreqs ngc_usrreqs = { NULL, /* abort */ pru_accept_notsupp, ngc_attach, ngc_bind, ngc_connect, pru_connect2_notsupp, pru_control_notsupp, ngc_detach, NULL, /* disconnect */ pru_listen_notsupp, NULL, /* setpeeraddr */ pru_rcvd_notsupp, pru_rcvoob_notsupp, ngc_send, pru_sense_null, NULL, /* shutdown */ ng_setsockaddr, sosend, soreceive, sopoll }; static struct pr_usrreqs ngd_usrreqs = { NULL, /* abort */ pru_accept_notsupp, ngd_attach, NULL, /* bind */ ngd_connect, pru_connect2_notsupp, pru_control_notsupp, ngd_detach, NULL, /* disconnect */ pru_listen_notsupp, NULL, /* setpeeraddr */ pru_rcvd_notsupp, pru_rcvoob_notsupp, ngd_send, pru_sense_null, NULL, /* shutdown */ ng_setsockaddr, sosend, soreceive, sopoll }; /* * Definitions of protocols supported in the NETGRAPH domain. */ extern struct domain ngdomain; /* stop compiler warnings */ static struct protosw ngsw[] = { { SOCK_DGRAM, &ngdomain, NG_CONTROL, PR_ATOMIC | PR_ADDR | PR_RIGHTS, 0, 0, 0, 0, NULL, 0, 0, 0, 0, &ngc_usrreqs }, { SOCK_DGRAM, &ngdomain, NG_DATA, PR_ATOMIC | PR_ADDR, 0, 0, 0, 0, NULL, 0, 0, 0, 0, &ngd_usrreqs } }; struct domain ngdomain = { AF_NETGRAPH, "netgraph", 0, NULL, NULL, ngsw, &ngsw[sizeof(ngsw) / sizeof(ngsw[0])], 0, NULL, 0, 0 }; DOMAIN_SET(ng); In addition you need to add code to link in your ISR code. Once again here is our version of that code.. alter to taste.. /* * Pick an item off the queue, process it, and dispose of the queue entry. * Should be running at splnet. */ static void ngintr(void) { hook_p hook; struct ng_queue_entry *ngq; struct mbuf *m; meta_p meta; void *retaddr; struct ng_mesg *msg; node_p node; int error = 0; int s; while (1) { s = splhigh(); if ((ngq = ngqbase)) { ngqbase = ngq->next; ngqsize--; } splx(s); if (ngq == NULL) return; switch (ngq->flags) { case NGQF_DATA: hook = ngq->body.data.da_hook; m = ngq->body.data.da_m; meta = ngq->body.data.da_meta; RETURN_QBLK(ngq); NG_SEND_DATA(error, hook, m, meta); ng_unref_hook(hook); break; case NGQF_MESG: node = ngq->body.msg.msg_node; msg = ngq->body.msg.msg_msg; retaddr = ngq->body.msg.msg_retaddr; RETURN_QBLK(ngq); if (node->flags & NG_INVALID) { FREE(msg, M_NETGRAPH); } else { CALL_MSG_HANDLER(error, node, msg, retaddr, NULL); } ng_unref(node); if (retaddr) FREE(retaddr, M_NETGRAPH); break; default: RETURN_QBLK(ngq); } } } NETISR_SET(NETISR_NG, ngintr); Once again.. the very inclusion of this code links itself in on linking. the trick is the NETISR_SET macro. This code uses our own queue, and is queuing structures wich point to the mbufs. You would but probably use a normal interface queue as you will see in if_ethersubr.c and ipintr() (ip_input.c from memory) instead, and queue the mbufs directly usinghte IF_QUEUE() macro. (and it's friends). (IF_DEQUEUE()) The code snippet for queing the packets is as follows.. this is run in the driver code, where the code above is in the protocol stack and recieves the packets. /* queue the data for packup by hte protocol stack */ s = splhigh(); if (ngqbase) { ngqlast->next = q; } else { ngqbase = q; } ngqlast = q; ngqsize++; splx(s); /* Schedule software interrupt to handle it later */ schednetisr(NETISR_NG); > > The stack components are coded as klds. And I need to be able to create > frames on the Ethernet (which is the primary media target, but not > exclusively) and pick up frames. The system will run IP and well as this > new stack in parallel. Unfortunatly, at this time you can't add a protocol entirely by KLD, as you still need to change in-line code in if_ethersubr.c that is being worked on, but may take a while to coome to light. julian > > Can somebody shed some light on this? > > Thanks in advance, > Chris > > -- > "We are not bound by any concept, we are just bound to make any concept work > better than others." -- Dr. Ferry Porsche > > [Disclaimer: I speak for myself and my views are my own and not in any way to > be construed as the views of BellSouth Corporation. ] > > To Unsubscribe: send mail to majordomo@FreeBSD.org > with "unsubscribe freebsd-hackers" in the body of the message > To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95.990118213616.9336B-100000>