1 /* 2 * Copyright (c) University of British Columbia, 1984 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Laboratory for Computation Vision and the Computer Science Department 8 * of the University of British Columbia. 9 * 10 * %sccs.include.redist.c% 11 * 12 * @(#)hd_subr.c 7.4 (Berkeley) 08/30/90 13 */ 14 15 #include "param.h" 16 #include "systm.h" 17 #include "mbuf.h" 18 #include "domain.h" 19 #include "socket.h" 20 #include "protosw.h" 21 #include "errno.h" 22 #include "time.h" 23 #include "kernel.h" 24 25 #include "../net/if.h" 26 27 #include "hdlc.h" 28 #include "hd_var.h" 29 #include "x25.h" 30 31 hd_init () 32 { 33 34 hdintrq.ifq_maxlen = IFQ_MAXLEN; 35 } 36 37 hd_ctlinput (prc, addr) 38 caddr_t addr; 39 { 40 register struct x25config *xcp = (struct x25config *)addr; 41 register struct ifnet *ifp; 42 register struct hdcb *hdp; 43 register struct ifaddr *ifa; 44 45 if (xcp->xc_addr.x25_family != AF_CCITT) 46 return (EAFNOSUPPORT); 47 if (xcp->xc_lptype != HDLCPROTO_LAPB) 48 return (EPROTONOSUPPORT); 49 for (ifa = ifa_ifwithaddr ((struct sockaddr *)xcp); ifa; ifa = ifa->ifa_next) 50 if (ifa->ifa_addr->sa_family == AF_CCITT) 51 break; 52 if (ifa == 0 || (ifp = ifa->ifa_ifp) == 0) 53 panic ("hd_ctlinput"); 54 for (hdp = hdcbhead; hdp; hdp = hdp->hd_next) 55 if (hdp->hd_ifp == ifp) 56 break; 57 58 if (hdp == 0) { /* new interface */ 59 register int error; 60 register struct mbuf *m; 61 62 m = m_getclr (M_DONTWAIT, MT_PCB); 63 if (m == 0) 64 return (ENOBUFS); 65 if (error = pk_ctlinput (PRC_LINKDOWN, xcp)) { 66 m_freem (m); 67 return (error); 68 } 69 70 hdp = mtod (m, struct hdcb *); 71 hdp->hd_ifp = ifp; 72 hdp->hd_xcp = xcp; 73 hdp->hd_next = hdcbhead; 74 hdcbhead = hdp; 75 hdp->hd_state = INIT; 76 } 77 78 switch (prc) { 79 case PRC_IFUP: 80 if (xcp->xc_lwsize == 0 || 81 xcp->xc_lwsize > MAX_WINDOW_SIZE) 82 xcp->xc_lwsize = MAX_WINDOW_SIZE; 83 if (hdp->hd_state == INIT) 84 SET_TIMER (hdp); 85 break; 86 87 case PRC_IFDOWN: 88 if (hdp->hd_state == ABM) 89 hd_message (hdp, "Operator shutdown: link closed"); 90 (void) pk_ctlinput (PRC_LINKDOWN, xcp); 91 hd_writeinternal (hdp, DISC, POLLON); 92 hdp->hd_state = DISC_SENT; 93 SET_TIMER (hdp); 94 } 95 return (0); 96 } 97 98 hd_initvars (hdp) 99 register struct hdcb *hdp; 100 { 101 register struct mbuf *m; 102 register int i; 103 104 /* Clear Transmit queue. */ 105 while ((m = hd_remove (&hdp->hd_txq)) != NULL) 106 m_freem (m); 107 108 /* Clear Retransmit queue. */ 109 i = hdp->hd_lastrxnr; 110 while (i != hdp->hd_retxqi) { 111 m_freem (hdp->hd_retxq[i]); 112 i = (i + 1) % MODULUS; 113 } 114 hdp->hd_retxqi = 0; 115 116 hdp->hd_vs = hdp->hd_vr = 0; 117 hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0; 118 hdp->hd_rrtimer = 0; 119 KILL_TIMER(hdp); 120 hdp->hd_retxcnt = 0; 121 hdp->hd_condition = 0; 122 } 123 124 hd_decode (hdp, frame) 125 register struct hdcb *hdp; 126 struct Hdlc_frame *frame; 127 { 128 register int frametype = ILLEGAL; 129 register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame; 130 register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame; 131 register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame; 132 133 if (iframe -> hdlc_0 == 0) { 134 frametype = IFRAME; 135 hdp->hd_iframes_in++; 136 } 137 138 else if (sframe -> hdlc_01 == 1) { 139 /* Supervisory format. */ 140 switch (sframe -> s2) { 141 case 0: 142 frametype = RR; 143 hdp->hd_rrs_in++; 144 break; 145 146 case 1: 147 frametype = RNR; 148 hdp->hd_rnrs_in++; 149 break; 150 151 case 2: 152 frametype = REJ; 153 hdp->hd_rejs_in++; 154 } 155 } 156 else if (uframe -> hdlc_11 == 3) { 157 /* Unnumbered format. */ 158 switch (uframe -> m3) { 159 case 0: 160 frametype = DM; 161 break; 162 163 case 1: 164 frametype = SABM; 165 break; 166 167 case 2: 168 frametype = DISC; 169 break; 170 171 case 3: 172 frametype = UA; 173 break; 174 175 case 4: 176 frametype = FRMR; 177 hdp->hd_frmrs_in++; 178 } 179 } 180 return (frametype); 181 } 182 183 /* 184 * This routine is called when the HDLC layer internally generates a 185 * command or response for the remote machine ( eg. RR, UA etc. ). 186 * Only supervisory or unnumbered frames are processed. 187 */ 188 189 hd_writeinternal (hdp, frametype, pf) 190 register struct hdcb *hdp; 191 register int frametype, pf; 192 { 193 register struct mbuf *buf; 194 struct Hdlc_frame *frame; 195 register struct Hdlc_sframe *sframe; 196 register struct Hdlc_uframe *uframe; 197 198 MGET (buf, M_DONTWAIT, MT_HEADER); 199 if (buf == 0) 200 return; 201 frame = mtod (buf, struct Hdlc_frame *); 202 sframe = mtod (buf, struct Hdlc_sframe *); 203 uframe = mtod (buf, struct Hdlc_uframe *); 204 205 /* Assume a response - address structure for DTE */ 206 frame -> address = ADDRESS_A; 207 buf -> m_len = 2; 208 buf -> m_act = buf -> m_next = NULL; 209 210 switch (frametype) { 211 case RR: 212 frame -> control = RR_CONTROL; 213 hdp->hd_rrs_out++; 214 break; 215 216 case RNR: 217 frame -> control = RNR_CONTROL; 218 hdp->hd_rnrs_out++; 219 break; 220 221 case REJ: 222 frame -> control = REJ_CONTROL; 223 hdp->hd_rejs_out++; 224 break; 225 226 case SABM: 227 frame -> control = SABM_CONTROL; 228 frame -> address = ADDRESS_B; 229 break; 230 231 case DISC: 232 frame -> control = DISC_CONTROL; 233 frame -> address = ADDRESS_B; 234 break; 235 236 case DM: 237 frame -> control = DM_CONTROL; 238 break; 239 240 case UA: 241 frame -> control = UA_CONTROL; 242 break; 243 244 case FRMR: 245 frame -> control = FRMR_CONTROL; 246 bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3); 247 buf -> m_len = 5; 248 hdp->hd_frmrs_out++; 249 250 } 251 252 if (sframe -> hdlc_01 == 1) { 253 /* Supervisory format - RR, REJ, or RNR. */ 254 sframe -> nr = hdp->hd_vr; 255 sframe -> pf = pf; 256 hdp->hd_lasttxnr = hdp->hd_vr; 257 hdp->hd_rrtimer = 0; 258 } 259 else 260 uframe -> pf = pf; 261 262 hd_trace (hdp, TX, frame); 263 (*hdp->hd_output)(hdp, buf); 264 } 265 266 struct mbuf * 267 hd_remove (q) 268 struct hdtxq *q; 269 { 270 register struct mbuf *m; 271 272 m = q -> head; 273 if (m) { 274 if ((q -> head = m -> m_act) == NULL) 275 q -> tail = NULL; 276 m -> m_act = 0; 277 } 278 return (m); 279 } 280 281 hd_append (q, m) 282 register struct hdtxq *q; 283 register struct mbuf *m; 284 { 285 286 m -> m_act = NULL; 287 if (q -> tail == NULL) 288 q -> head = m; 289 else 290 q -> tail -> m_act = m; 291 q -> tail = m; 292 } 293 294 hd_flush (ifp) 295 struct ifnet *ifp; 296 { 297 register struct mbuf *m; 298 register int s; 299 300 while (1) { 301 s = spl6 (); /* XXX SHOULDN'T THIS BE splimp? */ 302 IF_DEQUEUE (&ifp->if_snd, m); 303 splx (s); 304 if (m == 0) 305 break; 306 m_freem (m); 307 } 308 } 309 310 hd_message (hdp, msg) 311 struct hdcb *hdp; 312 char *msg; 313 { 314 char *format_ntn (); 315 316 if (hdcbhead -> hd_next) 317 printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg); 318 else 319 printf ("HDLC: %s\n", msg); 320 } 321 322 #ifdef HDLCDEBUG 323 hd_status (hdp) 324 struct hdcb *hdp; 325 { 326 printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n", 327 hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi); 328 329 printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n", 330 hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx); 331 } 332 #endif 333