3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/uni/sscop_pdu.c,v 1.5 2000/01/17 20:49:52 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/sscop_pdu.c,v 1.7 2006/12/20 18:14:43 dillon Exp $
31 * ATM Forum UNI Support
32 * ---------------------
34 * SSCOP - PDU subroutines
38 #include <netproto/atm/kern_include.h>
41 #include "sscop_misc.h"
42 #include "sscop_pdu.h"
43 #include "sscop_var.h"
48 static KBuffer
* sscop_stat_init (struct sscop
*);
49 static KBuffer
* sscop_stat_add (sscop_seq
, KBuffer
*);
50 static int sscop_stat_end (struct sscop
*, sscop_seq
,
51 KBuffer
*, KBuffer
*);
52 static int sscop_recv_locate (struct sscop
*, sscop_seq
,
57 * Build and send BGN PDU
59 * A BGN PDU will be constructed and passed down the protocol stack.
60 * The SSCOP-UU/N(UU) field is not supported.
63 * sop pointer to sscop connection control block
64 * source originator of BGN PDU (Q.SAAL1 only)
67 * 0 PDU successfully built and passed down the stack
68 * else unable to build or send pdu
72 sscop_send_bgn(struct sscop
*sop
, int source
)
82 KB_ALLOCPKT(m
, sizeof(struct bgn_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
87 * Setup buffer controls
89 KB_HEADSET(m
, MIN(sop
->so_headout
,
90 KB_BFRLEN(m
) - sizeof(struct bgn_pdu
)));
91 KB_LEN(m
) = sizeof(struct bgn_pdu
);
96 KB_DATASTART(m
, bp
, struct bgn_pdu
*);
97 *(int *)&bp
->bgn_rsvd
[0] = 0;
98 if (sop
->so_vers
!= SSCOP_VERS_QSAAL
)
99 bp
->bgn_nsq
= sop
->so_sendconn
;
101 htonl((PT_BGN
<< PT_TYPE_SHIFT
) | SEQ_VAL(sop
->so_rcvmax
));
102 if ((sop
->so_vers
== SSCOP_VERS_QSAAL
) &&
103 (source
== SSCOP_SOURCE_SSCOP
))
104 bp
->bgn_type
|= PT_SOURCE_SSCOP
;
107 * Send PDU towards peer
109 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
110 sop
->so_connvc
, (int)m
, 0, err
);
120 * Build and send BGAK PDU
122 * A BGAK PDU will be constructed and passed down the protocol stack.
123 * The SSCOP-UU/N(UU) field is not supported.
126 * sop pointer to sscop connection control block
129 * 0 PDU successfully built and passed down the stack
130 * else unable to build or send pdu
134 sscop_send_bgak(struct sscop
*sop
)
144 KB_ALLOCPKT(m
, sizeof(struct bgak_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
149 * Setup buffer controls
151 KB_HEADSET(m
, MIN(sop
->so_headout
,
152 KB_BFRLEN(m
) - sizeof(struct bgak_pdu
)));
153 KB_LEN(m
) = sizeof(struct bgak_pdu
);
158 KB_DATASTART(m
, bp
, struct bgak_pdu
*);
161 htonl((PT_BGAK
<< PT_TYPE_SHIFT
) | SEQ_VAL(sop
->so_rcvmax
));
164 * Send PDU towards peer
166 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
167 sop
->so_connvc
, (int)m
, 0, err
);
177 * Build and send BGREJ PDU
179 * A BGREJ PDU will be constructed and passed down the protocol stack.
180 * The SSCOP-UU/N(UU) field is not supported.
183 * sop pointer to sscop connection control block
186 * 0 PDU successfully built and passed down the stack
187 * else unable to build or send pdu
191 sscop_send_bgrej(struct sscop
*sop
)
194 struct bgrej_pdu
*bp
;
201 KB_ALLOCPKT(m
, sizeof(struct bgrej_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
206 * Setup buffer controls
208 KB_HEADSET(m
, MIN(sop
->so_headout
,
209 KB_BFRLEN(m
) - sizeof(struct bgrej_pdu
)));
210 KB_LEN(m
) = sizeof(struct bgrej_pdu
);
215 KB_DATASTART(m
, bp
, struct bgrej_pdu
*);
217 *(u_int
*)&bp
->bgrej_type
= htonl((PT_BGREJ
<< PT_TYPE_SHIFT
) | 0);
220 * Send PDU towards peer
222 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
223 sop
->so_connvc
, (int)m
, 0, err
);
233 * Build and send END PDU
235 * An END PDU will be constructed and passed down the protocol stack.
236 * The SSCOP-UU/N(UU) field is not supported.
239 * sop pointer to sscop connection control block
240 * source originator of END PDU
243 * 0 PDU successfully built and passed down the stack
244 * else unable to build or send pdu
248 sscop_send_end(struct sscop
*sop
, int source
)
258 KB_ALLOCPKT(m
, sizeof(struct end_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
263 * Setup buffer controls
265 KB_HEADSET(m
, MIN(sop
->so_headout
,
266 KB_BFRLEN(m
) - sizeof(struct end_pdu
)));
267 KB_LEN(m
) = sizeof(struct end_pdu
);
272 KB_DATASTART(m
, ep
, struct end_pdu
*);
274 *(u_int
*)&ep
->end_type
= htonl((PT_END
<< PT_TYPE_SHIFT
) | 0);
275 if (source
== SSCOP_SOURCE_SSCOP
) {
276 ep
->end_type
|= PT_SOURCE_SSCOP
;
277 sop
->so_flags
|= SOF_ENDSSCOP
;
278 } else if (source
== SSCOP_SOURCE_USER
)
279 sop
->so_flags
&= ~SOF_ENDSSCOP
;
280 else if ((source
== SSCOP_SOURCE_LAST
) &&
281 (sop
->so_flags
& SOF_ENDSSCOP
))
282 ep
->end_type
|= PT_SOURCE_SSCOP
;
285 * Send PDU towards peer
287 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
288 sop
->so_connvc
, (int)m
, 0, err
);
298 * Build and send ENDAK PDU
300 * An ENDAK PDU will be constructed and passed down the protocol stack.
303 * sop pointer to sscop connection control block
306 * 0 PDU successfully built and passed down the stack
307 * else unable to build or send pdu
311 sscop_send_endak(struct sscop
*sop
)
314 struct endak_q2110_pdu
*e2p
;
315 struct endak_qsaal_pdu
*esp
;
322 if (sop
->so_vers
== SSCOP_VERS_QSAAL
)
323 size
= sizeof(struct endak_qsaal_pdu
);
325 size
= sizeof(struct endak_q2110_pdu
);
330 KB_ALLOCPKT(m
, size
, KB_F_NOWAIT
, KB_T_HEADER
);
335 * Setup buffer controls
337 KB_HEADSET(m
, MIN(sop
->so_headout
, KB_BFRLEN(m
) - size
));
343 if (sop
->so_vers
== SSCOP_VERS_QSAAL
) {
344 KB_DATASTART(m
, esp
, struct endak_qsaal_pdu
*);
345 *(u_int
*)&esp
->endak_type
=
346 htonl((PT_ENDAK
<< PT_TYPE_SHIFT
) | 0);
348 KB_DATASTART(m
, e2p
, struct endak_q2110_pdu
*);
349 e2p
->endak_rsvd2
= 0;
350 *(u_int
*)&e2p
->endak_type
=
351 htonl((PT_ENDAK
<< PT_TYPE_SHIFT
) | 0);
355 * Send PDU towards peer
357 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
358 sop
->so_connvc
, (int)m
, 0, err
);
368 * Build and send RS PDU
370 * A RS PDU will be constructed and passed down the protocol stack.
371 * The SSCOP-UU/N(UU) field is not supported.
374 * sop pointer to sscop connection control block
377 * 0 PDU successfully built and passed down the stack
378 * else unable to build or send pdu
382 sscop_send_rs(struct sscop
*sop
)
392 KB_ALLOCPKT(m
, sizeof(struct rs_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
397 * Setup buffer controls
399 KB_HEADSET(m
, MIN(sop
->so_headout
,
400 KB_BFRLEN(m
) - sizeof(struct rs_pdu
)));
401 KB_LEN(m
) = sizeof(struct rs_pdu
);
406 KB_DATASTART(m
, rp
, struct rs_pdu
*);
407 *(int *)&rp
->rs_rsvd
[0] = 0;
408 if (sop
->so_vers
!= SSCOP_VERS_QSAAL
) {
409 rp
->rs_nsq
= sop
->so_sendconn
;
410 rp
->rs_nmr
= htonl((PT_RS
<< PT_TYPE_SHIFT
) |
411 SEQ_VAL(sop
->so_rcvmax
));
413 rp
->rs_nmr
= htonl((PT_RS
<< PT_TYPE_SHIFT
) | 0);
417 * Send PDU towards peer
419 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
420 sop
->so_connvc
, (int)m
, 0, err
);
430 * Build and send RSAK PDU
432 * An RSAK PDU will be constructed and passed down the protocol stack.
435 * sop pointer to sscop connection control block
438 * 0 PDU successfully built and passed down the stack
439 * else unable to build or send pdu
443 sscop_send_rsak(struct sscop
*sop
)
446 struct rsak_q2110_pdu
*r2p
;
447 struct rsak_qsaal_pdu
*rsp
;
454 if (sop
->so_vers
== SSCOP_VERS_QSAAL
)
455 size
= sizeof(struct rsak_qsaal_pdu
);
457 size
= sizeof(struct rsak_q2110_pdu
);
462 KB_ALLOCPKT(m
, size
, KB_F_NOWAIT
, KB_T_HEADER
);
467 * Setup buffer controls
469 KB_HEADSET(m
, MIN(sop
->so_headout
, KB_BFRLEN(m
) - size
));
475 if (sop
->so_vers
== SSCOP_VERS_QSAAL
) {
476 KB_DATASTART(m
, rsp
, struct rsak_qsaal_pdu
*);
477 *(u_int
*)&rsp
->rsaks_type
=
478 htonl((PT_RSAK
<< PT_TYPE_SHIFT
) | 0);
480 KB_DATASTART(m
, r2p
, struct rsak_q2110_pdu
*);
482 r2p
->rsak_nmr
= htonl((PT_RSAK
<< PT_TYPE_SHIFT
) |
483 SEQ_VAL(sop
->so_rcvmax
));
487 * Send PDU towards peer
489 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
490 sop
->so_connvc
, (int)m
, 0, err
);
500 * Build and send ER PDU
502 * An ER PDU will be constructed and passed down the protocol stack.
505 * sop pointer to sscop connection control block
508 * 0 PDU successfully built and passed down the stack
509 * else unable to build or send pdu
513 sscop_send_er(struct sscop
*sop
)
523 KB_ALLOCPKT(m
, sizeof(struct er_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
528 * Setup buffer controls
530 KB_HEADSET(m
, MIN(sop
->so_headout
,
531 KB_BFRLEN(m
) - sizeof(struct er_pdu
)));
532 KB_LEN(m
) = sizeof(struct er_pdu
);
537 KB_DATASTART(m
, ep
, struct er_pdu
*);
538 *(int *)&ep
->er_rsvd
[0] = 0;
539 ep
->er_nsq
= sop
->so_sendconn
;
540 ep
->er_nmr
= htonl((PT_ER
<< PT_TYPE_SHIFT
) | SEQ_VAL(sop
->so_rcvmax
));
543 * Send PDU towards peer
545 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
546 sop
->so_connvc
, (int)m
, 0, err
);
556 * Build and send ERAK PDU
558 * An ERAK PDU will be constructed and passed down the protocol stack.
561 * sop pointer to sscop connection control block
564 * 0 PDU successfully built and passed down the stack
565 * else unable to build or send pdu
569 sscop_send_erak(struct sscop
*sop
)
579 KB_ALLOCPKT(m
, sizeof(struct erak_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
584 * Setup buffer controls
586 KB_HEADSET(m
, MIN(sop
->so_headout
,
587 KB_BFRLEN(m
) - sizeof(struct erak_pdu
)));
588 KB_LEN(m
) = sizeof(struct erak_pdu
);
593 KB_DATASTART(m
, ep
, struct erak_pdu
*);
595 ep
->erak_nmr
= htonl((PT_ERAK
<< PT_TYPE_SHIFT
) |
596 SEQ_VAL(sop
->so_rcvmax
));
599 * Send PDU towards peer
601 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
602 sop
->so_connvc
, (int)m
, 0, err
);
612 * Build and send POLL PDU
614 * A POLL PDU will be constructed and passed down the protocol stack.
617 * sop pointer to sscop connection control block
620 * 0 PDU successfully built and passed down the stack
621 * else unable to build or send pdu
625 sscop_send_poll(struct sscop
*sop
)
635 KB_ALLOCPKT(m
, sizeof(struct poll_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
640 * Setup buffer controls
642 KB_HEADSET(m
, MIN(sop
->so_headout
,
643 KB_BFRLEN(m
) - sizeof(struct poll_pdu
)));
644 KB_LEN(m
) = sizeof(struct poll_pdu
);
649 KB_DATASTART(m
, pp
, struct poll_pdu
*);
650 pp
->poll_nps
= htonl(SEQ_VAL(sop
->so_pollsend
));
651 pp
->poll_ns
= htonl((PT_POLL
<< PT_TYPE_SHIFT
) | SEQ_VAL(sop
->so_send
));
654 * Send PDU towards peer
656 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
657 sop
->so_connvc
, (int)m
, 0, err
);
667 * STAT PDU Construction - Initialize for new PDU
670 * sop pointer to sscop connection control block
673 * addr pointer to initialized buffer
674 * 0 unable to allocate buffer
678 sscop_stat_init(struct sscop
*sop
)
682 #define STAT_INIT_SIZE (sizeof(struct stat_pdu) + 2 * sizeof(sscop_seq))
687 KB_ALLOCPKT(m
, STAT_INIT_SIZE
, KB_F_NOWAIT
, KB_T_HEADER
);
692 * Setup buffer controls
694 KB_HEADSET(m
, sop
->so_headout
< (KB_BFRLEN(m
) - STAT_INIT_SIZE
) ?
695 sop
->so_headout
: 0);
699 #undef STAT_INIT_SIZE
704 * STAT PDU Construction - Add List Element
707 * elem sequence number to add to list
708 * m pointer to current buffer
711 * addr pointer to current buffer (updated)
712 * 0 buffer allocation failure
716 sscop_stat_add(sscop_seq elem
, KBuffer
*m
)
723 * See if new element will fit in current buffer
725 KB_TAILROOM(m
, space
);
726 if (space
< sizeof(elem
)) {
729 * Nope, so get another buffer
731 KB_ALLOC(n
, sizeof(elem
), KB_F_NOWAIT
, KB_T_DATA
);
746 KB_DATAEND(m
, sp
, sscop_seq
*);
748 KB_LEN(m
) += sizeof (elem
);
754 * STAT PDU Construction - Add Trailer and Send
757 * sop pointer to sscop connection control block
758 * nps received poll sequence number (POLL.N(PS))
759 * head pointer to head of buffer chain
760 * m pointer to current (last) buffer
763 * 0 STAT successfully sent
764 * else unable to send STAT or truncated STAT was sent - buffer freed
768 sscop_stat_end(struct sscop
*sop
, sscop_seq nps
, KBuffer
*head
, KBuffer
*m
)
772 int err
, space
, trunc
= 0;
775 * See if PDU trailer will fit in current buffer
777 KB_TAILROOM(m
, space
);
778 if (space
< sizeof(struct stat_pdu
)) {
781 * Doesn't fit, so get another buffer
783 KB_ALLOC(n
, sizeof(struct stat_pdu
), KB_F_NOWAIT
, KB_T_DATA
);
786 * Out of buffers - truncate elements and send
787 * what we can, but tell caller that we can't
788 * send any more segments.
792 KB_LEN(m
) -= sizeof(sscop_seq
);
793 space
+= sizeof(sscop_seq
);
794 } while (space
< sizeof(struct stat_pdu
));
808 KB_DATAEND(m
, sp
, struct stat_pdu
*);
809 sp
->stat_nps
= htonl(nps
);
810 sp
->stat_nmr
= htonl(sop
->so_rcvmax
);
811 sp
->stat_nr
= htonl(sop
->so_rcvnext
);
812 sp
->stat_type
= PT_STAT
;
813 KB_LEN(m
) += sizeof(struct stat_pdu
);
816 * Finally, send the STAT
818 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
819 sop
->so_connvc
, (int)head
, 0, err
);
823 * We lie about the STACK_CALL failing...
836 * Check for PDU in Receive Queue
838 * A receive queue will be searched for an SD PDU matching the requested
839 * sequence number. The caller must supply a pointer to the address of the
840 * PDU in the particular receive queue at which to begin the search. This
841 * function will update that pointer as it traverses the queue.
844 * sop pointer to sscop connection control block
845 * seq sequence number of PDU to locate
846 * currp address of pointer to PDU in receive queue to start search
849 * 0 reqeusted PDU not in receive queue
850 * 1 requested PDU located in receive queue
854 sscop_recv_locate(struct sscop
*sop
, sscop_seq seq
, struct pdu_hdr
**currp
)
859 * Search queue until we know the answer
863 * If we're at the end of the queue, the PDU isn't there
869 * Get the current PDU sequence number
871 cs
= (*currp
)->ph_ns
;
874 * See if we're at the requested PDU
880 * If we're past the requested seq number,
881 * the PDU isn't there
883 if (SEQ_LT(seq
, cs
, sop
->so_rcvnext
))
887 * Go to next PDU and keep looking
889 *currp
= (*currp
)->ph_recv_lk
;
895 * Build and send STAT PDU
897 * A STAT PDU will be constructed and passed down the protocol stack.
900 * sop pointer to sscop connection control block
901 * nps received poll sequence number (POLL.N(PS))
904 * 0 PDU successfully built and passed down the stack
905 * else unable to build or send complete pdu
909 sscop_send_stat(struct sscop
*sop
, sscop_seq nps
)
911 KBuffer
*head
, *curr
, *n
;
912 struct pdu_hdr
*rq
= sop
->so_recv_hd
;
914 sscop_seq vrh
= sop
->so_rcvhigh
;
915 sscop_seq vrr
= sop
->so_rcvnext
;
919 * Initialize for start of STAT PDU
921 head
= sscop_stat_init(sop
);
927 * Start with first PDU not yet received
932 * Keep looping until we get to last sent PDU
937 * Find next missing PDU
939 while (SEQ_LT(i
, vrh
, vrr
) && sscop_recv_locate(sop
, i
, &rq
)) {
944 * Add odd (start of missing gap) STAT element
946 n
= sscop_stat_add(i
, curr
);
954 * Have we reached the last sent PDU sequence number??
958 * Yes, then we're done, send STAT
964 * Have we reached the max STAT size yet??
966 if (len
>= PDU_MAX_ELEM
) {
968 * Yes, send this STAT segment
970 if (sscop_stat_end(sop
, nps
, head
, curr
)) {
975 * Start a new segment
977 head
= sscop_stat_init(sop
);
983 * Restart missing gap
985 curr
= sscop_stat_add(i
, curr
);
994 * Now find the end of the missing gap
998 } while (SEQ_LT(i
, vrh
, vrr
) &&
999 (sscop_recv_locate(sop
, i
, &rq
) == 0));
1002 * Add even (start of received gap) STAT element
1004 n
= sscop_stat_add(i
, curr
);
1013 * Finally, send the STAT PDU (or last STAT segment)
1015 if (sscop_stat_end(sop
, nps
, head
, curr
)) {
1023 * Send a truncated STAT PDU
1025 sscop_stat_end(sop
, nps
, head
, curr
);
1032 * Build and send USTAT PDU
1034 * A USTAT PDU will be constructed and passed down the protocol stack.
1037 * sop pointer to sscop connection control block
1038 * ns sequence number for second list element
1041 * 0 PDU successfully built and passed down the stack
1042 * else unable to build or send pdu
1046 sscop_send_ustat(struct sscop
*sop
, sscop_seq ns
)
1049 struct ustat_pdu
*up
;
1054 * Get buffer for PDU
1056 KB_ALLOCPKT(m
, sizeof(struct ustat_pdu
), KB_F_NOWAIT
, KB_T_HEADER
);
1061 * Setup buffer controls
1063 KB_HEADSET(m
, MIN(sop
->so_headout
,
1064 KB_BFRLEN(m
) - sizeof(struct ustat_pdu
)));
1065 KB_LEN(m
) = sizeof(struct ustat_pdu
);
1070 KB_DATASTART(m
, up
, struct ustat_pdu
*);
1071 up
->ustat_le1
= htonl(SEQ_VAL(sop
->so_rcvhigh
));
1072 up
->ustat_le2
= htonl(SEQ_VAL(ns
));
1073 up
->ustat_nmr
= htonl(SEQ_VAL(sop
->so_rcvmax
));
1075 htonl((PT_USTAT
<< PT_TYPE_SHIFT
) | SEQ_VAL(sop
->so_rcvnext
));
1078 * Send PDU towards peer
1080 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
1081 sop
->so_connvc
, (int)m
, 0, err
);
1091 * Build and send UD PDU
1093 * A UD PDU will be constructed and passed down the protocol stack.
1096 * sop pointer to sscop connection control block
1097 * m pointer to user data buffer chain
1100 * 0 PDU successfully built and passed down the stack
1101 * else unable to build or send pdu (buffer released)
1105 sscop_send_ud(struct sscop
*sop
, KBuffer
*m
)
1109 int pad
, trlen
, space
;
1113 * Count data and get to last buffer in chain
1115 for (ml
= m
; ; ml
= KB_NEXT(ml
)) {
1117 if (KB_NEXT(ml
) == NULL
)
1122 * Verify data length
1124 if (len
> sop
->so_parm
.sp_maxinfo
) {
1126 sscop_abort(sop
, "sscop: maximum unitdata size exceeded\n");
1131 * Figure out how much padding we'll need
1133 pad
= ((len
+ (PDU_PAD_ALIGN
- 1)) & ~(PDU_PAD_ALIGN
- 1)) - len
;
1134 trlen
= pad
+ sizeof(struct ud_pdu
);
1137 * Get space for PDU trailer and padding
1139 KB_TAILROOM(ml
, space
);
1140 if (space
< trlen
) {
1142 * Allocate & link buffer for pad and trailer
1144 KB_ALLOC(n
, trlen
, KB_F_NOWAIT
, KB_T_HEADER
);
1154 * Build the PDU trailer
1156 * Since we can't be sure of alignment in the buffers, we
1157 * have to move this a byte at a time.
1159 KB_DATAEND(ml
, cp
, u_char
*);
1161 *cp
++ = (pad
<< PT_PAD_SHIFT
) | PT_UD
;
1163 KB_LEN(ml
) += trlen
;
1166 * Now pass PDU down the stack
1168 STACK_CALL(CPCS_UNITDATA_INV
, sop
->so_lower
, sop
->so_tokl
,
1169 sop
->so_connvc
, (int)m
, 0, err
);
1180 * Print an SSCOP PDU
1183 * sop pointer to sscop connection control block
1184 * m pointer to pdu buffer chain
1185 * msg pointer to message string
1192 sscop_pdu_print(struct sscop
*sop
, KBuffer
*m
, char *msg
)
1197 vcp
= sop
->so_connvc
->cvc_vcc
;
1198 ksnprintf(buf
, sizeof(buf
),
1199 "sscop %s: vcc=(%d,%d)\n", msg
, vcp
->vc_vpi
, vcp
->vc_vci
);
1200 atm_pdu_print(m
, buf
);