1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * llc_pdu.c - access to PDU internals
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (c) 1997 by Procom Technology, Inc.
5*4882a593Smuzhiyun * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * This program can be redistributed or modified under the terms of the
8*4882a593Smuzhiyun * GNU General Public License as published by the Free Software Foundation.
9*4882a593Smuzhiyun * This program is distributed without any warranty or implied warranty
10*4882a593Smuzhiyun * of merchantability or fitness for a particular purpose.
11*4882a593Smuzhiyun *
12*4882a593Smuzhiyun * See the GNU General Public License for more details.
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <linux/netdevice.h>
16*4882a593Smuzhiyun #include <net/llc_pdu.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
19*4882a593Smuzhiyun static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
20*4882a593Smuzhiyun
llc_pdu_set_cmd_rsp(struct sk_buff * skb,u8 pdu_type)21*4882a593Smuzhiyun void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun llc_pdu_un_hdr(skb)->ssap |= pdu_type;
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun /**
27*4882a593Smuzhiyun * pdu_set_pf_bit - sets poll/final bit in LLC header
28*4882a593Smuzhiyun * @skb: Frame to set bit in
29*4882a593Smuzhiyun * @bit_value: poll/final bit (0 or 1).
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * This function sets poll/final bit in LLC header (based on type of PDU).
32*4882a593Smuzhiyun * in I or S pdus, p/f bit is right bit of fourth byte in header. in U
33*4882a593Smuzhiyun * pdus p/f bit is fifth bit of third byte.
34*4882a593Smuzhiyun */
llc_pdu_set_pf_bit(struct sk_buff * skb,u8 bit_value)35*4882a593Smuzhiyun void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun u8 pdu_type;
38*4882a593Smuzhiyun struct llc_pdu_sn *pdu;
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun llc_pdu_decode_pdu_type(skb, &pdu_type);
41*4882a593Smuzhiyun pdu = llc_pdu_sn_hdr(skb);
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun switch (pdu_type) {
44*4882a593Smuzhiyun case LLC_PDU_TYPE_I:
45*4882a593Smuzhiyun case LLC_PDU_TYPE_S:
46*4882a593Smuzhiyun pdu->ctrl_2 = (pdu->ctrl_2 & 0xFE) | bit_value;
47*4882a593Smuzhiyun break;
48*4882a593Smuzhiyun case LLC_PDU_TYPE_U:
49*4882a593Smuzhiyun pdu->ctrl_1 |= (pdu->ctrl_1 & 0xEF) | (bit_value << 4);
50*4882a593Smuzhiyun break;
51*4882a593Smuzhiyun }
52*4882a593Smuzhiyun }
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /**
55*4882a593Smuzhiyun * llc_pdu_decode_pf_bit - extracs poll/final bit from LLC header
56*4882a593Smuzhiyun * @skb: input skb that p/f bit must be extracted from it
57*4882a593Smuzhiyun * @pf_bit: poll/final bit (0 or 1)
58*4882a593Smuzhiyun *
59*4882a593Smuzhiyun * This function extracts poll/final bit from LLC header (based on type of
60*4882a593Smuzhiyun * PDU). In I or S pdus, p/f bit is right bit of fourth byte in header. In
61*4882a593Smuzhiyun * U pdus p/f bit is fifth bit of third byte.
62*4882a593Smuzhiyun */
llc_pdu_decode_pf_bit(struct sk_buff * skb,u8 * pf_bit)63*4882a593Smuzhiyun void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun u8 pdu_type;
66*4882a593Smuzhiyun struct llc_pdu_sn *pdu;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun llc_pdu_decode_pdu_type(skb, &pdu_type);
69*4882a593Smuzhiyun pdu = llc_pdu_sn_hdr(skb);
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun switch (pdu_type) {
72*4882a593Smuzhiyun case LLC_PDU_TYPE_I:
73*4882a593Smuzhiyun case LLC_PDU_TYPE_S:
74*4882a593Smuzhiyun *pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
75*4882a593Smuzhiyun break;
76*4882a593Smuzhiyun case LLC_PDU_TYPE_U:
77*4882a593Smuzhiyun *pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
78*4882a593Smuzhiyun break;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /**
83*4882a593Smuzhiyun * llc_pdu_init_as_disc_cmd - Builds DISC PDU
84*4882a593Smuzhiyun * @skb: Address of the skb to build
85*4882a593Smuzhiyun * @p_bit: The P bit to set in the PDU
86*4882a593Smuzhiyun *
87*4882a593Smuzhiyun * Builds a pdu frame as a DISC command.
88*4882a593Smuzhiyun */
llc_pdu_init_as_disc_cmd(struct sk_buff * skb,u8 p_bit)89*4882a593Smuzhiyun void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_U;
94*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC;
95*4882a593Smuzhiyun pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /**
99*4882a593Smuzhiyun * llc_pdu_init_as_i_cmd - builds I pdu
100*4882a593Smuzhiyun * @skb: Address of the skb to build
101*4882a593Smuzhiyun * @p_bit: The P bit to set in the PDU
102*4882a593Smuzhiyun * @ns: The sequence number of the data PDU
103*4882a593Smuzhiyun * @nr: The seq. number of the expected I PDU from the remote
104*4882a593Smuzhiyun *
105*4882a593Smuzhiyun * Builds a pdu frame as an I command.
106*4882a593Smuzhiyun */
llc_pdu_init_as_i_cmd(struct sk_buff * skb,u8 p_bit,u8 ns,u8 nr)107*4882a593Smuzhiyun void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
108*4882a593Smuzhiyun {
109*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_I;
112*4882a593Smuzhiyun pdu->ctrl_2 = 0;
113*4882a593Smuzhiyun pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); /* p/f bit */
114*4882a593Smuzhiyun pdu->ctrl_1 |= (ns << 1) & 0xFE; /* set N(S) in bits 2..8 */
115*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /**
119*4882a593Smuzhiyun * llc_pdu_init_as_rej_cmd - builds REJ PDU
120*4882a593Smuzhiyun * @skb: Address of the skb to build
121*4882a593Smuzhiyun * @p_bit: The P bit to set in the PDU
122*4882a593Smuzhiyun * @nr: The seq. number of the expected I PDU from the remote
123*4882a593Smuzhiyun *
124*4882a593Smuzhiyun * Builds a pdu frame as a REJ command.
125*4882a593Smuzhiyun */
llc_pdu_init_as_rej_cmd(struct sk_buff * skb,u8 p_bit,u8 nr)126*4882a593Smuzhiyun void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_S;
131*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ;
132*4882a593Smuzhiyun pdu->ctrl_2 = 0;
133*4882a593Smuzhiyun pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
134*4882a593Smuzhiyun pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
135*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun /**
139*4882a593Smuzhiyun * llc_pdu_init_as_rnr_cmd - builds RNR pdu
140*4882a593Smuzhiyun * @skb: Address of the skb to build
141*4882a593Smuzhiyun * @p_bit: The P bit to set in the PDU
142*4882a593Smuzhiyun * @nr: The seq. number of the expected I PDU from the remote
143*4882a593Smuzhiyun *
144*4882a593Smuzhiyun * Builds a pdu frame as an RNR command.
145*4882a593Smuzhiyun */
llc_pdu_init_as_rnr_cmd(struct sk_buff * skb,u8 p_bit,u8 nr)146*4882a593Smuzhiyun void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_S;
151*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR;
152*4882a593Smuzhiyun pdu->ctrl_2 = 0;
153*4882a593Smuzhiyun pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
154*4882a593Smuzhiyun pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
155*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun /**
159*4882a593Smuzhiyun * llc_pdu_init_as_rr_cmd - Builds RR pdu
160*4882a593Smuzhiyun * @skb: Address of the skb to build
161*4882a593Smuzhiyun * @p_bit: The P bit to set in the PDU
162*4882a593Smuzhiyun * @nr: The seq. number of the expected I PDU from the remote
163*4882a593Smuzhiyun *
164*4882a593Smuzhiyun * Builds a pdu frame as an RR command.
165*4882a593Smuzhiyun */
llc_pdu_init_as_rr_cmd(struct sk_buff * skb,u8 p_bit,u8 nr)166*4882a593Smuzhiyun void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
167*4882a593Smuzhiyun {
168*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_S;
171*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
172*4882a593Smuzhiyun pdu->ctrl_2 = p_bit & LLC_S_PF_BIT_MASK;
173*4882a593Smuzhiyun pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
174*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun /**
178*4882a593Smuzhiyun * llc_pdu_init_as_sabme_cmd - builds SABME pdu
179*4882a593Smuzhiyun * @skb: Address of the skb to build
180*4882a593Smuzhiyun * @p_bit: The P bit to set in the PDU
181*4882a593Smuzhiyun *
182*4882a593Smuzhiyun * Builds a pdu frame as an SABME command.
183*4882a593Smuzhiyun */
llc_pdu_init_as_sabme_cmd(struct sk_buff * skb,u8 p_bit)184*4882a593Smuzhiyun void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_U;
189*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME;
190*4882a593Smuzhiyun pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun /**
194*4882a593Smuzhiyun * llc_pdu_init_as_dm_rsp - builds DM response pdu
195*4882a593Smuzhiyun * @skb: Address of the skb to build
196*4882a593Smuzhiyun * @f_bit: The F bit to set in the PDU
197*4882a593Smuzhiyun *
198*4882a593Smuzhiyun * Builds a pdu frame as a DM response.
199*4882a593Smuzhiyun */
llc_pdu_init_as_dm_rsp(struct sk_buff * skb,u8 f_bit)200*4882a593Smuzhiyun void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_U;
205*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_RSP_DM;
206*4882a593Smuzhiyun pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun /**
210*4882a593Smuzhiyun * llc_pdu_init_as_frmr_rsp - builds FRMR response PDU
211*4882a593Smuzhiyun * @skb: Address of the frame to build
212*4882a593Smuzhiyun * @prev_pdu: The rejected PDU frame
213*4882a593Smuzhiyun * @f_bit: The F bit to set in the PDU
214*4882a593Smuzhiyun * @vs: tx state vari value for the data link conn at the rejecting LLC
215*4882a593Smuzhiyun * @vr: rx state var value for the data link conn at the rejecting LLC
216*4882a593Smuzhiyun * @vzyxw: completely described in the IEEE Std 802.2 document (Pg 55)
217*4882a593Smuzhiyun *
218*4882a593Smuzhiyun * Builds a pdu frame as a FRMR response.
219*4882a593Smuzhiyun */
llc_pdu_init_as_frmr_rsp(struct sk_buff * skb,struct llc_pdu_sn * prev_pdu,u8 f_bit,u8 vs,u8 vr,u8 vzyxw)220*4882a593Smuzhiyun void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
221*4882a593Smuzhiyun u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun struct llc_frmr_info *frmr_info;
224*4882a593Smuzhiyun u8 prev_pf = 0;
225*4882a593Smuzhiyun u8 *ctrl;
226*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_U;
229*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR;
230*4882a593Smuzhiyun pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun frmr_info = (struct llc_frmr_info *)&pdu->ctrl_2;
233*4882a593Smuzhiyun ctrl = (u8 *)&prev_pdu->ctrl_1;
234*4882a593Smuzhiyun FRMR_INFO_SET_REJ_CNTRL(frmr_info,ctrl);
235*4882a593Smuzhiyun FRMR_INFO_SET_Vs(frmr_info, vs);
236*4882a593Smuzhiyun FRMR_INFO_SET_Vr(frmr_info, vr);
237*4882a593Smuzhiyun prev_pf = llc_pdu_get_pf_bit(prev_pdu);
238*4882a593Smuzhiyun FRMR_INFO_SET_C_R_BIT(frmr_info, prev_pf);
239*4882a593Smuzhiyun FRMR_INFO_SET_INVALID_PDU_CTRL_IND(frmr_info, vzyxw);
240*4882a593Smuzhiyun FRMR_INFO_SET_INVALID_PDU_INFO_IND(frmr_info, vzyxw);
241*4882a593Smuzhiyun FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw);
242*4882a593Smuzhiyun FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw);
243*4882a593Smuzhiyun FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw);
244*4882a593Smuzhiyun skb_put(skb, sizeof(struct llc_frmr_info));
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun /**
248*4882a593Smuzhiyun * llc_pdu_init_as_rr_rsp - builds RR response pdu
249*4882a593Smuzhiyun * @skb: Address of the skb to build
250*4882a593Smuzhiyun * @f_bit: The F bit to set in the PDU
251*4882a593Smuzhiyun * @nr: The seq. number of the expected data PDU from the remote
252*4882a593Smuzhiyun *
253*4882a593Smuzhiyun * Builds a pdu frame as an RR response.
254*4882a593Smuzhiyun */
llc_pdu_init_as_rr_rsp(struct sk_buff * skb,u8 f_bit,u8 nr)255*4882a593Smuzhiyun void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_S;
260*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_RSP_RR;
261*4882a593Smuzhiyun pdu->ctrl_2 = 0;
262*4882a593Smuzhiyun pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
263*4882a593Smuzhiyun pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
264*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun /**
268*4882a593Smuzhiyun * llc_pdu_init_as_rej_rsp - builds REJ response pdu
269*4882a593Smuzhiyun * @skb: Address of the skb to build
270*4882a593Smuzhiyun * @f_bit: The F bit to set in the PDU
271*4882a593Smuzhiyun * @nr: The seq. number of the expected data PDU from the remote
272*4882a593Smuzhiyun *
273*4882a593Smuzhiyun * Builds a pdu frame as a REJ response.
274*4882a593Smuzhiyun */
llc_pdu_init_as_rej_rsp(struct sk_buff * skb,u8 f_bit,u8 nr)275*4882a593Smuzhiyun void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
276*4882a593Smuzhiyun {
277*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_S;
280*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ;
281*4882a593Smuzhiyun pdu->ctrl_2 = 0;
282*4882a593Smuzhiyun pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
283*4882a593Smuzhiyun pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
284*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun /**
288*4882a593Smuzhiyun * llc_pdu_init_as_rnr_rsp - builds RNR response pdu
289*4882a593Smuzhiyun * @skb: Address of the frame to build
290*4882a593Smuzhiyun * @f_bit: The F bit to set in the PDU
291*4882a593Smuzhiyun * @nr: The seq. number of the expected data PDU from the remote
292*4882a593Smuzhiyun *
293*4882a593Smuzhiyun * Builds a pdu frame as an RNR response.
294*4882a593Smuzhiyun */
llc_pdu_init_as_rnr_rsp(struct sk_buff * skb,u8 f_bit,u8 nr)295*4882a593Smuzhiyun void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_S;
300*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
301*4882a593Smuzhiyun pdu->ctrl_2 = 0;
302*4882a593Smuzhiyun pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
303*4882a593Smuzhiyun pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
304*4882a593Smuzhiyun pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun /**
308*4882a593Smuzhiyun * llc_pdu_init_as_ua_rsp - builds UA response pdu
309*4882a593Smuzhiyun * @skb: Address of the frame to build
310*4882a593Smuzhiyun * @f_bit: The F bit to set in the PDU
311*4882a593Smuzhiyun *
312*4882a593Smuzhiyun * Builds a pdu frame as a UA response.
313*4882a593Smuzhiyun */
llc_pdu_init_as_ua_rsp(struct sk_buff * skb,u8 f_bit)314*4882a593Smuzhiyun void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun pdu->ctrl_1 = LLC_PDU_TYPE_U;
319*4882a593Smuzhiyun pdu->ctrl_1 |= LLC_2_PDU_RSP_UA;
320*4882a593Smuzhiyun pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun /**
324*4882a593Smuzhiyun * llc_pdu_decode_pdu_type - designates PDU type
325*4882a593Smuzhiyun * @skb: input skb that type of it must be designated.
326*4882a593Smuzhiyun * @type: type of PDU (output argument).
327*4882a593Smuzhiyun *
328*4882a593Smuzhiyun * This function designates type of PDU (I, S or U).
329*4882a593Smuzhiyun */
llc_pdu_decode_pdu_type(struct sk_buff * skb,u8 * type)330*4882a593Smuzhiyun static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (pdu->ctrl_1 & 1) {
335*4882a593Smuzhiyun if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
336*4882a593Smuzhiyun *type = LLC_PDU_TYPE_U;
337*4882a593Smuzhiyun else
338*4882a593Smuzhiyun *type = LLC_PDU_TYPE_S;
339*4882a593Smuzhiyun } else
340*4882a593Smuzhiyun *type = LLC_PDU_TYPE_I;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /**
344*4882a593Smuzhiyun * llc_pdu_get_pf_bit - extracts p/f bit of input PDU
345*4882a593Smuzhiyun * @pdu: pointer to LLC header.
346*4882a593Smuzhiyun *
347*4882a593Smuzhiyun * This function extracts p/f bit of input PDU. at first examines type of
348*4882a593Smuzhiyun * PDU and then extracts p/f bit. Returns the p/f bit.
349*4882a593Smuzhiyun */
llc_pdu_get_pf_bit(struct llc_pdu_sn * pdu)350*4882a593Smuzhiyun static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun u8 pdu_type;
353*4882a593Smuzhiyun u8 pf_bit = 0;
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (pdu->ctrl_1 & 1) {
356*4882a593Smuzhiyun if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
357*4882a593Smuzhiyun pdu_type = LLC_PDU_TYPE_U;
358*4882a593Smuzhiyun else
359*4882a593Smuzhiyun pdu_type = LLC_PDU_TYPE_S;
360*4882a593Smuzhiyun } else
361*4882a593Smuzhiyun pdu_type = LLC_PDU_TYPE_I;
362*4882a593Smuzhiyun switch (pdu_type) {
363*4882a593Smuzhiyun case LLC_PDU_TYPE_I:
364*4882a593Smuzhiyun case LLC_PDU_TYPE_S:
365*4882a593Smuzhiyun pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
366*4882a593Smuzhiyun break;
367*4882a593Smuzhiyun case LLC_PDU_TYPE_U:
368*4882a593Smuzhiyun pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
369*4882a593Smuzhiyun break;
370*4882a593Smuzhiyun }
371*4882a593Smuzhiyun return pf_bit;
372*4882a593Smuzhiyun }
373