From owner-svn-src-all@FreeBSD.ORG Sat May 23 16:51:14 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 32B1C106566C; Sat, 23 May 2009 16:51:14 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1EEFD8FC15; Sat, 23 May 2009 16:51:14 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4NGpELp061179; Sat, 23 May 2009 16:51:14 GMT (envelope-from bz@svn.freebsd.org) Received: (from bz@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4NGpDtI061174; Sat, 23 May 2009 16:51:13 GMT (envelope-from bz@svn.freebsd.org) Message-Id: <200905231651.n4NGpDtI061174@svn.freebsd.org> From: "Bjoern A. Zeeb" Date: Sat, 23 May 2009 16:51:13 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r192649 - in head/sys: netinet netinet6 sys X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 23 May 2009 16:51:14 -0000 Author: bz Date: Sat May 23 16:51:13 2009 New Revision: 192649 URL: http://svn.freebsd.org/changeset/base/192649 Log: Implement UDP control block support. So far the udp_tun_func_t had been (ab)using inp_ppcb for udp in kernel tunneling callbacks. Move that into the udpcb and add a field for flags there to be used by upcoming changes instead of sticking udp only flags into in_pcb flags2. Bump __FreeBSD_version for ports to detect it and because of vnet* struct size changes. Submitted by: jhb (7.x version) Reviewed by: rwatson Modified: head/sys/netinet/udp_usrreq.c head/sys/netinet/udp_var.h head/sys/netinet/vinet.h head/sys/netinet6/udp6_usrreq.c head/sys/sys/param.h Modified: head/sys/netinet/udp_usrreq.c ============================================================================== --- head/sys/netinet/udp_usrreq.c Sat May 23 16:42:38 2009 (r192648) +++ head/sys/netinet/udp_usrreq.c Sat May 23 16:51:13 2009 (r192649) @@ -137,6 +137,7 @@ SYSCTL_ULONG(_net_inet_udp, UDPCTL_RECVS #ifdef VIMAGE_GLOBALS struct inpcbhead udb; /* from udp_var.h */ struct inpcbinfo udbinfo; +static uma_zone_t udpcb_zone; struct udpstat udpstat; /* from udp_var.h */ #endif @@ -158,6 +159,7 @@ udp_zone_change(void *tag) INIT_VNET_INET(curvnet); uma_zone_set_max(V_udbinfo.ipi_zone, maxsockets); + uma_zone_set_max(V_udpcb_zone, maxsockets); } static int @@ -187,13 +189,39 @@ udp_init(void) &V_udbinfo.ipi_hashmask); V_udbinfo.ipi_porthashbase = hashinit(UDBHASHSIZE, M_PCB, &V_udbinfo.ipi_porthashmask); - V_udbinfo.ipi_zone = uma_zcreate("udpcb", sizeof(struct inpcb), NULL, - NULL, udp_inpcb_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); + V_udbinfo.ipi_zone = uma_zcreate("udp_inpcb", sizeof(struct inpcb), + NULL, NULL, udp_inpcb_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); uma_zone_set_max(V_udbinfo.ipi_zone, maxsockets); + + V_udpcb_zone = uma_zcreate("udpcb", sizeof(struct udpcb), + NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE); + uma_zone_set_max(V_udpcb_zone, maxsockets); + EVENTHANDLER_REGISTER(maxsockets_change, udp_zone_change, NULL, EVENTHANDLER_PRI_ANY); } +int +udp_newudpcb(struct inpcb *inp) +{ + INIT_VNET_INET(curvnet); + struct udpcb *up; + + up = uma_zalloc(V_udpcb_zone, M_NOWAIT | M_ZERO); + if (up == NULL) + return (ENOBUFS); + inp->inp_ppcb = up; + return (0); +} + +void +udp_discardcb(struct udpcb *up) +{ + INIT_VNET_INET(curvnet); + + uma_zfree(V_udpcb_zone, up); +} + /* * Subroutine of udp_input(), which appends the provided mbuf chain to the * passed pcb/socket. The caller must provide a sockaddr_in via udp_in that @@ -272,6 +300,7 @@ udp_input(struct mbuf *m, int off) struct udphdr *uh; struct ifnet *ifp; struct inpcb *inp; + struct udpcb *up; int len; struct ip save_ip; struct sockaddr_in udp_in; @@ -455,28 +484,25 @@ udp_input(struct mbuf *m, int off) struct mbuf *n; n = m_copy(m, 0, M_COPYALL); - if (last->inp_ppcb == NULL) { + up = intoudpcb(last); + if (up->u_tun_func == NULL) { if (n != NULL) udp_append(last, ip, n, iphlen + sizeof(struct udphdr), &udp_in); - INP_RUNLOCK(last); } else { /* * Engage the tunneling protocol we * will have to leave the info_lock * up, since we are hunting through * multiple UDP's. - * */ - udp_tun_func_t tunnel_func; - tunnel_func = (udp_tun_func_t)last->inp_ppcb; - tunnel_func(n, iphlen, last); - INP_RUNLOCK(last); + (*up->u_tun_func)(n, iphlen, last); } + INP_RUNLOCK(last); } last = inp; /* @@ -501,22 +527,18 @@ udp_input(struct mbuf *m, int off) UDPSTAT_INC(udps_noportbcast); goto badheadlocked; } - if (last->inp_ppcb == NULL) { + up = intoudpcb(last); + if (up->u_tun_func == NULL) { udp_append(last, ip, m, iphlen + sizeof(struct udphdr), &udp_in); - INP_RUNLOCK(last); - INP_INFO_RUNLOCK(&V_udbinfo); } else { /* * Engage the tunneling protocol. */ - udp_tun_func_t tunnel_func; - - tunnel_func = (udp_tun_func_t)last->inp_ppcb; - tunnel_func(m, iphlen, last); - INP_RUNLOCK(last); - INP_INFO_RUNLOCK(&V_udbinfo); + (*up->u_tun_func)(m, iphlen, last); } + INP_RUNLOCK(last); + INP_INFO_RUNLOCK(&V_udbinfo); return; } @@ -560,18 +582,16 @@ udp_input(struct mbuf *m, int off) INP_RUNLOCK(inp); goto badunlocked; } - if (inp->inp_ppcb != NULL) { + up = intoudpcb(inp); + if (up->u_tun_func == NULL) { + udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in); + } else { /* * Engage the tunneling protocol. */ - udp_tun_func_t tunnel_func; - tunnel_func = (udp_tun_func_t)inp->inp_ppcb; - tunnel_func(m, iphlen, inp); - INP_RUNLOCK(inp); - return; + (*up->u_tun_func)(m, iphlen, inp); } - udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in); INP_RUNLOCK(inp); return; @@ -1142,18 +1162,19 @@ udp_attach(struct socket *so, int proto, } inp = (struct inpcb *)so->so_pcb; - INP_INFO_WUNLOCK(&V_udbinfo); inp->inp_vflag |= INP_IPV4; inp->inp_ip_ttl = V_ip_defttl; - /* - * UDP does not have a per-protocol pcb (inp->inp_ppcb). - * We use this pointer for kernel tunneling pointer. - * If we ever need to have a protocol block we will - * need to move this function pointer there. Null - * in this pointer means "do the normal thing". - */ - inp->inp_ppcb = NULL; + + error = udp_newudpcb(inp); + if (error) { + in_pcbdetach(inp); + in_pcbfree(inp); + INP_INFO_WUNLOCK(&V_udbinfo); + return (error); + } + INP_WUNLOCK(inp); + INP_INFO_WUNLOCK(&V_udbinfo); return (0); } @@ -1161,24 +1182,26 @@ int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f) { struct inpcb *inp; + struct udpcb *up; - inp = (struct inpcb *)so->so_pcb; KASSERT(so->so_type == SOCK_DGRAM, ("udp_set_kernel_tunneling: !dgram")); KASSERT(so->so_pcb != NULL, ("udp_set_kernel_tunneling: NULL inp")); if (so->so_type != SOCK_DGRAM) { /* Not UDP socket... sorry! */ return (ENOTSUP); } + inp = (struct inpcb *)so->so_pcb; if (inp == NULL) { /* NULL INP? */ return (EINVAL); } INP_WLOCK(inp); - if (inp->inp_ppcb != NULL) { + up = intoudpcb(inp); + if (up->u_tun_func != NULL) { INP_WUNLOCK(inp); return (EBUSY); } - inp->inp_ppcb = f; + up->u_tun_func = f; INP_WUNLOCK(inp); return (0); } @@ -1256,6 +1279,7 @@ udp_detach(struct socket *so) { INIT_VNET_INET(so->so_vnet); struct inpcb *inp; + struct udpcb *up; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp_detach: inp == NULL")); @@ -1263,9 +1287,13 @@ udp_detach(struct socket *so) ("udp_detach: not disconnected")); INP_INFO_WLOCK(&V_udbinfo); INP_WLOCK(inp); + up = intoudpcb(inp); + KASSERT(up != NULL, ("%s: up == NULL", __func__)); + inp->inp_ppcb = NULL; in_pcbdetach(inp); in_pcbfree(inp); INP_INFO_WUNLOCK(&V_udbinfo); + udp_discardcb(up); } static int Modified: head/sys/netinet/udp_var.h ============================================================================== --- head/sys/netinet/udp_var.h Sat May 23 16:42:38 2009 (r192648) +++ head/sys/netinet/udp_var.h Sat May 23 16:51:13 2009 (r192649) @@ -51,6 +51,19 @@ struct udpiphdr { #define ui_ulen ui_u.uh_ulen #define ui_sum ui_u.uh_sum +typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *); + +/* + * UDP control block; one per udp. + */ +struct udpcb { + udp_tun_func_t u_tun_func; /* UDP kernel tunneling callback. */ + u_int u_flags; /* Generic UDP flags. */ +}; + +#define intoudpcb(ip) ((struct udpcb *)(ip)->inp_ppcb) +#define sotoudpcb(so) (intoudpcb(sotoinpcb(so))) + struct udpstat { /* input statistics: */ u_long udps_ipackets; /* total input packets */ @@ -110,14 +123,15 @@ extern u_long udp_sendspace; extern u_long udp_recvspace; extern int udp_log_in_vain; +int udp_newudpcb(struct inpcb *); +void udp_discardcb(struct udpcb *); + void udp_ctlinput(int, struct sockaddr *, void *); void udp_init(void); void udp_input(struct mbuf *, int); struct inpcb *udp_notify(struct inpcb *inp, int errno); int udp_shutdown(struct socket *so); - -typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *); int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f); #endif Modified: head/sys/netinet/vinet.h ============================================================================== --- head/sys/netinet/vinet.h Sat May 23 16:42:38 2009 (r192648) +++ head/sys/netinet/vinet.h Sat May 23 16:51:13 2009 (r192649) @@ -149,6 +149,7 @@ struct vnet_inet { struct inpcbhead _udb; struct inpcbinfo _udbinfo; + uma_zone_t _udpcb_zone; struct udpstat _udpstat; int _udp_blackhole; @@ -373,6 +374,7 @@ extern struct vnet_inet vnet_inet_0; #define V_twq_2msl VNET_INET(twq_2msl) #define V_udb VNET_INET(udb) #define V_udbinfo VNET_INET(udbinfo) +#define V_udpcb_zone VNET_INET(udpcb_zone) #define V_udp_blackhole VNET_INET(udp_blackhole) #define V_udpstat VNET_INET(udpstat) #define V_useloopback VNET_INET(useloopback) Modified: head/sys/netinet6/udp6_usrreq.c ============================================================================== --- head/sys/netinet6/udp6_usrreq.c Sat May 23 16:42:38 2009 (r192648) +++ head/sys/netinet6/udp6_usrreq.c Sat May 23 16:51:13 2009 (r192649) @@ -181,6 +181,7 @@ udp6_input(struct mbuf **mp, int *offp, struct ip6_hdr *ip6; struct udphdr *uh; struct inpcb *inp; + struct udpcb *up; int off = *offp; int plen, ulen; struct sockaddr_in6 fromsa; @@ -315,7 +316,10 @@ udp6_input(struct mbuf **mp, int *offp, if ((n = m_copy(m, 0, M_COPYALL)) != NULL) { INP_RLOCK(last); - if (last->inp_ppcb != NULL) { + up = intoudpcb(last); + if (up->u_tun_func == NULL) { + udp6_append(last, n, off, &fromsa); + } else { /* * Engage the tunneling * protocol we will have to @@ -324,15 +328,9 @@ udp6_input(struct mbuf **mp, int *offp, * through multiple UDP's. * */ - udp_tun_func_t tunnel_func; - - tunnel_func = (udp_tun_func_t)last->inp_ppcb; - tunnel_func(n, off, last); - INP_RUNLOCK(last); - } else { - udp6_append(last, n, off, &fromsa); - INP_RUNLOCK(last); + (*up->u_tun_func)(n, off, last); } + INP_RUNLOCK(last); } } last = inp; @@ -361,18 +359,15 @@ udp6_input(struct mbuf **mp, int *offp, } INP_RLOCK(last); INP_INFO_RUNLOCK(&V_udbinfo); - if (last->inp_ppcb != NULL) { + up = intoudpcb(last); + if (up->u_tun_func == NULL) { + udp6_append(last, m, off, &fromsa); + } else { /* * Engage the tunneling protocol. */ - udp_tun_func_t tunnel_func; - - tunnel_func = (udp_tun_func_t)inp->inp_ppcb; - tunnel_func(m, off, last); - INP_RUNLOCK(last); - return (IPPROTO_DONE); + (*up->u_tun_func)(m, off, last); } - udp6_append(last, m, off, &fromsa); INP_RUNLOCK(last); return (IPPROTO_DONE); } @@ -409,18 +404,16 @@ udp6_input(struct mbuf **mp, int *offp, } INP_RLOCK(inp); INP_INFO_RUNLOCK(&V_udbinfo); - if (inp->inp_ppcb != NULL) { + up = intoudpcb(inp); + if (up->u_tun_func == NULL) { + udp6_append(inp, m, off, &fromsa); + } else { /* * Engage the tunneling protocol. */ - udp_tun_func_t tunnel_func; - tunnel_func = (udp_tun_func_t)inp->inp_ppcb; - tunnel_func(m, off, inp); - INP_RUNLOCK(inp); - return (IPPROTO_DONE); + (*up->u_tun_func)(m, off, inp); } - udp6_append(inp, m, off, &fromsa); INP_RUNLOCK(inp); return (IPPROTO_DONE); @@ -820,7 +813,6 @@ udp6_attach(struct socket *so, int proto return (error); } inp = (struct inpcb *)so->so_pcb; - INP_INFO_WUNLOCK(&V_udbinfo); inp->inp_vflag |= INP_IPV6; if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) inp->inp_vflag |= INP_IPV4; @@ -833,7 +825,16 @@ udp6_attach(struct socket *so, int proto * which may match an IPv4-mapped IPv6 address. */ inp->inp_ip_ttl = V_ip_defttl; + + error = udp_newudpcb(inp); + if (error) { + in_pcbdetach(inp); + in_pcbfree(inp); + INP_INFO_WUNLOCK(&V_udbinfo); + return (error); + } INP_WUNLOCK(inp); + INP_INFO_WUNLOCK(&V_udbinfo); return (0); } @@ -968,15 +969,19 @@ udp6_detach(struct socket *so) { INIT_VNET_INET(so->so_vnet); struct inpcb *inp; + struct udpcb *up; inp = sotoinpcb(so); KASSERT(inp != NULL, ("udp6_detach: inp == NULL")); INP_INFO_WLOCK(&V_udbinfo); INP_WLOCK(inp); + up = intoudpcb(inp); + KASSERT(up != NULL, ("%s: up == NULL", __func__)); in_pcbdetach(inp); in_pcbfree(inp); INP_INFO_WUNLOCK(&V_udbinfo); + udp_discardcb(up); } static int Modified: head/sys/sys/param.h ============================================================================== --- head/sys/sys/param.h Sat May 23 16:42:38 2009 (r192648) +++ head/sys/sys/param.h Sat May 23 16:51:13 2009 (r192649) @@ -57,7 +57,7 @@ * is created, otherwise 1. */ #undef __FreeBSD_version -#define __FreeBSD_version 800088 /* Master, propagated to newvers */ +#define __FreeBSD_version 800089 /* Master, propagated to newvers */ #ifndef LOCORE #include