Bug fixes to flow control code; put correct dlpi header on data
[ppp.git] / svr4 / ppp.c
index c99f426ebfd534234e07deea557009a2126e3386..497a414c2a16c620893b6b4c5d823ea0dd38fd1d 100644 (file)
@@ -24,7 +24,7 @@
  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
  * OR MODIFICATIONS.
  *
- * $Id: ppp.c,v 1.3 1995/05/29 06:59:36 paulus Exp $
+ * $Id: ppp.c,v 1.5 1995/06/23 01:38:49 paulus Exp $
  */
 
 /*
@@ -81,6 +81,7 @@ typedef struct upperstr {
     int req_sap;               /* which SAP the DLPI client requested */
     struct upperstr *ppa;      /* control stream for our ppa */
     struct upperstr *next;     /* next stream for this ppa */
+    uint ioc_id;               /* last ioctl ID for this stream */
     /*
      * There is exactly one control stream for each PPA.
      * The following fields are only used for control streams.
@@ -127,6 +128,7 @@ static int send_data __P((mblk_t *, upperstr_t *));
 static void new_ppa __P((queue_t *, mblk_t *));
 static void attach_ppa __P((queue_t *, mblk_t *));
 static void detach_ppa __P((queue_t *, mblk_t *));
+static void debug_dump __P((queue_t *, mblk_t *));
 static upperstr_t *find_dest __P((upperstr_t *, int));
 static int putctl2 __P((queue_t *, int, int, int));
 static int putctl4 __P((queue_t *, int, int, int));
@@ -355,6 +357,8 @@ pppclose(q, flag, credp)
     qprocsoff(q);
 
     up = (upperstr_t *) q->q_ptr;
+    if (up == 0)
+       return 0;
     if (up->flags & US_CONTROL) {
        /*
         * This stream represents a PPA:
@@ -391,13 +395,15 @@ pppclose(q, flag, credp)
        }
     }
 
+#ifdef sun
     if (up->kstats)
        kstat_delete(up->kstats);
+#endif
 
     q->q_ptr = NULL;
     WR(q)->q_ptr = NULL;
 
-    for (prevp = &minor_devs; *prevp != 0; prevp = &up->nextmn) {
+    for (prevp = &minor_devs; *prevp != 0; prevp = &(*prevp)->nextmn) {
        if (*prevp == up) {
            *prevp = up->nextmn;
            break;
@@ -457,6 +463,7 @@ pppuwput(q, mp)
            us->lowerq = lq = lb->l_qbot;
            lq->q_ptr = us;
            RD(lq)->q_ptr = us;
+           noenable(RD(lq));
            iop->ioc_count = 0;
            error = 0;
            us->flags &= ~US_LASTMOD;
@@ -521,7 +528,9 @@ pppuwput(q, mp)
            if (ppa == 0)
                break;
            us->ppa = ppa;
-           qwriter(q, NULL, attach_ppa, PERIM_OUTER);
+           iop->ioc_count = 0;
+           qwriter(q, mp, attach_ppa, PERIM_OUTER);
+           error = -1;
            break;
 
        case PPPIO_MRU:
@@ -559,9 +568,26 @@ pppuwput(q, mp)
            error = 0;
            break;
 
+       case PPPIO_DEBUG:
+           if (iop->ioc_count != sizeof(int))
+               break;
+           n = *(int *)mp->b_cont->b_rptr;
+           if (n == PPPDBG_DUMP + PPPDBG_DRIVER) {
+               qwriter(q, NULL, debug_dump, PERIM_OUTER);
+               iop->ioc_count = 0;
+               error = 0;
+           } else {
+               if (us->ppa == 0 || us->ppa->lowerq == 0)
+                   break;
+               putnext(us->ppa->lowerq, mp);
+               error = -1;
+           }
+           break;
+
        default:
            if (us->ppa == 0 || us->ppa->lowerq == 0)
                break;
+           us->ioc_id = iop->ioc_id;
            error = -1;
            switch (iop->ioc_cmd) {
            case PPPIO_GETSTAT:
@@ -982,8 +1008,12 @@ attach_ppa(q, mp)
        ;
     t->next = us;
     us->next = 0;
-    if (mp)
+    if (mp->b_datap->db_type == M_IOCTL) {
+       mp->b_datap->db_type = M_IOCACK;
+       qreply(q, mp);
+    } else {
        dlpi_ok(q, DL_ATTACH_REQ);
+    }
 }
 
 static void
@@ -1015,14 +1045,13 @@ pppuwsrv(q)
     mblk_t *mp;
 
     us = (upperstr_t *) q->q_ptr;
+    us->flags &= ~US_BLOCKED;
     while ((mp = getq(q)) != 0) {
        if (!send_data(mp, us)) {
            putbq(q, mp);
            break;
        }
     }
-    if (mp == 0)
-       us->flags &= ~US_BLOCKED;
     return 0;
 }
 
@@ -1037,8 +1066,10 @@ ppplwput(q, mp)
     if (ppa != 0) {            /* why wouldn't it? */
        ppa->stats.ppp_opackets++;
        ppa->stats.ppp_obytes += msgdsize(mp);
+#ifdef sun
        if (ppa->kstats != 0)
            KSTAT_NAMED_PTR(ppa->kstats)[2].value.ul++;
+#endif
     }
     putnext(q, mp);
     return 0;
@@ -1070,10 +1101,6 @@ pppursrv(q)
     dl_unitdata_ind_t *ud;
     int proto;
 
-    /*
-     * If this is a control stream and we don't have a lower queue attached,
-     * run the write service routines of other streams attached to this PPA.
-     */
     us = (upperstr_t *) q->q_ptr;
     if (us->flags & US_CONTROL) {
        /*
@@ -1093,6 +1120,8 @@ pppursrv(q)
        /*
         * A network protocol stream.  Put a DLPI header on each
         * packet and send it on.
+        * (Actually, it seems that the IP module will happily
+        * accept M_DATA messages without the DL_UNITDATA_IND header.)
         */
        while ((mp = getq(q)) != 0) {
            if (!canputnext(q)) {
@@ -1108,6 +1137,7 @@ pppursrv(q)
                freemsg(mp);
                continue;
            }
+           hdr->b_datap->db_type = M_PROTO;
            ud = (dl_unitdata_ind_t *) hdr->b_wptr;
            hdr->b_wptr += sizeof(dl_unitdata_ind_t) + 2 * sizeof(ulong);
            hdr->b_cont = mp;
@@ -1124,9 +1154,19 @@ pppursrv(q)
               (e.g. PPP_IP) */
            ((ulong *)(ud + 1))[0] = us->req_sap;       /* dest SAP */
            ((ulong *)(ud + 1))[1] = us->req_sap;       /* src SAP */
-           putnext(q, mp);
+           putnext(q, hdr);
        }
     }
+
+    /*
+     * If this stream is attached to a PPA with a lower queue pair,
+     * enable the read queue's service routine if it has data queued.
+     * XXX there is a possibility that packets could get out of order
+     * if ppplrput now runs before ppplrsrv.
+     */
+    if (us->ppa != 0 && us->ppa->lowerq != 0)
+       qenable(RD(us->ppa->lowerq));
+
     return 0;
 }
 
@@ -1152,6 +1192,7 @@ ppplrput(q, mp)
     queue_t *uq;
     int proto, len;
     mblk_t *np;
+    struct iocblk *iop;
 
     ppa = (upperstr_t *) q->q_ptr;
     if (ppa == 0) {
@@ -1173,21 +1214,41 @@ ppplrput(q, mp)
     case M_CTL:
        switch (*mp->b_rptr) {
        case PPPCTL_IERROR:
+#ifdef sun
            if (ppa->kstats != 0) {
                KSTAT_NAMED_PTR(ppa->kstats)[1].value.ul++;
            }
+#endif
            ppa->stats.ppp_ierrors++;
            break;
        case PPPCTL_OERROR:
+#ifdef sun
            if (ppa->kstats != 0) {
                KSTAT_NAMED_PTR(ppa->kstats)[3].value.ul++;
            }
+#endif
            ppa->stats.ppp_oerrors++;
            break;
        }
        freemsg(mp);
        break;
 
+    case M_IOCACK:
+    case M_IOCNAK:
+       /*
+        * Attempt to match up the response with the stream
+        * that the request came from.
+        */
+       iop = (struct iocblk *) mp->b_rptr;
+       for (us = ppa; us != 0; us = us->next)
+           if (us->ioc_id == iop->ioc_id)
+               break;
+       if (us == 0)
+           freemsg(mp);
+       else
+           putnext(us->q, mp);
+       break;
+
     default:
        if (mp->b_datap->db_type == M_DATA) {
            len = msgdsize(mp);
@@ -1205,9 +1266,11 @@ ppplrput(q, mp)
            }
            ppa->stats.ppp_ipackets++;
            ppa->stats.ppp_ibytes += len;
+#ifdef sun
            if (ppa->kstats != 0) {
                KSTAT_NAMED_PTR(ppa->kstats)[0].value.ul++;
            }
+#endif
            proto = PPP_PROTOCOL(mp->b_rptr);
            if (proto < 0x8000 && (us = find_dest(ppa, proto)) != 0) {
                /*
@@ -1305,3 +1368,33 @@ putctl4(q, type, code, val)
     putnext(q, mp);
     return 1;
 }
+
+static void
+debug_dump(q, mp)
+    queue_t *q;                        /* not used */
+    mblk_t *mp;                        /* not used either */
+{
+    upperstr_t *us;
+    queue_t *uq, *lq;
+
+    cmn_err(CE_CONT, "ppp upper streams:\n");
+    for (us = minor_devs; us != 0; us = us->nextmn) {
+       uq = us->q;
+       cmn_err(CE_CONT, " %d: q=%x rlev=%d wlev=%d flags=0x%b",
+               us->mn, uq, (uq? qsize(uq): 0), (uq? qsize(WR(uq)): 0),
+               us->flags, "\020\1priv\2control\3blocked\4last");
+       cmn_err(CE_CONT, " state=%x sap=%x req_sap=%x", us->state, us->sap,
+               us->req_sap);
+       if (us->ppa == 0)
+           cmn_err(CE_CONT, " ppa=?\n");
+       else
+           cmn_err(CE_CONT, " ppa=%d\n", us->ppa->ppa_id);
+       if (us->flags & US_CONTROL) {
+           lq = us->lowerq;
+           cmn_err(CE_CONT, "    control for %d lq=%x rlev=%d wlev=%d",
+                   us->ppa_id, lq, (lq? qsize(RD(lq)): 0),
+                   (lq? qsize(lq): 0));
+           cmn_err(CE_CONT, " mru=%d mtu=%d\n", us->mru, us->mtu);
+       }
+    }
+}