Re: cvs commit: src/sys/conf options src/sys/netinet ip_output.c

From: Bosko Milekic <bmilekic_at_unixdaemons.com>
Date: Thu, 27 Mar 2003 11:44:02 -0500
Can you please still use m_gethdr() or m_getcl() to do the allocations
in the defragment function?  Similarly, for > MCLBYTES, use m_getm().
Don't roll your own.

On Thu, Mar 27, 2003 at 01:36:38AM -0600, Mike Silbersack wrote:
> 
> Ok, I think I have m_defrag in a working state, please review.
> 
> Changes from last time:
> 
> - It supports infinitely long chains.
> - It has a "goal" argument which is supposed to be a hint to tell m_defrag
> how long the chain can be.  It is currently ignored; someone may want to
> honor this later for optimization purposes.
> - I fixed up the error case in if_xl, it only runs if needed now
> 
> At the top of the if_loop and if_xl patches are debugging code I used to
> make it was working right, they're certainly not going in.
> 
> m_defrag should be totally free of debug code.
> 
> Dig in!
> 
> Mike "Silby" Silbersack
> diff -u -r /usr/src/sys.old/kern/uipc_mbuf.c /usr/src/sys/kern/uipc_mbuf.c
> --- /usr/src/sys.old/kern/uipc_mbuf.c	Tue Mar 25 19:51:44 2003
> +++ /usr/src/sys/kern/uipc_mbuf.c	Thu Mar 27 01:32:36 2003
> _at__at_ -52,6 +52,7 _at__at_
>  int	max_protohdr;
>  int	max_hdr;
>  int	max_datalen;
> +int	m_defragcount;
>  
>  /*
>   * sysctl(8) exported objects
> _at__at_ -64,6 +65,8 _at__at_
>  SYSCTL_INT(_kern_ipc, KIPC_MAX_HDR, max_hdr, CTLFLAG_RW, &max_hdr, 0, "");
>  SYSCTL_INT(_kern_ipc, KIPC_MAX_DATALEN, max_datalen, CTLFLAG_RW,
>  	   &max_datalen, 0, "");
> +SYSCTL_INT(_kern_ipc, OID_AUTO, m_defragcount, CTLFLAG_RW,
> +	   &m_defragcount, 0, "");
>  
>  /*
>   * "Move" mbuf pkthdr from "from" to "to".
> _at__at_ -777,4 +780,66 _at__at_
>  	if (last != NULL)
>  		*last = m;
>  	return (len);
> +}
> +
> +/*
> + * Defragment a mbuf chain, returning a new mbuf chain which is
> + * comprised of some chain =< "goal".  Return NULL if mbuf
> + * allocation fails, rather than returning the still fragmented
> + * chain.  If a non-packet header is passed in, the original
> + * mbuf (chain?) will be returned unharmed.
> + *
> + */
> +struct mbuf *
> +m_defrag(struct mbuf *m0, int how, int goal)
> +{
> +	struct mbuf	*m_new = NULL, *m_final = NULL;
> +	int		progress = 0, length;
> +
> +	if (!(m0->m_flags & M_PKTHDR))
> +		return (m0);
> +
> +	m_final = m_gethdr(how, MT_DATA);
> +
> +	if (m_final == NULL)
> +		goto nospace;
> +
> +	if (m_dup_pkthdr(m_final, m0, how) == NULL)
> +		goto nospace;
> +
> +	m_new = m_final;
> +
> +	while (progress < m0->m_pkthdr.len) {
> +		length = m0->m_pkthdr.len - progress;
> +		if (length > MCLBYTES)
> +			length = MCLBYTES;
> +
> +		if (m_new == NULL)
> +			m_new = m_get(how, MT_DATA);
> +
> +		if (length > MHLEN) {
> +			MCLGET(m_new, how);
> +			if ((m_new->m_flags & M_EXT) == 0)
> +				goto nospace;
> +		}
> +
> +		m_copydata(m0, progress, length, mtod(m_new, caddr_t));
> +		progress += length;
> +		m_new->m_len = length;
> +		if (m_new != m_final)
> +			m_cat(m_final, m_new);
> +		m_new = NULL;
> +	}
> +	m_freem(m0);
> +	m0 = m_final;
> +	m_defragcount++;
> +	return (m0);
> +nospace:
> +	if (m0)
> +		m_freem(m0);
> +	if (m_new)
> +		m_free(m_new);
> +	if (m_final)
> +		m_freem(m_final);
> +	return (NULL);
>  }
> diff -u -r /usr/src/sys.old/net/if_loop.c /usr/src/sys/net/if_loop.c
> --- /usr/src/sys.old/net/if_loop.c	Tue Mar 25 19:51:02 2003
> +++ /usr/src/sys/net/if_loop.c	Thu Mar 27 01:37:45 2003
> _at__at_ -192,6 +192,27 _at__at_
>  	struct sockaddr *dst;
>  	register struct rtentry *rt;
>  {
> +	struct mbuf	*m_temp;
> +	int	before = 0, after = 0;
> +	int	lbefore = 0, lafter = 0;
> +
> +
> +        for (m_temp = m; m_temp != NULL; m_temp = m_temp->m_next) {
> +                lbefore += m_temp->m_len;
> +                before++;
> +        }
> + 
> +        if (before > 20)
> +                m = m_defrag(m, M_DONTWAIT, 1);
> + 
> +        for (m_temp = m; m_temp != NULL; m_temp = m_temp->m_next) { 
> +                lafter += m_temp->m_len;
> +                after++;
> +        }
> +
> +        if (before != after)
> +                printf("before: %i (%i) after: %i (%i)\n", before, lbefore, after, lafter);
> +
>  	if ((m->m_flags & M_PKTHDR) == 0)
>  		panic("looutput no HDR");
>  
> diff -u -r /usr/src/sys.old/pci/if_xl.c /usr/src/sys/pci/if_xl.c
> --- /usr/src/sys.old/pci/if_xl.c	Tue Mar 25 19:50:52 2003
> +++ /usr/src/sys/pci/if_xl.c	Thu Mar 27 01:01:02 2003
> _at__at_ -2412,9 +2412,27 _at__at_
>  	struct xl_chain		*c;
>  	struct mbuf		*m_head;
>  {
> -	struct xl_frag		*f = NULL;
>  	int			error;
> -	u_int32_t		baddr, status;
> +	u_int32_t		status;
> +	struct mbuf		*m_temp;
> +	int			lbefore = 0, lafter = 0;
> +	int			before = 0, after = 0;
> +
> +	for (m_temp = m_head; m_temp != NULL; m_temp = m_temp->m_next) {
> +		lbefore += m_temp->m_len;
> +		before++;
> +	}
> +
> +	if (before > 5)
> +		m_head = m_defrag(m_head, M_DONTWAIT, 1);
> +
> +	for (m_temp = m_head; m_temp != NULL; m_temp = m_temp->m_next) {
> +		lafter += m_temp->m_len;
> +		after++;
> +	}
> +
> +	if (before != after)
> +		printf("before: %i (%i) after: %i (%i)\n", before, lbefore, after, lafter);
>  
>  	/*
>   	 * Start packing the mbufs in this chain into
> _at__at_ -2439,35 +2457,21 _at__at_
>  	 * and would waste cycles.
>  	 */
>  	if (error) {
> -		struct mbuf		*m_new;
> +		m_head = m_defrag(m_head, M_DONTWAIT, XL_MAXFRAGS);
>  
> -		m_new = m_head->m_pkthdr.len > MHLEN ?
> -		    m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR) :
> -		    m_gethdr(M_DONTWAIT, MT_DATA);
> -		if (m_new == NULL) {
> -			m_freem(m_head);
> +		if (m_head == NULL) {
>  			printf("xl%d: no memory for tx list\n", sc->xl_unit);
>  			return(1);
>  		}
> -		m_copydata(m_head, 0, m_head->m_pkthdr.len,	
> -					mtod(m_new, caddr_t));
> -		m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
> -		m_freem(m_head);
> -		m_head = m_new;
> -		f = &c->xl_ptr->xl_frag[0];
> -		error = bus_dmamap_load(sc->xl_mtag, c->xl_map,
> -		    mtod(m_new, void *), MCLBYTES, xl_dma_map_addr,
> -		    &baddr, 0);
> +
> +		error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map,
> +			m_head, xl_dma_map_txbuf, c->xl_ptr, 0);
>  		if (error) {
> -			m_freem(m_new);
> +			m_freem(m_head);
>  			printf("xl%d: can't map mbuf (error %d)\n",
>  			    sc->xl_unit, error);
>  			return(1);
>  		}
> -		f->xl_addr = htole32(baddr);
> -		f->xl_len = htole32(m_new->m_len | XL_LAST_FRAG);
> -		c->xl_ptr->xl_status = htole32(m_new->m_len);
> -		c->xl_ptr->xl_next = 0;
>  	}
>  
>  	if (sc->xl_type == XL_TYPE_905B) {
> diff -u -r /usr/src/sys.old/pci/if_xlreg.h /usr/src/sys/pci/if_xlreg.h
> --- /usr/src/sys.old/pci/if_xlreg.h	Tue Mar 25 19:50:52 2003
> +++ /usr/src/sys/pci/if_xlreg.h	Tue Mar 25 21:28:53 2003
> _at__at_ -420,7 +420,7 _at__at_
>  
>  #define XL_LAST_FRAG		0x80000000
>  
> -#define XL_MAXFRAGS		63
> +#define XL_MAXFRAGS		10
>  #define XL_RX_LIST_CNT		128
>  #define XL_TX_LIST_CNT		256
>  #define XL_RX_LIST_SZ		XL_RX_LIST_CNT * sizeof(struct xl_list_onefrag)
> diff -u -r /usr/src/sys.old/sys/mbuf.h /usr/src/sys/sys/mbuf.h
> --- /usr/src/sys.old/sys/mbuf.h	Tue Mar 25 19:50:46 2003
> +++ /usr/src/sys/sys/mbuf.h	Wed Mar 26 19:59:26 2003
> _at__at_ -430,6 +430,7 _at__at_
>  struct	mbuf	*m_copym(struct mbuf *, int, int, int);
>  struct	mbuf	*m_copypacket(struct mbuf *, int);
>  void		 m_copy_pkthdr(struct mbuf *, struct mbuf *);
> +struct	mbuf	*m_defrag(struct mbuf *, int, int);
>  struct	mbuf	*m_devget(char *, int, int, struct ifnet *,
>  		    void (*)(char *, caddr_t, u_int));
>  struct	mbuf	*m_dup(struct mbuf *, int);


-- 
Bosko Milekic
bmilekic_at_unixdaemons.com
bmilekic_at_FreeBSD.org
Received on Thu Mar 27 2003 - 08:44:10 UTC