Index: /branches/rel_apv_10_7_4/usr/click/lib/libtune/tune.c
===================================================================
--- /branches/rel_apv_10_7_4/usr/click/lib/libtune/tune.c	(revision 39971)
+++ /branches/rel_apv_10_7_4/usr/click/lib/libtune/tune.c	(working copy)
@@ -166,6 +166,9 @@
 
 #define ICMPLIM_SYSCTL			"net.inet.icmp.icmplim"
 
+/* TWSD-1571: Non-VNET sysctl in ip_icmp.c, used by badport_bandlim() */
+#define ICMPLIM_GLOBAL_SYSCTL		"net.inet.icmp.icmplim_global"
+
 #define GET_CPUS_SYSCTL        "kern.cpus"
 
 #define RTOS_CONF_ST_SYSCTL    "net.inet.clicktcp.rtos_conf_state"
@@ -3866,7 +3869,7 @@
 
 
 ca_errcode_t
-ui_tune_icmp_reply_limit(uint32_t limit) 
+ui_tune_icmp_reply_limit(uint32_t limit)
 {
 	if (limit > ICMP_LIMIT_MAX) {
 		printf("Value range 0 to %d\n", ICMP_LIMIT_MAX);
@@ -3876,6 +3879,8 @@
 		perror("Error setting icmp replylimit value");
 		return -1;
 	}
+	/* TWSD-1571: Also set non-VNET global used by badport_bandlim() */
+	sysctlbyname(ICMPLIM_GLOBAL_SYSCTL, NULL, NULL, &limit, sizeof(limit));
 	return 0;
 }
 
@@ -3888,6 +3893,8 @@
 		perror("Error setting icmp replylimit value");
 		return -1;
 	}
+	/* TWSD-1571: Also set non-VNET global used by badport_bandlim() */
+	sysctlbyname(ICMPLIM_GLOBAL_SYSCTL, NULL, NULL, &limit, sizeof(limit));
 	return 0;
 }
 
Index: /branches/rel_apv_10_7_4/usr/src/sys/click/net/click_ether.c
===================================================================
--- /branches/rel_apv_10_7_4/usr/src/sys/click/net/click_ether.c	(revision 39971)
+++ /branches/rel_apv_10_7_4/usr/src/sys/click/net/click_ether.c	(working copy)
@@ -33,6 +33,7 @@
 #include <netinet/ip.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_icmp.h>
+#include <netinet/icmp_var.h>
 #include <netinet/tcp.h>
 #include <netinet/tcp_seq.h>
 #include <netinet/tcpip.h>
@@ -2536,7 +2537,7 @@
 	}
 
 	/* If not management traffic, do bandwidth limit */
-	if ((ret != CLICKTCP_ERR_PACKET) && 
+	if ((ret != CLICKTCP_ERR_PACKET) &&
 		(ret != CLICKTCP_NOT_OUR_PACKET_IS_MGMT)) {
 		if (bandwidth_deny(m)) {
 			m_freem(m);
@@ -2683,6 +2684,36 @@
 			break;
 		case IPPROTO_ICMP:
 			iph = mtod(m, struct ip *);
+			/* TWSD-1571: Rate limit ICMP echo/tstamp on fast path.
+			 * badport_bandlim() in ATCP thread uses per-VNET icmplim
+			 * which doesn't get the tune command value. Rate limit
+			 * here using icmplim_global (non-VNET, set by tune). */
+			{
+				extern int icmplim_global;
+				extern int ticks;
+				extern int hz;
+				static int icmp_last_tick = 0;
+				static int icmp_curpps = 0;
+				struct icmp *icmph_fast;
+
+				icmph_fast = (struct icmp *)((caddr_t)iph + (iph->ip_hl << 2));
+				if ((icmph_fast->icmp_type == ICMP_ECHO ||
+				    icmph_fast->icmp_type == ICMP_TSTAMP) &&
+				    icmplim_global > 0) {
+					int now = ticks;
+					if (icmp_last_tick == 0 ||
+					    (unsigned)(now - icmp_last_tick) >= (unsigned)hz) {
+						icmp_last_tick = now;
+						icmp_curpps = 1;
+					} else {
+						icmp_curpps++;
+						if (icmp_curpps > icmplim_global) {
+							m_freem(m);
+							return;
+						}
+					}
+				}
+			}
 			if (click_ddos_icmp_deny(GETHDR(iph, icmp), 0)) {
 				m_freem(m);
 				return;
@@ -2808,6 +2839,28 @@
 	}
 
 #ifdef UINET
+	/* TWSD-1571: For ICMP echo/tstamp to port IP (slow path), Linux
+	 * kernel is the rightful responder via KNI. Apply rate limit here,
+	 * send to KNI, and skip BSD (netisr_dispatch) to avoid double replies.
+	 */
+	if (ip_p == IPPROTO_ICMP) {
+		struct icmp *icmph_kni;
+		iph = mtod(m, struct ip *);
+		icmph_kni = (struct icmp *)((caddr_t)iph + (iph->ip_hl << 2));
+		if (icmph_kni->icmp_type == ICMP_ECHO ||
+		    icmph_kni->icmp_type == ICMP_TSTAMP) {
+			if (badport_bandlim(icmph_kni->icmp_type == ICMP_ECHO ?
+			    BANDLIM_ICMP_ECHO : BANDLIM_ICMP_TSTAMP) < 0) {
+				m_freem(m);
+				return;
+			}
+			/* Rate limit passed - send to Linux only, skip BSD */
+			dpdk_kni_ingress(m);
+			m_freem(m);
+			return;
+		}
+	}
+
 	/*send to Linux KNI as well*/
 	dpdk_kni_ingress(m);
 
Index: /branches/rel_apv_10_7_4/usr/src/sys/netinet/ip_icmp.c
===================================================================
--- /branches/rel_apv_10_7_4/usr/src/sys/netinet/ip_icmp.c	(revision 39971)
+++ /branches/rel_apv_10_7_4/usr/src/sys/netinet/ip_icmp.c	(working copy)
@@ -86,6 +86,17 @@
 	&VNET_NAME(icmplim), 0,
 	"Maximum number of ICMP responses per second");
 
+/* TWSD-1571: Non-VNET copy of icmplim for badport_bandlim().
+ * With VIMAGE, V_icmplim is per-VNET. The tune command sets icmplim via
+ * sysctlbyname on uinet_instance_default(), but badport_bandlim() runs
+ * in ATCP threads with different VNETs where icmplim stays at 1000.
+ * This plain global has its own non-VNET sysctl so the tune command
+ * can set it via sysctlbyname without cross-linking issues. */
+int icmplim_global = 1000;
+SYSCTL_INT(_net_inet_icmp, OID_AUTO, icmplim_global, CTLFLAG_RW,
+	&icmplim_global, 0,
+	"Non-VNET ICMP rate limit used by badport_bandlim (TWSD-1571)");
+
 static VNET_DEFINE(int, icmplim_output) = 1;
 #define	V_icmplim_output		VNET(icmplim_output)
 SYSCTL_VNET_INT(_net_inet_icmp, OID_AUTO, icmplim_output, CTLFLAG_RW,
@@ -1000,20 +1011,18 @@
 	/*
 	 * Return ok status if feature disabled or argument out of range.
 	 */
-	if (V_icmplim > 0 && (u_int) which < N(rates)) {
+	/* TWSD-1571: Use icmplim_global instead of V_icmplim.
+	 * V_icmplim is per-VNET and only set in default instance;
+	 * ATCP threads run in different VNETs where it stays 1000. */
+	if (icmplim_global > 0 && (u_int) which < N(rates)) {
 		struct rate *r = &rates[which];
 		int opps = r->curpps;
 
-		if (!ppsratecheck(&r->lasttime, &r->curpps, V_icmplim))
+		if (!ppsratecheck(&r->lasttime, &r->curpps, icmplim_global))
 			return -1;	/* discard packet */
-		/*
-		 * If we've dropped below the threshold after having
-		 * rate-limited traffic print the message.  This preserves
-		 * the previous behaviour at the expense of added complexity.
-		 */
-		if (V_icmplim_output && opps > V_icmplim)
+		if (V_icmplim_output && opps > icmplim_global)
 			log(LOG_NOTICE, "Limiting %s from %d to %d packets/sec\n",
-				r->type, opps, V_icmplim);
+				r->type, opps, icmplim_global);
 	}
 	return 0;			/* okay to send packet */
 #undef N
