From eugen@eg.sd.rdtc.ru  Wed Sep 18 19:22:27 2013
Return-Path: <eugen@eg.sd.rdtc.ru>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1])
	(using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
	(No client certificate requested)
	by hub.freebsd.org (Postfix) with ESMTP id 67E08E1D
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 18 Sep 2013 19:22:27 +0000 (UTC)
	(envelope-from eugen@eg.sd.rdtc.ru)
Received: from eg.sd.rdtc.ru (eg.sd.rdtc.ru [IPv6:2a03:3100:c:13::5])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(No client certificate requested)
	by mx1.freebsd.org (Postfix) with ESMTPS id B11EC20C3
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 18 Sep 2013 19:22:25 +0000 (UTC)
Received: from eg.sd.rdtc.ru (localhost [127.0.0.1])
	by eg.sd.rdtc.ru (8.14.7/8.14.7) with ESMTP id r8IJMLPQ064603;
	Thu, 19 Sep 2013 02:22:21 +0700 (NOVT)
	(envelope-from eugen@eg.sd.rdtc.ru)
Received: (from eugen@localhost)
	by eg.sd.rdtc.ru (8.14.7/8.14.7/Submit) id r8IJMFOV064602;
	Thu, 19 Sep 2013 02:22:15 +0700 (NOVT)
	(envelope-from eugen)
Message-Id: <201309181922.r8IJMFOV064602@eg.sd.rdtc.ru>
Date: Thu, 19 Sep 2013 02:22:15 +0700 (NOVT)
From: Eugene Grosbein <egrosbein@rdtc.ru>
To: FreeBSD-gnats-submit@freebsd.org
Subject: [patch] [ng_mppc] ng_mppc(4) blocks on network errors unconditionaly
X-Send-Pr-Version: 3.114
X-GNATS-Notify:

>Number:         182212
>Category:       kern
>Synopsis:       [patch] [ng_mppc] ng_mppc(4) blocks on network errors unconditionaly
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-net
>State:          patched
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Sep 18 19:30:00 UTC 2013
>Closed-Date:    
>Last-Modified:  Thu May 22 07:30:00 UTC 2014
>Originator:     Eugene Grosbein
>Release:        FreeBSD 8.4-STABLE amd64
>Organization:
RDTC JSC
>Environment:
System: FreeBSD eg.sd.rdtc.ru 8.4-STABLE FreeBSD 8.4-STABLE #2 r251830M: Mon Jun 17 18:05:24 NOVT 2013 root@eg.sd.rdtc.ru:/usr/local/obj/usr/local/src/sys/EG amd64

>Description:
	Netgraph node ng_mppc(4) is used by mpd daemon to implement
	MPPC/MPPE for Compression Control Protocol (CCP) used with various
	PPP tunnels (pptp/l2tp/etc.)

	This node blocks itself when "too many" packets got dropped in between
	PPP peers and MPPE should do "re-keying". The threshold is hardcoded
	in its code. The code considers "re-keying" as too CPU intensive task.
	Thus, it tries to protect the box from DoS.
	This code dates back to year 2000.

	When such event occcurs, PPP tunnel hangs: CCP does not get reset,
	IP packets cannot pass tunnel anymore but system interface "looks fine".

	These days mpd runs on multi-MHZ and GHZ boxes and may be used
	not for BRAS'es with lots of tunnels but to form VPN between a pair
	of routers. In the latter case, manual reset of mpd link is required
	to revive VPN tunnel.


>How-To-Repeat:
	
	Run PPtP or L2TP tunnel between two mpd servers over WAN link
	with non-zero amount of packet drops and/or packet rearrangements
	having MPPC/MPPE enabled. Soon, you will get a message in the dmesg
	buffer similar to:

ng_mppc_decompress: too many (4094) packets dropped, disabling node 0xc7020900!

	Then tunnel just hangs until manually restarted as LCP echos
	cannot detect this problem.

>Fix:

	Let's system administrator decides if such behavour is needed.
	The following patch introduces new sysctl subtree "net.graph.mppe"
	with three read/write sysctls (each one is loader tunnable too):

net.graph.mppe.block_on_max_rekey - non-zero value means current behavour,
zero disables node block;

net.graph.mppe.mppe_log_max_rekey - non-zero value permits to write messages
to the log to notify of described event;

net.graph.mppe.max_rekey - allows to change the threshold.

	By default, node block is prohibited and mpd just resets CCP
	and tunnel continues to work. Mpd writes a line like this to its log:

CCP: SendResetReq #3 link 0 (Opened)
	
	At the another side, next line is written to mpd log:

CCP: rec'd Reset Request #3 (Opened)

--- sys/netgraph/ng_mppc.c.orig	2013-04-07 01:07:27.000000000 +0700
+++ sys/netgraph/ng_mppc.c	2013-09-19 01:54:54.000000000 +0700
@@ -55,6 +55,7 @@
 #include <sys/malloc.h>
 #include <sys/endian.h>
 #include <sys/errno.h>
+#include <sys/sysctl.h>
 #include <sys/syslog.h>
 
 #include <netgraph/ng_message.h>
@@ -107,6 +108,23 @@
  */
 #define MPPE_MAX_REKEY		1000
 
+SYSCTL_NODE(_net_graph, OID_AUTO, mppe, CTLFLAG_RW, 0, "MPPE");
+
+static int mppe_block_on_max_rekey = 0;
+TUNABLE_INT("net.graph.mppe.block_on_max_rekey", &mppe_block_on_max_rekey);
+SYSCTL_INT(_net_graph_mppe, OID_AUTO, block_on_max_rekey, CTLFLAG_RW,
+    &mppe_block_on_max_rekey, 0, "Block node on max MPPE key re-calculations");
+
+static int mppe_log_max_rekey = 1;
+TUNABLE_INT("net.graph.mppe.log_max_rekey", &mppe_log_max_rekey);
+SYSCTL_INT(_net_graph_mppe, OID_AUTO, log_max_rekey, CTLFLAG_RW,
+    &mppe_log_max_rekey, 0, "Log max MPPE key re-calculations event");
+
+static int mppe_max_rekey = MPPE_MAX_REKEY;
+TUNABLE_INT("net.graph.mppe.max_rekey", &mppe_max_rekey);
+SYSCTL_INT(_net_graph_mppe, OID_AUTO, max_rekey, CTLFLAG_RW,
+    &mppe_max_rekey, 0, "Maximum number of MPPE key re-calculations");
+
 /* MPPC packet header bits */
 #define MPPC_FLAG_FLUSHED	0x8000		/* xmitter reset state */
 #define MPPC_FLAG_RESTART	0x4000		/* compress history restart */
@@ -651,12 +669,23 @@
 			/* How many times are we going to have to re-key? */
 			rekey = ((d->cfg.bits & MPPE_STATELESS) != 0) ?
 			    numLost : (numLost / (MPPE_UPDATE_MASK + 1));
-			if (rekey > MPPE_MAX_REKEY) {
-				log(LOG_ERR, "%s: too many (%d) packets"
-				    " dropped, disabling node %p!",
-				    __func__, numLost, node);
+			if (rekey > mppe_max_rekey) {
+			    if (mppe_block_on_max_rekey) {
+				if (mppe_log_max_rekey) {
+				    log(LOG_ERR, "%s: too many (%d) packets"
+					" dropped, disabling node %p!\n",
+					__func__, numLost, node);
+				}
 				priv->recv.cfg.enable = 0;
 				goto failed;
+			    } else {
+				if (mppe_log_max_rekey) {
+				    log(LOG_ERR, "%s: %d packets"
+					" dropped, node %p\n",
+					__func__, numLost, node);
+				}
+				goto failed;
+			    }
 			}
 
 			/* Re-key as necessary to catch up to peer */

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-net 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Sep 19 02:35:33 UTC 2013 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=182212 
State-Changed-From-To: open->patched 
State-Changed-By: mav 
State-Changed-When: Thu May 22 07:27:24 UTC 2014 
State-Changed-Why:  
Patch committed to HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=182212 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/182212: commit references a PR
Date: Thu, 22 May 2014 07:27:08 +0000 (UTC)

 Author: mav
 Date: Thu May 22 07:27:04 2014
 New Revision: 266538
 URL: http://svnweb.freebsd.org/changeset/base/266538
 
 Log:
   Make ng_mppc to not disable the node in case of multiple packet loss.
   Quite often it can be just packet reorder, and killing link in such case
   is inconvenient.  Add few sysctl's to control that behavior.
   
   PR:		kern/182212
   Submitted by:	Eugene Grosbein <egrosbein@rdtc.ru>
   MFC after:	2 weeks
 
 Modified:
   head/sys/netgraph/ng_mppc.c
 
 Modified: head/sys/netgraph/ng_mppc.c
 ==============================================================================
 --- head/sys/netgraph/ng_mppc.c	Thu May 22 07:25:36 2014	(r266537)
 +++ head/sys/netgraph/ng_mppc.c	Thu May 22 07:27:04 2014	(r266538)
 @@ -55,6 +55,7 @@
  #include <sys/malloc.h>
  #include <sys/endian.h>
  #include <sys/errno.h>
 +#include <sys/sysctl.h>
  #include <sys/syslog.h>
  
  #include <netgraph/ng_message.h>
 @@ -107,6 +108,23 @@ static MALLOC_DEFINE(M_NETGRAPH_MPPC, "n
   */
  #define MPPE_MAX_REKEY		1000
  
 +SYSCTL_NODE(_net_graph, OID_AUTO, mppe, CTLFLAG_RW, 0, "MPPE");
 +
 +static int mppe_block_on_max_rekey = 0;
 +TUNABLE_INT("net.graph.mppe.block_on_max_rekey", &mppe_block_on_max_rekey);
 +SYSCTL_INT(_net_graph_mppe, OID_AUTO, block_on_max_rekey, CTLFLAG_RW,
 +    &mppe_block_on_max_rekey, 0, "Block node on max MPPE key re-calculations");
 +
 +static int mppe_log_max_rekey = 1;
 +TUNABLE_INT("net.graph.mppe.log_max_rekey", &mppe_log_max_rekey);
 +SYSCTL_INT(_net_graph_mppe, OID_AUTO, log_max_rekey, CTLFLAG_RW,
 +    &mppe_log_max_rekey, 0, "Log max MPPE key re-calculations event");
 +
 +static int mppe_max_rekey = MPPE_MAX_REKEY;
 +TUNABLE_INT("net.graph.mppe.max_rekey", &mppe_max_rekey);
 +SYSCTL_INT(_net_graph_mppe, OID_AUTO, max_rekey, CTLFLAG_RW,
 +    &mppe_max_rekey, 0, "Maximum number of MPPE key re-calculations");
 +
  /* MPPC packet header bits */
  #define MPPC_FLAG_FLUSHED	0x8000		/* xmitter reset state */
  #define MPPC_FLAG_RESTART	0x4000		/* compress history restart */
 @@ -646,12 +664,23 @@ ng_mppc_decompress(node_p node, struct m
  			/* How many times are we going to have to re-key? */
  			rekey = ((d->cfg.bits & MPPE_STATELESS) != 0) ?
  			    numLost : (numLost / (MPPE_UPDATE_MASK + 1));
 -			if (rekey > MPPE_MAX_REKEY) {
 -				log(LOG_ERR, "%s: too many (%d) packets"
 -				    " dropped, disabling node %p!",
 -				    __func__, numLost, node);
 +			if (rekey > mppe_max_rekey) {
 +			    if (mppe_block_on_max_rekey) {
 +				if (mppe_log_max_rekey) {
 +				    log(LOG_ERR, "%s: too many (%d) packets"
 +					" dropped, disabling node %p!\n",
 +					__func__, numLost, node);
 +				}
  				priv->recv.cfg.enable = 0;
  				goto failed;
 +			    } else {
 +				if (mppe_log_max_rekey) {
 +				    log(LOG_ERR, "%s: %d packets"
 +					" dropped, node %p\n",
 +					__func__, numLost, node);
 +				}
 +				goto failed;
 +			    }
  			}
  
  			/* Re-key as necessary to catch up to peer */
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
>Unformatted:
