Subject: Reducing error packets sent back.
To: None <tech-net@netbsd.org>
From: Darren Reed <avalon@coombs.anu.edu.au>
List: tech-net
Date: 01/21/2000 17:09:15
Should we be thinking of adding a knob to control how frequently
NetBSD sends out ICMP unreachables ? Below I've got a patch which
I just hacked up (untested :) which provides a knob in sysctl to
control how often to actually send an ICMP error back. I've added
a patch which uses the same knob for ICMP6 (an ICMP error is an
ICMP error, be it v4 or v6).
It should show up as:
net.inet.icmp.errrate
and defaults to 1 (send a reply back every packet). It surplants
ICMPCTL_MTUDISC (appears to have moved to IP) with ICMPCTL_ERRRATE.
Setting it to 0 turns off sending back ICMP error replies, whereas
a positive number means every nth packet. I've added stat to count
the number of times it skips sending a packet.
This selective sending of ICMP errors is pretty common now.
Comments ?
btw, is it worthwhile adding a similar knob to TCP to throttle the
sending back of RST's ?
Darren
*** netinet/icmp_var.h.orig Fri Jan 21 16:41:17 2000
--- netinet/icmp_var.h Fri Jan 21 16:47:39 2000
***************
*** 45,50 ****
--- 45,51 ----
struct icmpstat {
/* statistics related to icmp packets generated */
u_quad_t icps_error; /* # of calls to icmp_error */
+ u_quad_t icps_skip; /* # of times we skiped sending */
u_quad_t icps_oldshort; /* no error 'cuz old ip too short */
u_quad_t icps_oldicmp; /* no error 'cuz old was icmp */
u_quad_t icps_outhist[ICMP_MAXTYPE + 1];
***************
*** 61,72 ****
* Names for ICMP sysctl objects
*/
#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */
! #define ICMPCTL_MTUDISC 2 /* allow path MTU discovery */
#define ICMPCTL_MAXID 3
#define ICMPCTL_NAMES { \
{ 0, 0 }, \
{ "maskrepl", CTLTYPE_INT }, \
}
#ifdef _KERNEL
--- 62,74 ----
* Names for ICMP sysctl objects
*/
#define ICMPCTL_MASKREPL 1 /* allow replies to netmask requests */
! #define ICMPCTL_ERRRATE 2 /* flow control of ICMP error replies*/
#define ICMPCTL_MAXID 3
#define ICMPCTL_NAMES { \
{ 0, 0 }, \
{ "maskrepl", CTLTYPE_INT }, \
+ { "errrate", CTLTYPE_INT }, \
}
#ifdef _KERNEL
*** netinet/ip_icmp.c.orig Fri Jan 21 16:35:23 2000
--- netinet/ip_icmp.c Fri Jan 21 17:02:30 2000
***************
*** 142,150 ****
--- 142,152 ----
*/
int icmpmaskrepl = 0;
+ int icmperrrate = 1;
#ifdef ICMPPRINTFS
int icmpprintfs = 0;
#endif
+ int icmp_error_calls = 0;
#if 0
static int ip_next_mtu __P((int, int));
***************
*** 196,201 ****
--- 198,211 ----
/* Don't send error in response to a multicast or broadcast packet */
if (n->m_flags & (M_BCAST|M_MCAST))
goto freeit;
+ /* Flow control for sending ICMP error messages back */
+ icmp_error_calls++;
+ if (icmp_error_calls != icmperrrate) {
+ icmpstat.icps_skip++;
+ goto freeit;
+ }
+ icmp_error_calls = 0;
+
/*
* First, formulate icmp message
*/
***************
*** 729,734 ****
--- 739,746 ----
switch (name[0]) {
case ICMPCTL_MASKREPL:
return (sysctl_int(oldp, oldlenp, newp, newlen, &icmpmaskrepl));
+ case ICMPCTL_ERRRATE:
+ return (sysctl_int(oldp, oldlenp, newp, newlen, &icmperrrate));
default:
return (ENOPROTOOPT);
}
*** netinet6/icmp6.c.orig Fri Jan 21 16:59:41 2000
--- netinet6/icmp6.c Fri Jan 21 17:04:28 2000
***************
*** 117,122 ****
--- 117,124 ----
extern int icmp6_nodeinfo;
static struct rttimer_queue *icmp6_mtudisc_timeout_q = NULL;
extern int pmtu_expire;
+ extern int icmp_error_calls;
+ extern int icmperrrate;
static int icmp6_rip6_input __P((struct mbuf **, int));
static int icmp6_ratelimit __P((const struct in6_addr *, const int, const int));
***************
*** 280,285 ****
--- 282,295 ----
goto freeit;
}
+ /* Flow control for sending ICMP error messages back */
+ icmp_error_calls++;
+ if (icmp_error_calls != icmperrrate) {
+ icmp6stat.icp6s_skip++;
+ goto freeit;
+ }
+ icmp_error_calls = 0;
+
/*
* OK, ICMP6 can be generated.
*/
*** netinet6/icmp6.h.orig Fri Jan 21 17:00:13 2000
--- netinet6/icmp6.h Fri Jan 21 17:00:53 2000
***************
*** 500,505 ****
--- 500,506 ----
struct icmp6stat {
/* statistics related to icmp6 packets generated */
u_quad_t icp6s_error; /* # of calls to icmp6_error */
+ u_quad_t icp6s_skip; /* # of times we skiped sending */
u_quad_t icp6s_canterror; /* no error 'cuz old was icmp */
u_quad_t icp6s_toofreq; /* no error 'cuz rate limitation */
u_quad_t icp6s_outhist[256];