Module Name:    src
Committed By:   rmind
Date:           Wed Aug 25 00:05:14 UTC 2010

Modified Files:
        src/sys/netinet: ip_reass.c ip_var.h

Log Message:
Use own IPv4 reassembly queue entry structure and leave struct ipqent only
for TCP.  Now both struct ipfr_qent, struct ipfr_queue and hashed fragment
queue are abstracted and no longer public.


To generate a diff of this commit:
cvs rdiff -u -r1.2 -r1.3 src/sys/netinet/ip_reass.c
cvs rdiff -u -r1.94 -r1.95 src/sys/netinet/ip_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netinet/ip_reass.c
diff -u src/sys/netinet/ip_reass.c:1.2 src/sys/netinet/ip_reass.c:1.3
--- src/sys/netinet/ip_reass.c:1.2	Mon Jul 19 14:09:45 2010
+++ src/sys/netinet/ip_reass.c	Wed Aug 25 00:05:14 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_reass.c,v 1.2 2010/07/19 14:09:45 rmind Exp $	*/
+/*	$NetBSD: ip_reass.c,v 1.3 2010/08/25 00:05:14 rmind Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1988, 1993
@@ -46,7 +46,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.2 2010/07/19 14:09:45 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ip_reass.c,v 1.3 2010/08/25 00:05:14 rmind Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -73,7 +73,32 @@
 #include <netinet/in_var.h>
 
 /*
- * IP datagram reassembly hashed queues, pool, lock and counters.
+ * IP reassembly queue structures.  Each fragment being reassembled is
+ * attached to one of these structures.  They are timed out after TTL
+ * drops to 0, and may also be reclaimed if memory becomes tight.
+ */
+
+typedef struct ipfr_qent {
+	TAILQ_ENTRY(ipfr_qent)	ipqe_q;
+	struct ip *		ipqe_ip;
+	struct mbuf *		ipqe_m;
+	bool			ipqe_mff;
+} ipfr_qent_t;
+
+typedef struct ipfr_queue {
+	LIST_ENTRY(ipfr_queue)	ipq_q;		/* to other reass headers */
+	TAILQ_HEAD(, ipfr_qent)	ipq_fragq;	/* queue of fragment entries */
+	uint8_t			ipq_ttl;	/* time for reass q to live */
+	uint8_t			ipq_p;		/* protocol of this fragment */
+	uint16_t		ipq_id;		/* sequence id for reassembly */
+	struct in_addr		ipq_src;
+	struct in_addr		ipq_dst;
+	uint16_t		ipq_nfrags;	/* frags in this queue entry */
+	uint8_t 		ipq_tos;	/* TOS of this fragment */
+} ipfr_queue_t;
+
+/*
+ * Hash table of IP reassembly queues.
  */
 #define	IPREASS_HASH_SHIFT	6
 #define	IPREASS_HASH_SIZE	(1 << IPREASS_HASH_SHIFT)
@@ -81,52 +106,36 @@
 #define	IPREASS_HASH(x, y) \
 	(((((x) & 0xf) | ((((x) >> 8) & 0xf) << 4)) ^ (y)) & IPREASS_HASH_MASK)
 
-struct ipqhead	ipq[IPREASS_HASH_SIZE];
-struct pool	ipqent_pool;
-static int	ipq_locked;
+static LIST_HEAD(, ipfr_queue)	ip_frags[IPREASS_HASH_SIZE];
+static struct pool	ipqent_pool;
+static int		ipq_locked;
 
-static int	ip_nfragpackets;	/* packets in reass queue */
-static int	ip_nfrags;		/* total fragments in reass queues */
+/* Number of packets in reassembly queue and total number of fragments. */
+static int		ip_nfragpackets;
+static int		ip_nfrags;
 
-static int	ip_maxfragpackets;	/* limit on packets. XXX sysctl */
-static int	ip_maxfrags;		/* limit on fragments. XXX sysctl */
+/* Limits on packet and fragments. */
+static int		ip_maxfragpackets;
+static int		ip_maxfrags;
 
 /*
- * IP reassembly queue structure.  Each fragment being reassembled is
- * attached to one of these structures.  They are timed out after ipq_ttl
- * drops to 0, and may also be reclaimed if memory becomes tight.
+ * Cached copy of nmbclusters.  If nbclusters is different, recalculate
+ * IP parameters derived from nmbclusters.
  */
-struct ipq {
-	LIST_ENTRY(ipq)	ipq_q;		/* to other reass headers */
-	uint8_t		ipq_ttl;	/* time for reass q to live */
-	uint8_t		ipq_p;		/* protocol of this fragment */
-	uint16_t	ipq_id;		/* sequence id for reassembly */
-	struct ipqehead	ipq_fragq;	/* to ip fragment queue */
-	struct in_addr	ipq_src;
-	struct in_addr	ipq_dst;
-	uint16_t	ipq_nfrags;	/* frags in this queue entry */
-	uint8_t 	ipq_tos;	/* TOS of this fragment */
-};
-
-/*
- * Cached copy of nmbclusters. If nbclusters is different,
- * recalculate IP parameters derived from nmbclusters.
- */
-static int	ip_nmbclusters;			/* copy of nmbclusters */
+static int		ip_nmbclusters;
 
 /*
  * IP reassembly TTL machinery for multiplicative drop.
  */
-static u_int	fragttl_histo[IPFRAGTTL + 1];
+static u_int		fragttl_histo[IPFRAGTTL + 1];
 
-void		sysctl_ip_reass_setup(void);
-static void	ip_nmbclusters_changed(void);
+void			sysctl_ip_reass_setup(void);
+static void		ip_nmbclusters_changed(void);
 
-static struct ipq *	ip_reass_lookup(struct ip *, u_int *);
-static struct mbuf *	ip_reass(struct ipqent *, struct ipq *, u_int);
+static struct mbuf *	ip_reass(ipfr_qent_t *, ipfr_queue_t *, u_int);
 static u_int		ip_reass_ttl_decr(u_int ticks);
 static void		ip_reass_drophalf(void);
-static void		ip_freef(struct ipq *);
+static void		ip_freef(ipfr_queue_t *);
 
 /*
  * ip_reass_init:
@@ -138,11 +147,11 @@
 {
 	int i;
 
-	pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl",
+	pool_init(&ipqent_pool, sizeof(ipfr_qent_t), 0, 0, 0, "ipqepl",
 	    NULL, IPL_VM);
 
 	for (i = 0; i < IPREASS_HASH_SIZE; i++) {
-		LIST_INIT(&ipq[i]);
+		LIST_INIT(&ip_frags[i]);
 	}
 	ip_maxfragpackets = 200;
 	ip_maxfrags = 0;
@@ -255,34 +264,6 @@
 #define	IPQ_UNLOCK()		ipq_unlock()
 
 /*
- * ip_reass_lookup:
- *
- *	Look for queue of fragments of this datagram.
- */
-static struct ipq *
-ip_reass_lookup(struct ip *ip, u_int *hashp)
-{
-	struct ipq *fp;
-	u_int hash;
-
-	IPQ_LOCK();
-	hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
-	LIST_FOREACH(fp, &ipq[hash], ipq_q) {
-		if (ip->ip_id != fp->ipq_id)
-			continue;
-		if (!in_hosteq(ip->ip_src, fp->ipq_src))
-			continue;
-		if (!in_hosteq(ip->ip_dst, fp->ipq_dst))
-			continue;
-		if (ip->ip_p != fp->ipq_p)
-			continue;
-		break;
-	}
-	*hashp = hash;
-	return fp;
-}
-
-/*
  * ip_reass:
  *
  *	Take incoming datagram fragment and try to reassemble it into whole
@@ -290,12 +271,11 @@
  *	then it is given as 'fp'; otherwise have to make a chain.
  */
 struct mbuf *
-ip_reass(struct ipqent *ipqe, struct ipq *fp, u_int hash)
+ip_reass(ipfr_qent_t *ipqe, ipfr_queue_t *fp, const u_int hash)
 {
-	struct ipqhead *ipqhead = &ipq[hash];
 	const int hlen = ipqe->ipqe_ip->ip_hl << 2;
 	struct mbuf *m = ipqe->ipqe_m, *t;
-	struct ipqent *nq, *p, *q;
+	ipfr_qent_t *nq, *p, *q;
 	struct ip *ip;
 	int i, next, s;
 
@@ -338,11 +318,11 @@
 			goto dropfrag;
 		}
 		ip_nfragpackets++;
-		fp = malloc(sizeof(struct ipq), M_FTABLE, M_NOWAIT);
+		fp = malloc(sizeof(ipfr_queue_t), M_FTABLE, M_NOWAIT);
 		if (fp == NULL) {
 			goto dropfrag;
 		}
-		LIST_INSERT_HEAD(ipqhead, fp, ipq_q);
+		LIST_INSERT_HEAD(&ip_frags[hash], fp, ipq_q);
 		fp->ipq_nfrags = 1;
 		fp->ipq_ttl = IPFRAGTTL;
 		fp->ipq_p = ipqe->ipqe_ip->ip_p;
@@ -510,9 +490,9 @@
  *	Free a fragment reassembly header and all associated datagrams.
  */
 static void
-ip_freef(struct ipq *fp)
+ip_freef(ipfr_queue_t *fp)
 {
-	struct ipqent *q, *p;
+	ipfr_qent_t *q, *p;
 	u_int nfrags = 0;
 	int s;
 
@@ -550,14 +530,14 @@
 ip_reass_ttl_decr(u_int ticks)
 {
 	u_int nfrags, median, dropfraction, keepfraction;
-	struct ipq *fp, *nfp;
+	ipfr_queue_t *fp, *nfp;
 	int i;
 
 	nfrags = 0;
 	memset(fragttl_histo, 0, sizeof(fragttl_histo));
 
 	for (i = 0; i < IPREASS_HASH_SIZE; i++) {
-		for (fp = LIST_FIRST(&ipq[i]); fp != NULL; fp = nfp) {
+		for (fp = LIST_FIRST(&ip_frags[i]); fp != NULL; fp = nfp) {
 			fp->ipq_ttl = ((fp->ipq_ttl <= ticks) ?
 			    0 : fp->ipq_ttl - ticks);
 			nfp = LIST_NEXT(fp, ipq_q);
@@ -660,8 +640,8 @@
 
 		i = dropscanidx;
 		while (ip_nfragpackets > ip_maxfragpackets && wrapped == 0) {
-			while (LIST_FIRST(&ipq[i]) != NULL) {
-				ip_freef(LIST_FIRST(&ipq[i]));
+			while (LIST_FIRST(&ip_frags[i]) != NULL) {
+				ip_freef(LIST_FIRST(&ip_frags[i]));
 			}
 			if (++i >= IPREASS_HASH_SIZE) {
 				i = 0;
@@ -691,12 +671,24 @@
 int
 ip_reass_packet(struct mbuf *m, struct ip *ip, bool mff, struct mbuf **m_final)
 {
-	struct ipq *fp;
-	struct ipqent *ipqe;
+	ipfr_queue_t *fp;
+	ipfr_qent_t *ipqe;
 	u_int hash;
 
 	/* Look for queue of fragments of this datagram. */
-	fp = ip_reass_lookup(ip, &hash);
+	IPQ_LOCK();
+	hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id);
+	LIST_FOREACH(fp, &ip_frags[hash], ipq_q) {
+		if (ip->ip_id != fp->ipq_id)
+			continue;
+		if (!in_hosteq(ip->ip_src, fp->ipq_src))
+			continue;
+		if (!in_hosteq(ip->ip_dst, fp->ipq_dst))
+			continue;
+		if (ip->ip_p != fp->ipq_p)
+			continue;
+		break;
+	}
 
 	/* Make sure that TOS matches previous fragments. */
 	if (fp && fp->ipq_tos != ip->ip_tos) {

Index: src/sys/netinet/ip_var.h
diff -u src/sys/netinet/ip_var.h:1.94 src/sys/netinet/ip_var.h:1.95
--- src/sys/netinet/ip_var.h:1.94	Mon Jul 19 19:16:45 2010
+++ src/sys/netinet/ip_var.h	Wed Aug 25 00:05:14 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ip_var.h,v 1.94 2010/07/19 19:16:45 rmind Exp $	*/
+/*	$NetBSD: ip_var.h,v 1.95 2010/08/25 00:05:14 rmind Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1993
@@ -49,7 +49,7 @@
 } __packed;
 
 /*
- * Ip (reassembly or sequence) queue structures.
+ * IP sequence queue structure.
  *
  * XXX -- The following explains why the ipqe_m field is here, for TCP's use:
  * We want to avoid doing m_pullup on incoming packets but that
@@ -77,7 +77,6 @@
 	u_int32_t ipqe_len;
 	u_int32_t ipqe_flags;
 };
-#define	ipqe_ip		_ipqe_u1._ip
 #define	ipqe_tcp	_ipqe_u1._tcp
 
 /*
@@ -161,7 +160,6 @@
 
 extern struct domain inetdomain;
 
-extern LIST_HEAD(ipqhead, ipq) ipq[];	/* ip reass. queue */
 extern int   ip_defttl;			/* default IP ttl */
 extern int   ipforwarding;		/* ip forwarding */
 extern int   ip_mtudisc;		/* mtu discovery */

Reply via email to