svn commit: r196192 - in stable/7/sys: . contrib/pf netinet netinet6

Bjoern A. Zeeb bz at FreeBSD.org
Thu Aug 13 15:16:31 UTC 2009


Author: bz
Date: Thu Aug 13 15:16:30 2009
New Revision: 196192
URL: http://svn.freebsd.org/changeset/base/196192

Log:
  MFC: r192649
  
    Implement UDP control block support.
  
    Add udpcb support with own fields and flags for UDP instead
    of further sticking things into in_pcb and flags fields.
    Attach the udpcb to the inp_ppcb in the kernel.
  
    Note: the udp tunneling parts are not (yet) existing in 7
    and thus were not merged.
  
  Reviewed by:	rwatson

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/netinet/udp_usrreq.c
  stable/7/sys/netinet/udp_var.h
  stable/7/sys/netinet6/udp6_usrreq.c

Modified: stable/7/sys/netinet/udp_usrreq.c
==============================================================================
--- stable/7/sys/netinet/udp_usrreq.c	Thu Aug 13 15:14:02 2009	(r196191)
+++ stable/7/sys/netinet/udp_usrreq.c	Thu Aug 13 15:16:30 2009	(r196192)
@@ -138,6 +138,7 @@ SYSCTL_INT(_net_inet_udp, OID_AUTO, sore
 
 struct inpcbhead	udb;		/* from udp_var.h */
 struct inpcbinfo	udbinfo;
+static uma_zone_t	udpcb_zone;
 
 #ifndef UDBHASHSIZE
 #define	UDBHASHSIZE	128
@@ -156,6 +157,7 @@ udp_zone_change(void *tag)
 {
 
 	uma_zone_set_max(udbinfo.ipi_zone, maxsockets);
+	uma_zone_set_max(udpcb_zone, maxsockets);
 }
 
 static int
@@ -179,9 +181,14 @@ udp_init(void)
 	    &udbinfo.ipi_hashmask);
 	udbinfo.ipi_porthashbase = hashinit(UDBHASHSIZE, M_PCB,
 	    &udbinfo.ipi_porthashmask);
-	udbinfo.ipi_zone = uma_zcreate("udpcb", sizeof(struct inpcb), NULL,
-	    NULL, udp_inpcb_init, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+	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(udbinfo.ipi_zone, maxsockets);
+
+	udpcb_zone = uma_zcreate("udpcb", sizeof(struct udpcb),
+	    NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, UMA_ZONE_NOFREE);
+	uma_zone_set_max(udpcb_zone, maxsockets);
+
 	EVENTHANDLER_REGISTER(maxsockets_change, udp_zone_change, NULL,
 	    EVENTHANDLER_PRI_ANY);
 	TUNABLE_INT_FETCH("net.inet.udp.soreceive_dgram_enabled",
@@ -194,6 +201,25 @@ udp_init(void)
 	}
 }
 
+int
+udp_newudpcb(struct inpcb *inp)
+{
+	struct udpcb *up;
+
+	up = uma_zalloc(udpcb_zone, M_NOWAIT | M_ZERO);
+	if (up == NULL)
+		return (ENOBUFS);
+	inp->inp_ppcb = up;
+	return (0);
+}
+
+void
+udp_discardcb(struct udpcb *up)
+{
+
+	uma_zfree(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
@@ -1129,10 +1155,19 @@ udp_attach(struct socket *so, int proto,
 	}
 
 	inp = (struct inpcb *)so->so_pcb;
-	INP_INFO_WUNLOCK(&udbinfo);
 	inp->inp_vflag |= INP_IPV4;
 	inp->inp_ip_ttl = ip_defttl;
+
+	error = udp_newudpcb(inp);
+	if (error) {
+		in_pcbdetach(inp);
+		in_pcbfree(inp);
+		INP_INFO_WUNLOCK(&udbinfo);
+		return (error);
+	}
+
 	INP_WUNLOCK(inp);
+	INP_INFO_WUNLOCK(&udbinfo);
 	return (0);
 }
 
@@ -1205,6 +1240,7 @@ static void
 udp_detach(struct socket *so)
 {
 	struct inpcb *inp;
+	struct udpcb *up;
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp_detach: inp == NULL"));
@@ -1212,9 +1248,13 @@ udp_detach(struct socket *so)
 	    ("udp_detach: not disconnected"));
 	INP_INFO_WLOCK(&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(&udbinfo);
+	udp_discardcb(up);
 }
 
 static int

Modified: stable/7/sys/netinet/udp_var.h
==============================================================================
--- stable/7/sys/netinet/udp_var.h	Thu Aug 13 15:14:02 2009	(r196191)
+++ stable/7/sys/netinet/udp_var.h	Thu Aug 13 15:16:30 2009	(r196192)
@@ -51,6 +51,17 @@ struct udpiphdr {
 #define	ui_ulen		ui_u.uh_ulen
 #define	ui_sum		ui_u.uh_sum
 
+/*
+ * UDP control block; one per udp.
+ */
+struct udpcb {
+	void		*u_pspare;
+	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 */
@@ -102,6 +113,9 @@ extern struct udpstat		udpstat;
 extern int			udp_blackhole;
 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);

Modified: stable/7/sys/netinet6/udp6_usrreq.c
==============================================================================
--- stable/7/sys/netinet6/udp6_usrreq.c	Thu Aug 13 15:14:02 2009	(r196191)
+++ stable/7/sys/netinet6/udp6_usrreq.c	Thu Aug 13 15:16:30 2009	(r196192)
@@ -739,7 +739,6 @@ udp6_attach(struct socket *so, int proto
 		return (error);
 	}
 	inp = (struct inpcb *)so->so_pcb;
-	INP_INFO_WUNLOCK(&udbinfo);
 	inp->inp_vflag |= INP_IPV6;
 	if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0)
 		inp->inp_vflag |= INP_IPV4;
@@ -752,7 +751,16 @@ udp6_attach(struct socket *so, int proto
 	 * which may match an IPv4-mapped IPv6 address.
 	 */
 	inp->inp_ip_ttl = ip_defttl;
+
+	error = udp_newudpcb(inp);
+	if (error) {
+		in_pcbdetach(inp);
+		in_pcbfree(inp);
+		INP_INFO_WUNLOCK(&udbinfo);
+		return (error);
+	}
 	INP_WUNLOCK(inp);
+	INP_INFO_WUNLOCK(&udbinfo);
 	return (0);
 }
 
@@ -883,15 +891,19 @@ static void
 udp6_detach(struct socket *so)
 {
 	struct inpcb *inp;
+	struct udpcb *up;
 
 	inp = sotoinpcb(so);
 	KASSERT(inp != NULL, ("udp6_detach: inp == NULL"));
 
 	INP_INFO_WLOCK(&udbinfo);
 	INP_WLOCK(inp);
+	up = intoudpcb(inp);
+	KASSERT(up != NULL, ("%s: up == NULL", __func__));
 	in_pcbdetach(inp);
 	in_pcbfree(inp);
 	INP_INFO_WUNLOCK(&udbinfo);
+	udp_discardcb(up);
 }
 
 static int


More information about the svn-src-all mailing list