NetBSD Problem Report #3480

Received: (qmail-queue invoked from smtpd); 12 Apr 1997 09:10:59 -0000
Message-Id: <199704120909.SAA00583@ducati.imada.math.human.nagoya-u.ac.jp>
Date: Sat, 12 Apr 1997 18:09:21 +0900 (JST)
From: koji@math.human.nagoya-u.ac.jp
Reply-To: koji@math.human.nagoya-u.ac.jp
To: gnats-bugs@gnats.netbsd.org
Subject: Deletion of dtom in ip_input.c
X-Send-Pr-Version: 3.95

>Number:         3480
>Category:       kern
>Synopsis:       changes to eliminate dtom in ip reassembly code in ip_input.c
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          closed
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Apr 12 02:20:01 +0000 1997
>Closed-Date:    Tue Jun 24 01:31:55 +0000 1997
>Last-Modified:  Tue Jun 24 01:33:03 +0000 1997
>Originator:     Koji Imada - je4owb/2
>Release:        970409
>Organization:
Mathematics Group of Graduate School of Human
	Infomatics, Nagoya University, Japan. 
>Environment:

System: NetBSD ducati 1.2D NetBSD 1.2D (DUCATI) #1: Sat Apr 12 11:35:25 JST 1997 koji@ducati:/mnt2/NetBSD/work/src-ipv6/sys/arch/i386/compile/DUCATI i386


>Description:
	changes to eliminate dtom in ip reassembly code in
	ip_input.c. struct ipqent is modified to always keep pointer
	to mbuf. And struct ipq is allocated with MALLOC not
	m_get. These modification eliminates dtom in ip_input.c.
>How-To-Repeat:

>Fix:
	Apply following patches.

Index: sys/netinet//ip_input.c
===================================================================
RCS file: /mnt2/NetBSD/cvsroot/netbsd/sys/netinet/ip_input.c,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 ip_input.c
*** ip_input.c	1997/04/01 07:17:24	1.1.1.2
--- ip_input.c	1997/04/12 01:31:07
***************
*** 373,378 ****
--- 373,379 ----
  	 * but it's not worth the time; just let them time out.)
  	 */
  	if (ip->ip_off & ~(IP_DF|IP_RF)) {
+ #if 0 /* this is not necessary if dtom is not used */
  		if (m->m_flags & M_EXT) {		/* XXX */
  			if ((m = m_pullup(m, sizeof (struct ip))) == 0) {
  				ipstat.ips_toosmall++;
***************
*** 380,385 ****
--- 381,387 ----
  			}
  			ip = mtod(m, struct ip *);
  		}
+ #endif
  		/*
  		 * Look for queue of fragments
  		 * of this datagram.
***************
*** 425,430 ****
--- 427,442 ----
  				ipstat.ips_rcvmemdrop++;
  				goto bad;
  			}
+ #if 1 /* don't use dtom */
+ 			ipqe->ipqe_mff = mff;
+ 			ipqe->ipqe_m = m;
+ 			ipqe->ipqe_ip = ip;
+ 			m = ip_reass(ipqe, fp);
+ 			if (m == 0)
+ 				goto next;
+ 			ipstat.ips_reassembled++;
+ 			ip = mtod(m, struct ip *);
+ #else 
  			ipqe->ipqe_mff = mff;
  			ipqe->ipqe_ip = ip;
  			ip = ip_reass(ipqe, fp);
***************
*** 432,437 ****
--- 444,450 ----
  				goto next;
  			ipstat.ips_reassembled++;
  			m = dtom(ip);
+ #endif
  		} else
  			if (fp)
  				ip_freef(fp);
***************
*** 455,466 ****
   * reassembly of this datagram already exists, then it
   * is given as fp; otherwise have to make a chain.
   */
! struct ip *
  ip_reass(ipqe, fp)
  	register struct ipqent *ipqe;
  	register struct ipq *fp;
  {
! 	register struct mbuf *m = dtom(ipqe->ipqe_ip);
  	register struct ipqent *nq, *p, *q;
  	struct ip *ip;
  	struct mbuf *t;
--- 468,479 ----
   * reassembly of this datagram already exists, then it
   * is given as fp; otherwise have to make a chain.
   */
! struct mbuf *
  ip_reass(ipqe, fp)
  	register struct ipqent *ipqe;
  	register struct ipq *fp;
  {
! 	register struct mbuf *m = ipqe->ipqe_m;
  	register struct ipqent *nq, *p, *q;
  	struct ip *ip;
  	struct mbuf *t;
***************
*** 478,486 ****
--- 491,506 ----
  	 * If first fragment to arrive, create a reassembly queue.
  	 */
  	if (fp == 0) {
+ #if 1
+ 		MALLOC(fp, struct ipq *, sizeof (struct ipq),
+ 		    M_FTABLE, M_NOWAIT);
+ 		if (fp == NULL)
+ 			goto dropfrag;
+ #else
  		if ((t = m_get(M_DONTWAIT, MT_FTABLE)) == NULL)
  			goto dropfrag;
  		fp = mtod(t, struct ipq *);
+ #endif
  		LIST_INSERT_HEAD(&ipq, fp, ipq_q);
  		fp->ipq_ttl = IPFRAGTTL;
  		fp->ipq_p = ipqe->ipqe_ip->ip_p;
***************
*** 511,517 ****
  		if (i > 0) {
  			if (i >= ipqe->ipqe_ip->ip_len)
  				goto dropfrag;
! 			m_adj(dtom(ipqe->ipqe_ip), i);
  			ipqe->ipqe_ip->ip_off += i;
  			ipqe->ipqe_ip->ip_len -= i;
  		}
--- 531,537 ----
  		if (i > 0) {
  			if (i >= ipqe->ipqe_ip->ip_len)
  				goto dropfrag;
! 			m_adj(ipqe->ipqe_m, i);
  			ipqe->ipqe_ip->ip_off += i;
  			ipqe->ipqe_ip->ip_len -= i;
  		}
***************
*** 528,538 ****
  		if (i < q->ipqe_ip->ip_len) {
  			q->ipqe_ip->ip_len -= i;
  			q->ipqe_ip->ip_off += i;
! 			m_adj(dtom(q->ipqe_ip), i);
  			break;
  		}
  		nq = q->ipqe_q.le_next;
! 		m_freem(dtom(q->ipqe_ip));
  		LIST_REMOVE(q, ipqe_q);
  		FREE(q, M_IPQ);
  	}
--- 548,558 ----
  		if (i < q->ipqe_ip->ip_len) {
  			q->ipqe_ip->ip_len -= i;
  			q->ipqe_ip->ip_off += i;
! 			m_adj(q->ipqe_m, i);
  			break;
  		}
  		nq = q->ipqe_q.le_next;
! 		m_freem(q->ipqe_m);
  		LIST_REMOVE(q, ipqe_q);
  		FREE(q, M_IPQ);
  	}
***************
*** 568,581 ****
  		ip_freef(fp);
  		return (0);
  	}
! 	m = dtom(q->ipqe_ip);
  	t = m->m_next;
  	m->m_next = 0;
  	m_cat(m, t);
  	nq = q->ipqe_q.le_next;
  	FREE(q, M_IPQ);
  	for (q = nq; q != NULL; q = nq) {
! 		t = dtom(q->ipqe_ip);
  		nq = q->ipqe_q.le_next;
  		FREE(q, M_IPQ);
  		m_cat(m, t);
--- 588,601 ----
  		ip_freef(fp);
  		return (0);
  	}
! 	m = q->ipqe_m;
  	t = m->m_next;
  	m->m_next = 0;
  	m_cat(m, t);
  	nq = q->ipqe_q.le_next;
  	FREE(q, M_IPQ);
  	for (q = nq; q != NULL; q = nq) {
! 		t = q->ipqe_m;
  		nq = q->ipqe_q.le_next;
  		FREE(q, M_IPQ);
  		m_cat(m, t);
***************
*** 591,607 ****
  	ip->ip_src = fp->ipq_src;
  	ip->ip_dst = fp->ipq_dst;
  	LIST_REMOVE(fp, ipq_q);
  	(void) m_free(dtom(fp));
  	m->m_len += (ip->ip_hl << 2);
  	m->m_data -= (ip->ip_hl << 2);
  	/* some debugging cruft by sklower, below, will go away soon */
  	if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
  		register int plen = 0;
! 		for (t = m; m; m = m->m_next)
! 			plen += m->m_len;
! 		t->m_pkthdr.len = plen;
  	}
! 	return (ip);

  dropfrag:
  	ipstat.ips_fragdropped++;
--- 611,631 ----
  	ip->ip_src = fp->ipq_src;
  	ip->ip_dst = fp->ipq_dst;
  	LIST_REMOVE(fp, ipq_q);
+ #if 1
+ 	FREE(fp, M_FTABLE);
+ #else
  	(void) m_free(dtom(fp));
+ #endif
  	m->m_len += (ip->ip_hl << 2);
  	m->m_data -= (ip->ip_hl << 2);
  	/* some debugging cruft by sklower, below, will go away soon */
  	if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */
  		register int plen = 0;
! 		for (t = m; t; t = t->m_next)
! 			plen += t->m_len;
! 		m->m_pkthdr.len = plen;
  	}
! 	return (m);

  dropfrag:
  	ipstat.ips_fragdropped++;
***************
*** 622,633 ****

  	for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {
  		p = q->ipqe_q.le_next;
! 		m_freem(dtom(q->ipqe_ip));
  		LIST_REMOVE(q, ipqe_q);
  		FREE(q, M_IPQ);
  	}
  	LIST_REMOVE(fp, ipq_q);
  	(void) m_free(dtom(fp));
  }

  /*
--- 646,661 ----

  	for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) {
  		p = q->ipqe_q.le_next;
! 		m_freem(q->ipqe_m);
  		LIST_REMOVE(q, ipqe_q);
  		FREE(q, M_IPQ);
  	}
  	LIST_REMOVE(fp, ipq_q);
+ #if 1
+ 	FREE(fp, M_FTABLE);
+ #else
  	(void) m_free(dtom(fp));
+ #endif
  }

  /*
Index: sys/netinet//ip_var.h
===================================================================
RCS file: /mnt2/NetBSD/cvsroot/netbsd/sys/netinet/ip_var.h,v
retrieving revision 1.1.1.2
diff -c -r1.1.1.2 ip_var.h
*** ip_var.h	1997/04/01 07:17:27	1.1.1.2
--- ip_var.h	1997/04/12 01:14:17
***************
*** 66,80 ****
  		struct ip	*_ip;
  		struct tcpiphdr *_tcp;
  	} _ipqe_u1;
! 	union {
! 		u_int8_t	_mff;	/* for IP fragmentation */
! 		struct mbuf	*_m;	/* XXX for TCP; see above */
! 	} _ipqe_u2;
  };
  #define	ipqe_ip		_ipqe_u1._ip
  #define	ipqe_tcp	_ipqe_u1._tcp
- #define	ipqe_mff	_ipqe_u2._mff
- #define	ipqe_m		_ipqe_u2._m

  /*
   * Ip reassembly queue structure.  Each fragment
--- 66,76 ----
  		struct ip	*_ip;
  		struct tcpiphdr *_tcp;
  	} _ipqe_u1;
! 	struct mbuf	*ipqe_m;	/* mbuf contains packet */
! 	u_int8_t	ipqe_mff;	/* for IP fragmentation */
  };
  #define	ipqe_ip		_ipqe_u1._ip
  #define	ipqe_tcp	_ipqe_u1._tcp

  /*
   * Ip reassembly queue structure.  Each fragment
***************
*** 172,178 ****
  int	 ip_optcopy __P((struct ip *, struct ip *));
  int	 ip_output __P((struct mbuf *, ...));
  int	 ip_pcbopts __P((struct mbuf **, struct mbuf *));
! struct ip *
  	 ip_reass __P((struct ipqent *, struct ipq *));
  struct in_ifaddr *
  	 ip_rtaddr __P((struct in_addr));
--- 168,174 ----
  int	 ip_optcopy __P((struct ip *, struct ip *));
  int	 ip_output __P((struct mbuf *, ...));
  int	 ip_pcbopts __P((struct mbuf **, struct mbuf *));
! struct mbuf *
  	 ip_reass __P((struct ipqent *, struct ipq *));
  struct in_ifaddr *
  	 ip_rtaddr __P((struct in_addr));

>Release-Note:
>Audit-Trail:
State-Changed-From-To: open->feedback 
State-Changed-By: pk 
State-Changed-When: Wed Apr 16 15:46:13 PDT 1997 
State-Changed-Why:  
Can you explain why eliminating dtom() in this particular case is a win? 
Does it have a major performance benefit? 
State-Changed-From-To: feedback->analyzed 
State-Changed-By: thorpej 
State-Changed-When: Mon Jun 23 18:30:32 PDT 1997 
State-Changed-Why:  
This change is a correct one, and should be implemented. 
State-Changed-From-To: analyzed->closed 
State-Changed-By: thorpej 
State-Changed-When: Mon Jun 23 18:31:55 PDT 1997 
State-Changed-Why:  
This is a subset of PR 3628 
>Unformatted:
 Reply from Koji Imada <koji@bimota.imada.math.human.nagoya-u.ac.jp>:

 My goal is to eliminate all dtom()'s from kernel code. Since dtom()
 restricts improvement of mbuf routines for more utilization.

 Now, dtom() is forcing to use m_pullup for mbuf clusters on
 everywhere(described in p.374 of "The Design and Implementation of the 
 4.4BSD Operating System"). I think it is useless.

 This maybe some performance penalty(now, device drivers use mbuf
 clusters for many packets?). Special handling of mbuf clusters(M_EXT)
 is not preferable.

 I have found dtom() in ip_input.c and tcp_subr.c. The dtom() in
 tcp_subr.c may be eliminated by using malloc'ed memory instead of mbuf 
 for tcp_template(). I would send-pr patch for that too.

 I want to eliminate dtom()'s in all kernel codes and improve mbuf
 routines because current mbuf routines is not enough to be used for
 IPv6 code and ipsec codes.

 There are ugly codes to avoid limitation of current mbuf routines in
 inria's IPv6 code and nrl's Ipv6 code.

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.49 2026/05/14 01:52:41 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.