File:  [DragonFly] / src / sys / net / netisr.c
Revision 1.14: download - view: text, annotated - select for diffs
Wed Apr 21 18:13:51 2004 UTC (10 years, 3 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Fix a netmsg memory leak in the ARP code.  Adjust all ms_cmd function
dispatches to return a proper error code.

Reported-by: multiple people

    1: /*-
    2:  * Copyright (c) 2003 Jeffrey Hsu
    3:  * Copyright (c) 2003 Jonathan Lemon
    4:  * Copyright (c) 2003 Matthew Dillon
    5:  *
    6:  * $DragonFly: src/sys/net/netisr.c,v 1.14 2004/04/21 18:13:51 dillon Exp $
    7:  */
    8: 
    9: #include <sys/param.h>
   10: #include <sys/systm.h>
   11: #include <sys/kernel.h>
   12: #include <sys/malloc.h>
   13: #include <sys/msgport.h>
   14: #include <sys/proc.h>
   15: #include <sys/interrupt.h>
   16: #include <sys/socket.h>
   17: #include <sys/sysctl.h>
   18: #include <net/if.h>
   19: #include <net/if_var.h>
   20: #include <net/netisr.h>
   21: #include <machine/cpufunc.h>
   22: #include <machine/ipl.h>
   23: 
   24: #include <sys/thread2.h>
   25: #include <sys/msgport2.h>
   26: 
   27: static struct netisr netisrs[NETISR_MAX];
   28: 
   29: /* Per-CPU thread to handle any protocol.  */
   30: struct thread netisr_cpu[MAXCPU];
   31: lwkt_port netisr_afree_rport;
   32: 
   33: /*
   34:  * netisr_afree_rport replymsg function, only used to handle async
   35:  * messages which the sender has abandoned to their fate.
   36:  */
   37: static void
   38: netisr_autofree_reply(lwkt_port_t port, lwkt_msg_t msg)
   39: {
   40:     free(msg, M_LWKTMSG);
   41: }
   42: 
   43: static void
   44: netisr_init(void)
   45: {
   46:     int i;
   47: 
   48:     /* Create default per-cpu threads for generic protocol handling. */
   49:     for (i = 0; i < ncpus; ++i) {
   50: 	lwkt_create(netmsg_service_loop, NULL, NULL, &netisr_cpu[i], 0, i,
   51: 	    "netisr_cpu %d", i);
   52:     }
   53:     lwkt_initport(&netisr_afree_rport, NULL);
   54:     netisr_afree_rport.mp_replyport = netisr_autofree_reply;
   55: }
   56: 
   57: SYSINIT(netisr, SI_SUB_PROTO_BEGIN, SI_ORDER_FIRST, netisr_init, NULL);
   58: 
   59: void
   60: netmsg_service_loop(void *arg)
   61: {
   62:     struct netmsg *msg;
   63: 
   64:     while ((msg = lwkt_waitport(&curthread->td_msgport, NULL)))
   65: 	msg->nm_lmsg.ms_cmd.cm_func(&msg->nm_lmsg);
   66: }
   67: 
   68: /*
   69:  * Call the netisr directly.
   70:  * Queueing may be done in the msg port layer at its discretion.
   71:  */
   72: void
   73: netisr_dispatch(int num, struct mbuf *m)
   74: {
   75:     /* just queue it for now XXX JH */
   76:     netisr_queue(num, m);
   77: }
   78: 
   79: /*
   80:  * Same as netisr_dispatch(), but always queue.
   81:  * This is either used in places where we are not confident that
   82:  * direct dispatch is possible, or where queueing is required.
   83:  */
   84: int
   85: netisr_queue(int num, struct mbuf *m)
   86: {
   87:     struct netisr *ni;
   88:     struct netmsg_packet *pmsg;
   89:     lwkt_port_t port;
   90: 
   91:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
   92: 	("netisr_queue: bad isr %d", num));
   93: 
   94:     ni = &netisrs[num];
   95:     if (ni->ni_handler == NULL) {
   96: 	printf("netisr_queue: unregistered isr %d\n", num);
   97: 	return (EIO);
   98:     }
   99: 
  100:     if (!(port = ni->ni_mport(m)))
  101: 	return (EIO);
  102: 
  103:     /* use better message allocation system with limits later XXX JH */
  104:     pmsg = malloc(sizeof(struct netmsg_packet), M_LWKTMSG, M_WAITOK);
  105: 
  106:     lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
  107: 		lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
  108:     pmsg->nm_packet = m;
  109:     lwkt_sendmsg(port, &pmsg->nm_lmsg);
  110:     return (0);
  111: }
  112: 
  113: void
  114: netisr_register(int num, lwkt_portfn_t mportfn, netisr_fn_t handler)
  115: {
  116:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
  117: 	("netisr_register: bad isr %d", num));
  118: 
  119:     netisrs[num].ni_mport = mportfn;
  120:     netisrs[num].ni_handler = handler;
  121: }
  122: 
  123: int
  124: netisr_unregister(int num)
  125: {
  126:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
  127: 	("unregister_netisr: bad isr number: %d\n", num));
  128: 
  129:     /* XXX JH */
  130:     return (0);
  131: }
  132: 
  133: /*
  134:  * Return message port for default handler thread on CPU 0.
  135:  */
  136: lwkt_port_t
  137: cpu0_portfn(struct mbuf *m)
  138: {
  139:     return (&netisr_cpu[0].td_msgport);
  140: }
  141: 
  142: /* ARGSUSED */
  143: lwkt_port_t
  144: cpu0_soport(struct socket *so __unused, struct sockaddr *nam __unused)
  145: {
  146:     return (&netisr_cpu[0].td_msgport);
  147: }
  148: 
  149: /*
  150:  * This function is used to call the netisr handler from the appropriate
  151:  * netisr thread for polling and other purposes.
  152:  */
  153: void
  154: schednetisr(int num)
  155: {
  156:     struct netisr *ni = &netisrs[num];
  157:     struct netmsg *pmsg;
  158:     lwkt_port_t port = &netisr_cpu[0].td_msgport;
  159: 
  160:     KASSERT((num > 0 && num <= (sizeof(netisrs)/sizeof(netisrs[0]))),
  161: 	("schednetisr: bad isr %d", num));
  162: 
  163:     pmsg = malloc(sizeof(struct netmsg), M_LWKTMSG, M_NOWAIT);
  164:     if (pmsg) {
  165: 	lwkt_initmsg(&pmsg->nm_lmsg, &netisr_afree_rport, 0,
  166: 		    lwkt_cmd_func((void *)ni->ni_handler), lwkt_cmd_op_none);
  167: 	lwkt_sendmsg(port, &pmsg->nm_lmsg);
  168:     }
  169: }