kern/62957: When created dummynet pipe on output routerinterface with lower MTU system stops to generate 'Fragment Needed but DF was Set' ICMP in cases when it must

Alexander Motin mav at alkar.net
Mon Feb 23 08:30:35 PST 2004


The following reply was made to PR kern/62957; it has been noted by GNATS.

From: Alexander Motin <mav at alkar.net>
To: freebsd-gnats-submit at FreeBSD.org
Cc:  
Subject: Re: kern/62957: When created dummynet pipe on output router interface
 with lower MTU system stops to generate 'Fragment Needed but DF was Set'
 ICMP in cases when it must
Date: Mon, 23 Feb 2004 18:23:33 +0200

 This is a multi-part message in MIME format.
 --------------070208060804030100000702
 Content-Type: text/plain; charset=us-ascii; format=flowed
 Content-Transfer-Encoding: 7bit
 
 Here are my patches for this problem for 4.8 and 5.2.
 Review them please.
 
 -- 
 Alexander Motin mav at alkar.net
 ISP "Alkar-Teleport"
 
 --------------070208060804030100000702
 Content-Type: text/plain;
  name="dn_df_48.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="dn_df_48.patch"
 
 --- ip_dummynet.c.orig	Wed May 28 01:36:02 2003
 +++ ip_dummynet.c	Sat Feb 21 12:49:11 2004
 @@ -81,6 +81,7 @@
  #include <netinet/ip_fw.h>
  #include <netinet/ip_dummynet.h>
  #include <netinet/ip_var.h>
 +#include <netinet/ip_icmp.h>
  
  #include <netinet/if_ether.h> /* for struct arpcom */
  #include <net/bridge.h>
 @@ -407,6 +408,9 @@
  transmit_event(struct dn_pipe *pipe)
  {
      struct dn_pkt *pkt ;
 +    struct mbuf *mcopy;
 +    struct ip *ip;
 +    int error, type, code;
  
      while ( (pkt = pipe->head) && DN_KEY_LEQ(pkt->output_time, curr_time) ) {
  	/*
 @@ -426,7 +430,39 @@
  	 */
  	switch (pkt->dn_dir) {
  	case DN_TO_IP_OUT:
 -	    (void)ip_output((struct mbuf *)pkt, NULL, NULL, 0, NULL, NULL);
 +	    MGET(mcopy, M_DONTWAIT, pkt->dn_m->m_type);
 +	    if (mcopy != NULL && !m_dup_pkthdr(mcopy, pkt->dn_m, M_DONTWAIT)) {
 +		m_free(mcopy);
 +		mcopy = NULL;
 +	    }
 +	    if (mcopy != NULL) {
 +		ip = mtod(pkt->dn_m, struct ip *);
 +		mcopy->m_len = imin((ip->ip_hl << 2) + 8,
 +		    (int)ip->ip_len);
 +		m_copydata(pkt->dn_m, 0, mcopy->m_len, mtod(mcopy, caddr_t));
 +	    }
 +	    
 +	    error = ip_output((struct mbuf *)pkt, NULL, NULL, 0, NULL, NULL);
 +	    
 +	    if (mcopy != NULL) {
 +		switch (error) {
 +		    case ENETUNREACH:
 +		    case EHOSTUNREACH:
 +		    case ENETDOWN:
 +		    case EHOSTDOWN:
 +			type = ICMP_UNREACH;
 +		        code = ICMP_UNREACH_HOST;
 +			icmp_error(mcopy, type, code, 0, pkt->ifp);
 +			break;
 +		    case EMSGSIZE:
 +			type = ICMP_UNREACH;
 +		        code = ICMP_UNREACH_NEEDFRAG;
 +			icmp_error(mcopy, type, code, 0, pkt->ifp);
 +			break;
 +		    default:
 +			m_freem(mcopy);
 +		};
 +	    };
  	    rt_unref (pkt->ro.ro_rt) ;
  	    break ;
  
 
 --------------070208060804030100000702
 Content-Type: text/plain;
  name="dn_df_52.patch"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: inline;
  filename="dn_df_52.patch"
 
 --- ip_dummynet.c.orig	Mon Dec  8 11:50:54 2003
 +++ ip_dummynet.c	Sat Feb 21 12:17:44 2004
 @@ -73,6 +73,7 @@
  #include <netinet/ip_fw.h>
  #include <netinet/ip_dummynet.h>
  #include <netinet/ip_var.h>
 +#include <netinet/ip_icmp.h>
  
  #include <netinet/if_ether.h> /* for struct arpcom */
  #include <net/bridge.h>
 @@ -426,6 +427,9 @@
  transmit_event(struct dn_pipe *pipe)
  {
      struct dn_pkt *pkt ;
 +    struct mbuf *mcopy;
 +    struct ip *ip;
 +    int error, type, code;
  
      DUMMYNET_LOCK_ASSERT();
  
 @@ -449,7 +453,39 @@
  	 */
  	switch (pkt->dn_dir) {
  	case DN_TO_IP_OUT:
 -	    (void)ip_output((struct mbuf *)pkt, NULL, NULL, 0, NULL, NULL);
 +	    MGET(mcopy, M_DONTWAIT, pkt->dn_m->m_type);
 +	    if (mcopy != NULL && !m_dup_pkthdr(mcopy, pkt->dn_m, M_DONTWAIT)) {
 +		m_free(mcopy);
 +		mcopy = NULL;
 +	    }
 +	    if (mcopy != NULL) {
 +		ip = mtod(pkt->dn_m, struct ip *);
 +		mcopy->m_len = imin((ip->ip_hl << 2) + 8,
 +		    (int)ip->ip_len);
 +		m_copydata(pkt->dn_m, 0, mcopy->m_len, mtod(mcopy, caddr_t));
 +	    }
 +	    
 +	    error = ip_output((struct mbuf *)pkt, NULL, NULL, 0, NULL, NULL);
 +	    
 +	    if (mcopy != NULL) {
 +		switch (error) {
 +		    case ENETUNREACH:
 +		    case EHOSTUNREACH:
 +		    case ENETDOWN:
 +		    case EHOSTDOWN:
 +			type = ICMP_UNREACH;
 +		        code = ICMP_UNREACH_HOST;
 +			icmp_error(mcopy, type, code, 0, pkt->ifp);
 +			break;
 +		    case EMSGSIZE:
 +			type = ICMP_UNREACH;
 +		        code = ICMP_UNREACH_NEEDFRAG;
 +			icmp_error(mcopy, type, code, 0, pkt->ifp);
 +			break;
 +		    default:
 +			m_freem(mcopy);
 +		};
 +	    };
  	    rt_unref (pkt->ro.ro_rt, __func__) ;
  	    break ;
  
 
 --------------070208060804030100000702--


More information about the freebsd-bugs mailing list