git: d9aecafba755 - main - net/mpd5: fix some LCP negotiation problems

From: Eugene Grosbein <eugen_at_FreeBSD.org>
Date: Tue, 13 Sep 2022 09:44:28 UTC
The branch main has been updated by eugen:

URL: https://cgit.FreeBSD.org/ports/commit/?id=d9aecafba755cf46596c08f80516348aaeb5a452

commit d9aecafba755cf46596c08f80516348aaeb5a452
Author:     Eugene Grosbein <eugen@FreeBSD.org>
AuthorDate: 2022-09-13 09:32:20 +0000
Commit:     Eugene Grosbein <eugen@FreeBSD.org>
CommitDate: 2022-09-13 09:42:24 +0000

    net/mpd5: fix some LCP negotiation problems
    
    * Import upstream r2453: prevent endless LCP restarts in case of broken
    peer or heavy packet drops. Allow 3 restarts then terminate LCP.
    Let link redial restart it from the beginning, if configured.
    
    * Import upstream r2454: fixes long-standing bug
    known as "LCP: not converging" problem leaving link closed
    with erroneously disabled redial.
---
 net/mpd5/files/patch-redial | 174 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/net/mpd5/files/patch-redial b/net/mpd5/files/patch-redial
new file mode 100644
index 000000000000..b8f8c18d28c1
--- /dev/null
+++ b/net/mpd5/files/patch-redial
@@ -0,0 +1,174 @@
+Index: src/lcp.c
+===================================================================
+--- src/lcp.c	(revision 2452)
++++ src/lcp.c	(revision 2454)
+@@ -26,6 +26,7 @@
+ 
+   #define LCP_ECHO_INTERVAL	5	/* Enable keep alive by default */
+   #define LCP_ECHO_TIMEOUT	40
++  #define LCP_MAX_RESETS	3
+ 
+   #define LCP_KNOWN_CODES	(   (1 << CODE_CONFIGREQ)	\
+ 				  | (1 << CODE_CONFIGACK)	\
+@@ -180,6 +181,7 @@ LcpInit(Link l)
+   FsmInit(&lcp->fsm, &gLcpFsmType, l);
+   lcp->fsm.conf.echo_int = LCP_ECHO_INTERVAL;
+   lcp->fsm.conf.echo_max = LCP_ECHO_TIMEOUT;
++  lcp->resets = LCP_MAX_RESETS;
+   lcp->phase = PHASE_DEAD;
+   
+   AuthInit(l);
+@@ -690,8 +692,17 @@ LcpLayerDown(Fsm fp)
+     LcpState	const lcp = &l->lcp;
+ 
+     LcpStopActivity(l);
+-    if (lcp->phase == PHASE_AUTHENTICATE || lcp->phase == PHASE_NETWORK)
++    if (lcp->phase == PHASE_AUTHENTICATE || lcp->phase == PHASE_NETWORK) {
+       lcp->need_reset = 1;
++      if (lcp->resets > 0) {
++	Log(LG_LCP2, ("[%s] LCP: Reset (%u left)", l->name, (int)lcp->resets));
++	lcp->resets--;
++      } else {
++        Log(LG_LCP2, ("[%s] LCP: Too many resets", l->name));
++	FsmFailure(&lcp->fsm, FAIL_NEGOT_FAILURE);
++	lcp->resets = LCP_MAX_RESETS;
++      }
++    }
+ }
+ 
+ void LcpOpen(Link l)
+Index: src/lcp.h
+===================================================================
+--- src/lcp.h	(revision 2452)
++++ src/lcp.h	(revision 2454)
+@@ -87,6 +87,7 @@
+     struct fsm	fsm;			/* Finite state machine */
+     
+     u_char	need_reset;		/* LCP needs complete reset before ConfReq */
++    u_char	resets;			/* LCP resets left before failure */
+   };
+   typedef struct lcpstate	*LcpState;
+ 
+Index: src/link.c
+===================================================================
+--- src/link.c	(revision 2452)
++++ src/link.c	(revision 2454)
+@@ -52,6 +52,17 @@
+     SET_NO
+   };
+ 
++  /* Used to prevent auto-up on links closed manually */
++  enum {
++    LINK_ADMINSTATE_DOWN = 0,
++    LINK_ADMINSTATE_OPERATIONAL
++  };
++
++  static const char *linkAdminStateNames[] = {
++    "DOWN",
++    "OPERATIONAL"
++  };
++  
+   #define RBUF_SIZE		100
+ 
+ /*
+@@ -193,6 +204,7 @@ LinkOpenCmd(Context ctx)
+ {
+     if (ctx->lnk->tmpl)
+ 	Error("impossible to open template");
++    ctx->lnk->admin_state = LINK_ADMINSTATE_OPERATIONAL;
+     RecordLinkUpDownReason(NULL, ctx->lnk, 1, STR_MANUALLY, NULL);
+     LinkOpen(ctx->lnk);
+     return (0);
+@@ -207,6 +219,7 @@ LinkCloseCmd(Context ctx)
+ {
+     if (ctx->lnk->tmpl)
+ 	Error("impossible to close template");
++    ctx->lnk->admin_state = LINK_ADMINSTATE_DOWN;
+     RecordLinkUpDownReason(NULL, ctx->lnk, 0, STR_MANUALLY, NULL);
+     LinkClose(ctx->lnk);
+     return (0);
+@@ -258,7 +271,7 @@ LinkDown(Link l)
+ {
+     Log(LG_LINK, ("[%s] Link: DOWN event", l->name));
+ 
+-    if (OPEN_STATE(l->lcp.fsm.state)) {
++    if (OPEN_STATE(l->lcp.fsm.state) || l->admin_state != LINK_ADMINSTATE_DOWN) {
+ 	if (((l->conf.max_redial != 0) && (l->num_redial >= l->conf.max_redial)) ||
+ 	    gShutdownInProgress) {
+ 	    if (l->conf.max_redial >= 0) {
+@@ -307,6 +320,8 @@ LinkReopenTimeout(void *arg)
+     Log(LG_LINK, ("[%s] Link: reconnection attempt %hu",
+ 	l->name, l->num_redial));
+     RecordLinkUpDownReason(NULL, l, 1, STR_REDIAL, NULL);
++    if (!OPEN_STATE(l->lcp.fsm.state))
++	LinkOpen(l);
+     PhysOpen(l);
+ }
+ 
+@@ -411,6 +426,7 @@ LinkCreate(Context ctx, int ac, const char *const av[]
+ 	strlcpy(l->name, av[0 + stay], sizeof(l->name));
+ 	l->type = pt;
+ 	l->tmpl = tmpl;
++	l->admin_state = LINK_ADMINSTATE_OPERATIONAL;
+ 	l->stay = stay;
+ 	l->parent = -1;
+ 	SLIST_INIT(&l->actions);
+@@ -551,6 +567,7 @@ LinkInst(Link lt, const char *name, int tmpl, int stay
+ 	    SLIST_INSERT_AFTER(ap, a, next);
+ 	ap = a;
+     }
++    l->admin_state = LINK_ADMINSTATE_OPERATIONAL;
+     l->tmpl = tmpl;
+     l->stay = stay;
+     /* Count link as one more child of parent. */
+@@ -1321,6 +1338,7 @@ LinkStat(Context ctx, int ac, const char *const av[], 
+ 	Printf("\tChildren       : %d\r\n", l->children);
+     else {
+ 	Printf("\tState          : %s\r\n", gPhysStateNames[l->state]);
++	Printf("\tAdmin. state   : %s\r\n", linkAdminStateNames[l->admin_state]);
+ 	Printf("\tSession Id     : %s\r\n", l->session_id);
+ 	Printf("\tPeer ident     : %s\r\n", l->lcp.peer_ident);
+ 	if (l->state == PHYS_STATE_UP)
+Index: src/link.h
+===================================================================
+--- src/link.h	(revision 2452)
++++ src/link.h	(revision 2454)
+@@ -115,7 +115,8 @@
+     int			id;			/* Index of this link in gLinks */
+     u_char		tmpl;			/* This is template, not an instance */
+     u_char		stay;			/* Must not disappear */
+-    u_char		state;			/* Device current state */
++    u_char		state;			/* Physical device current state */
++    u_char		admin_state;		/* Link administrative state */
+     u_char		joined_bund;		/* Link successfully joined bundle */
+     u_char		originate;		/* Who originated the connection */
+     u_char		die;			/* LCP agreed to die */
+Index: src/phys.c
+===================================================================
+--- src/phys.c	(revision 2452)
++++ src/phys.c	(revision 2454)
+@@ -590,8 +590,8 @@ PhysMsg(int type, void *arg)
+ 	UNREF(l);
+ 	return;
+     }
+-    Log(LG_PHYS2, ("[%s] device: %s event",
+-	l->name, MsgName(type)));
++    Log(LG_PHYS2, ("[%s] device: %s event in state %s",
++	l->name, MsgName(type), gPhysStateNames[l->state]));
+     switch (type) {
+     case MSG_OPEN:
+     	l->downReasonValid=0;
+@@ -599,7 +599,12 @@ PhysMsg(int type, void *arg)
+ 	    PhysUp(l);
+ 	    break;
+ 	}
+-        (*l->type->open)(l);
++	/* Redial may result in MSG_OPEN for just opened device */
++	if (l->state == PHYS_STATE_DOWN)
++	    (*l->type->open)(l);
++	else
++	    Log(LG_PHYS2, ("[%s] device: OPEN event ignored",
++		l->name));
+         break;
+     case MSG_CLOSE:
+         (*l->type->close)(l);