1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * llc_s_ac.c - actions performed during sap state transition.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Description :
5*4882a593Smuzhiyun * Functions in this module are implementation of sap component actions.
6*4882a593Smuzhiyun * Details of actions can be found in IEEE-802.2 standard document.
7*4882a593Smuzhiyun * All functions have one sap and one event as input argument. All of
8*4882a593Smuzhiyun * them return 0 On success and 1 otherwise.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * Copyright (c) 1997 by Procom Technology, Inc.
11*4882a593Smuzhiyun * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
12*4882a593Smuzhiyun *
13*4882a593Smuzhiyun * This program can be redistributed or modified under the terms of the
14*4882a593Smuzhiyun * GNU General Public License as published by the Free Software Foundation.
15*4882a593Smuzhiyun * This program is distributed without any warranty or implied warranty
16*4882a593Smuzhiyun * of merchantability or fitness for a particular purpose.
17*4882a593Smuzhiyun *
18*4882a593Smuzhiyun * See the GNU General Public License for more details.
19*4882a593Smuzhiyun */
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include <linux/netdevice.h>
22*4882a593Smuzhiyun #include <net/llc.h>
23*4882a593Smuzhiyun #include <net/llc_pdu.h>
24*4882a593Smuzhiyun #include <net/llc_s_ac.h>
25*4882a593Smuzhiyun #include <net/llc_s_ev.h>
26*4882a593Smuzhiyun #include <net/llc_sap.h>
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /**
30*4882a593Smuzhiyun * llc_sap_action_unit_data_ind - forward UI PDU to network layer
31*4882a593Smuzhiyun * @sap: SAP
32*4882a593Smuzhiyun * @skb: the event to forward
33*4882a593Smuzhiyun *
34*4882a593Smuzhiyun * Received a UI PDU from MAC layer; forward to network layer as a
35*4882a593Smuzhiyun * UNITDATA INDICATION; verify our event is the kind we expect
36*4882a593Smuzhiyun */
llc_sap_action_unitdata_ind(struct llc_sap * sap,struct sk_buff * skb)37*4882a593Smuzhiyun int llc_sap_action_unitdata_ind(struct llc_sap *sap, struct sk_buff *skb)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun llc_sap_rtn_pdu(sap, skb);
40*4882a593Smuzhiyun return 0;
41*4882a593Smuzhiyun }
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /**
44*4882a593Smuzhiyun * llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer
45*4882a593Smuzhiyun * @sap: SAP
46*4882a593Smuzhiyun * @skb: the event to send
47*4882a593Smuzhiyun *
48*4882a593Smuzhiyun * Sends a UI PDU to the MAC layer in response to a UNITDATA REQUEST
49*4882a593Smuzhiyun * primitive from the network layer. Verifies event is a primitive type of
50*4882a593Smuzhiyun * event. Verify the primitive is a UNITDATA REQUEST.
51*4882a593Smuzhiyun */
llc_sap_action_send_ui(struct llc_sap * sap,struct sk_buff * skb)52*4882a593Smuzhiyun int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun struct llc_sap_state_ev *ev = llc_sap_ev(skb);
55*4882a593Smuzhiyun int rc;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
58*4882a593Smuzhiyun ev->daddr.lsap, LLC_PDU_CMD);
59*4882a593Smuzhiyun llc_pdu_init_as_ui_cmd(skb);
60*4882a593Smuzhiyun rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
61*4882a593Smuzhiyun if (likely(!rc)) {
62*4882a593Smuzhiyun skb_get(skb);
63*4882a593Smuzhiyun rc = dev_queue_xmit(skb);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun return rc;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun /**
69*4882a593Smuzhiyun * llc_sap_action_send_xid_c - send XID PDU as response to XID REQ
70*4882a593Smuzhiyun * @sap: SAP
71*4882a593Smuzhiyun * @skb: the event to send
72*4882a593Smuzhiyun *
73*4882a593Smuzhiyun * Send a XID command PDU to MAC layer in response to a XID REQUEST
74*4882a593Smuzhiyun * primitive from the network layer. Verify event is a primitive type
75*4882a593Smuzhiyun * event. Verify the primitive is a XID REQUEST.
76*4882a593Smuzhiyun */
llc_sap_action_send_xid_c(struct llc_sap * sap,struct sk_buff * skb)77*4882a593Smuzhiyun int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
78*4882a593Smuzhiyun {
79*4882a593Smuzhiyun struct llc_sap_state_ev *ev = llc_sap_ev(skb);
80*4882a593Smuzhiyun int rc;
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun llc_pdu_header_init(skb, LLC_PDU_TYPE_U_XID, ev->saddr.lsap,
83*4882a593Smuzhiyun ev->daddr.lsap, LLC_PDU_CMD);
84*4882a593Smuzhiyun llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
85*4882a593Smuzhiyun rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
86*4882a593Smuzhiyun if (likely(!rc)) {
87*4882a593Smuzhiyun skb_get(skb);
88*4882a593Smuzhiyun rc = dev_queue_xmit(skb);
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun return rc;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun /**
94*4882a593Smuzhiyun * llc_sap_action_send_xid_r - send XID PDU resp to MAC for received XID
95*4882a593Smuzhiyun * @sap: SAP
96*4882a593Smuzhiyun * @skb: the event to send
97*4882a593Smuzhiyun *
98*4882a593Smuzhiyun * Send XID response PDU to MAC in response to an earlier received XID
99*4882a593Smuzhiyun * command PDU. Verify event is a PDU type event
100*4882a593Smuzhiyun */
llc_sap_action_send_xid_r(struct llc_sap * sap,struct sk_buff * skb)101*4882a593Smuzhiyun int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
104*4882a593Smuzhiyun int rc = 1;
105*4882a593Smuzhiyun struct sk_buff *nskb;
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun llc_pdu_decode_sa(skb, mac_da);
108*4882a593Smuzhiyun llc_pdu_decode_da(skb, mac_sa);
109*4882a593Smuzhiyun llc_pdu_decode_ssap(skb, &dsap);
110*4882a593Smuzhiyun nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U,
111*4882a593Smuzhiyun sizeof(struct llc_xid_info));
112*4882a593Smuzhiyun if (!nskb)
113*4882a593Smuzhiyun goto out;
114*4882a593Smuzhiyun llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
115*4882a593Smuzhiyun LLC_PDU_RSP);
116*4882a593Smuzhiyun llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
117*4882a593Smuzhiyun rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
118*4882a593Smuzhiyun if (likely(!rc))
119*4882a593Smuzhiyun rc = dev_queue_xmit(nskb);
120*4882a593Smuzhiyun out:
121*4882a593Smuzhiyun return rc;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun /**
125*4882a593Smuzhiyun * llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ
126*4882a593Smuzhiyun * @sap: SAP
127*4882a593Smuzhiyun * @skb: the event to send
128*4882a593Smuzhiyun *
129*4882a593Smuzhiyun * Send a TEST command PDU to the MAC layer in response to a TEST REQUEST
130*4882a593Smuzhiyun * primitive from the network layer. Verify event is a primitive type
131*4882a593Smuzhiyun * event; verify the primitive is a TEST REQUEST.
132*4882a593Smuzhiyun */
llc_sap_action_send_test_c(struct llc_sap * sap,struct sk_buff * skb)133*4882a593Smuzhiyun int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun struct llc_sap_state_ev *ev = llc_sap_ev(skb);
136*4882a593Smuzhiyun int rc;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
139*4882a593Smuzhiyun ev->daddr.lsap, LLC_PDU_CMD);
140*4882a593Smuzhiyun llc_pdu_init_as_test_cmd(skb);
141*4882a593Smuzhiyun rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
142*4882a593Smuzhiyun if (likely(!rc)) {
143*4882a593Smuzhiyun skb_get(skb);
144*4882a593Smuzhiyun rc = dev_queue_xmit(skb);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun return rc;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
llc_sap_action_send_test_r(struct llc_sap * sap,struct sk_buff * skb)149*4882a593Smuzhiyun int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
152*4882a593Smuzhiyun struct sk_buff *nskb;
153*4882a593Smuzhiyun int rc = 1;
154*4882a593Smuzhiyun u32 data_size;
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun llc_pdu_decode_sa(skb, mac_da);
157*4882a593Smuzhiyun llc_pdu_decode_da(skb, mac_sa);
158*4882a593Smuzhiyun llc_pdu_decode_ssap(skb, &dsap);
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* The test request command is type U (llc_len = 3) */
161*4882a593Smuzhiyun data_size = ntohs(eth_hdr(skb)->h_proto) - 3;
162*4882a593Smuzhiyun nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, data_size);
163*4882a593Smuzhiyun if (!nskb)
164*4882a593Smuzhiyun goto out;
165*4882a593Smuzhiyun llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
166*4882a593Smuzhiyun LLC_PDU_RSP);
167*4882a593Smuzhiyun llc_pdu_init_as_test_rsp(nskb, skb);
168*4882a593Smuzhiyun rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
169*4882a593Smuzhiyun if (likely(!rc))
170*4882a593Smuzhiyun rc = dev_queue_xmit(nskb);
171*4882a593Smuzhiyun out:
172*4882a593Smuzhiyun return rc;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun /**
176*4882a593Smuzhiyun * llc_sap_action_report_status - report data link status to layer mgmt
177*4882a593Smuzhiyun * @sap: SAP
178*4882a593Smuzhiyun * @skb: the event to send
179*4882a593Smuzhiyun *
180*4882a593Smuzhiyun * Report data link status to layer management. Verify our event is the
181*4882a593Smuzhiyun * kind we expect.
182*4882a593Smuzhiyun */
llc_sap_action_report_status(struct llc_sap * sap,struct sk_buff * skb)183*4882a593Smuzhiyun int llc_sap_action_report_status(struct llc_sap *sap, struct sk_buff *skb)
184*4882a593Smuzhiyun {
185*4882a593Smuzhiyun return 0;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /**
189*4882a593Smuzhiyun * llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND
190*4882a593Smuzhiyun * @sap: SAP
191*4882a593Smuzhiyun * @skb: the event to send
192*4882a593Smuzhiyun *
193*4882a593Smuzhiyun * Send a XID response PDU to the network layer via a XID INDICATION
194*4882a593Smuzhiyun * primitive.
195*4882a593Smuzhiyun */
llc_sap_action_xid_ind(struct llc_sap * sap,struct sk_buff * skb)196*4882a593Smuzhiyun int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun llc_sap_rtn_pdu(sap, skb);
199*4882a593Smuzhiyun return 0;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun /**
203*4882a593Smuzhiyun * llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND
204*4882a593Smuzhiyun * @sap: SAP
205*4882a593Smuzhiyun * @skb: the event to send
206*4882a593Smuzhiyun *
207*4882a593Smuzhiyun * Send a TEST response PDU to the network layer via a TEST INDICATION
208*4882a593Smuzhiyun * primitive. Verify our event is a PDU type event.
209*4882a593Smuzhiyun */
llc_sap_action_test_ind(struct llc_sap * sap,struct sk_buff * skb)210*4882a593Smuzhiyun int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun llc_sap_rtn_pdu(sap, skb);
213*4882a593Smuzhiyun return 0;
214*4882a593Smuzhiyun }
215