Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/is-mlppp]: src/sys/net first part of defragmentation code. No dropping/s...



details:   https://anonhg.NetBSD.org/src/rev/44432312f09e
branches:  is-mlppp
changeset: 930625:44432312f09e
user:      is <is%NetBSD.org@localhost>
date:      Fri Apr 10 17:28:37 2020 +0000

description:
first part of defragmentation code. No dropping/sequence error statistics
yet, and no MRRU negotiation so not active.

diffstat:

 sys/net/if_spppsubr.c |  135 +++++++++++++++++++++++++++++++++++++++++++++++++-
 sys/net/if_spppvar.h  |    4 +-
 2 files changed, 136 insertions(+), 3 deletions(-)

diffs (195 lines):

diff -r 282fdb5de4d5 -r 44432312f09e sys/net/if_spppsubr.c
--- a/sys/net/if_spppsubr.c     Tue Apr 07 19:26:44 2020 +0000
+++ b/sys/net/if_spppsubr.c     Fri Apr 10 17:28:37 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_spppsubr.c,v 1.187.2.3 2020/04/07 19:26:44 is Exp $  */
+/*     $NetBSD: if_spppsubr.c,v 1.187.2.4 2020/04/10 17:28:37 is Exp $  */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.187.2.3 2020/04/07 19:26:44 is Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.187.2.4 2020/04/10 17:28:37 is Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -336,6 +336,9 @@
 static void sppp_lcp_check_and_close(struct sppp *sp);
 static int sppp_ncp_check(struct sppp *sp);
 
+static struct mbuf *sppp_ml_defrag(struct sppp *sp, struct mbuf *m,
+                                   u_int16_t *protocolp);
+
 static void sppp_ipcp_init(struct sppp *sp);
 static void sppp_ipcp_up(struct sppp *sp);
 static void sppp_ipcp_down(struct sppp *sp);
@@ -517,6 +520,123 @@
        }
 }
 
+
+/*
+ * Defragment an MP packet. 
+ *
+ * Returns NULL or an assembled packet or the original,
+ * and adjusts the passed protocol to the inner one.
+ *
+ * Called with and returns a packet without PPP header, 
+ * but with MP fragment header.
+ *
+ * Called and returns with lock held.
+ */
+static struct mbuf *
+sppp_ml_defrag(struct sppp *sp, struct mbuf *m, u_int16_t *protocolp)
+{
+       u_int8_t *p;
+       u_int8_t flags;
+       u_int32_t seqid;
+       u_int16_t protocol;
+       u_int16_t *m_protop;
+       int newflen;
+
+       if (*protocolp != PPP_MP)
+               return m;       /* not ours */
+
+       if (sp->lcp.mrru == 0)
+               return m;       /*
+                                * ours, but we're not ready.
+                                * sppp_input will arrange for rejection.
+                                */
+
+       if (m->m_len < 4) {
+               m = m_pullup(m, 4);
+               if (m == NULL) {
+                       if_statadd2(ifp, if_ierrors, 1, if_iqdrops, 1);
+                       return NULL;
+               }
+       }
+       p = mtod(m, u_int8_t *);
+       flags = *p; 
+       seqid = (p[1]<<16) + (p[2]<<8) + p[3];
+
+       m_adj(m, 4);
+
+       /* We're manipulating the defragmentation state below: */
+       SPPP_UPGRADE(sp);
+
+       if (flags & 0x80) {
+               /* Beginning fragment. */
+               sp->lcp.ml_seq_expected=seqid+1;        /* next expected */
+               
+               /* TODO: if prefix, count dropped? */
+
+               m_freem(sp->lcp.ml_prefix);
+               sp->lcp.ml_prefix = m;
+
+       } else if (seqid == sp->lcp.ml_seq_expected) {
+               sp->lcp.ml_seq_expected=seqid+1;        /* next expected */
+               if (sp->lcp.ml_prefix == 0) {
+                       /* didn't see B frame.  */
+                       /* TODO: count as dropped. */
+                       m_freem(m);
+                       return NULL;
+               }
+               /*
+                * m_cat might free the first mbuf (with pkthdr)
+                * in 2nd chain; therefore:
+                */
+               newflen = m->m_pkthdr.len;
+               m_cat(sp->lcp.ml_prefix, m);
+               lcp.ml_prefix->m_pkthdr.len += newflen;
+
+       } else {
+               /*
+                * sequence error. 
+                *
+                * For now, only drop this fragment, and don't touch state-
+                * might be from the long past or future, and we could still
+                * finish our current prefix.
+                *
+                * TODO: count as dropped.
+                */
+                m_freem(sp->lcp.ml_prefix);
+                return NULL;
+       }
+       /* Successfully got the Beginning or appended a non-B packet.*/
+       if (flags & 0x40) {
+               /* B/next was E packet. Unwrap gift and deliver. */
+               m = sp->lcp.ml_prefix;
+               sp->lcp.ml_prefix = NULL;
+
+               if (m->m_len < 2) {
+                       m = m_pullup(m,2)
+                       if (m == NULL) {
+                               * TODO: count as dropped.
+                               return NULL;
+                       }
+               }
+               /* RFC 1990 2.: don't assume no protocol field compression */
+               p = mtod(m, u_int8_t);
+               protocol = *p;
+               
+               if (protocol & 1) {
+                       m_adj(m, 1);
+               } else {
+                       protocol = (protocol << 8) + p[1];
+                       m_adj(m, 2);
+               }
+               *protocolp = protocol;
+
+               return m;
+       }
+
+       return NULL;
+}
+
+
 /*
  * Exported functions, comprising our interface to the lower layer.
  */
@@ -627,6 +747,12 @@
                protocol = ntohs(h->protocol);
        }
 
+       m = sppp_ml_defrag(sp, m, &protocol);
+       if (m == 0) {
+               SPPP_UNLOCK(sp);
+               return;
+       }
+
        switch (protocol) {
        default:
                if (sp->state[IDX_LCP] == STATE_OPENED) {
@@ -2222,6 +2348,11 @@
        /* Initialize activity timestamp: opening a connection is an activity */
        sp->pp_last_receive = sp->pp_last_activity = time_uptime;
 
+       /* Initialize mlppp state */
+       sp->lcp.mrru = sp->lcp.their_mrru = 0;
+       sp->lcp.ml_prefix = NULL;
+       sp->lcp.ml_seq_expected = 0;
+
        /*
         * If this interface is passive or dial-on-demand, and we are
         * still in Initial state, it means we've got an incoming
diff -r 282fdb5de4d5 -r 44432312f09e sys/net/if_spppvar.h
--- a/sys/net/if_spppvar.h      Tue Apr 07 19:26:44 2020 +0000
+++ b/sys/net/if_spppvar.h      Fri Apr 10 17:28:37 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_spppvar.h,v 1.22.12.2 2020/04/07 18:47:43 is Exp $  */
+/*     $NetBSD: if_spppvar.h,v 1.22.12.3 2020/04/10 17:28:37 is Exp $  */
 
 #ifndef _NET_IF_SPPPVAR_H_
 #define _NET_IF_SPPPVAR_H_
@@ -48,6 +48,8 @@
        /* multilink variables */
        u_long  mrru;           /* our   max received reconstructed unit */
        u_long  their_mrru;     /* their max received reconstructed unit */
+       u_long  ml_seq_xpctd;   /* next seqid we expect to receive */
+       struct mbuf *ml_prefix; /* reassembled packet so far */
 };
 
 #define IDX_IPCP 1             /* idx into state table */



Home | Main Index | Thread Index | Old Index