diff options
Diffstat (limited to 'net/llc')
-rw-r--r-- | net/llc/llc_station.c | 404 |
1 files changed, 9 insertions, 395 deletions
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index e16c1b96e527..917d700791ba 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c | |||
@@ -30,19 +30,12 @@ | |||
30 | * | 30 | * |
31 | * SAP and connection resource manager, one per adapter. | 31 | * SAP and connection resource manager, one per adapter. |
32 | * | 32 | * |
33 | * @state: state of station | ||
34 | * @xid_r_count: XID response PDU counter | ||
35 | * @mac_sa: MAC source address | 33 | * @mac_sa: MAC source address |
36 | * @sap_list: list of related SAPs | 34 | * @sap_list: list of related SAPs |
37 | * @ev_q: events entering state mach. | 35 | * @ev_q: events entering state mach. |
38 | * @mac_pdu_q: PDUs ready to send to MAC | 36 | * @mac_pdu_q: PDUs ready to send to MAC |
39 | */ | 37 | */ |
40 | struct llc_station { | 38 | struct llc_station { |
41 | u8 state; | ||
42 | u8 xid_r_count; | ||
43 | struct timer_list ack_timer; | ||
44 | u8 retry_count; | ||
45 | u8 maximum_retry; | ||
46 | struct { | 39 | struct { |
47 | struct sk_buff_head list; | 40 | struct sk_buff_head list; |
48 | spinlock_t lock; | 41 | spinlock_t lock; |
@@ -50,162 +43,38 @@ struct llc_station { | |||
50 | struct sk_buff_head mac_pdu_q; | 43 | struct sk_buff_head mac_pdu_q; |
51 | }; | 44 | }; |
52 | 45 | ||
53 | #define LLC_STATION_ACK_TIME (3 * HZ) | ||
54 | |||
55 | int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME; | ||
56 | |||
57 | /* Types of events (possible values in 'ev->type') */ | ||
58 | #define LLC_STATION_EV_TYPE_SIMPLE 1 | ||
59 | #define LLC_STATION_EV_TYPE_CONDITION 2 | ||
60 | #define LLC_STATION_EV_TYPE_PRIM 3 | ||
61 | #define LLC_STATION_EV_TYPE_PDU 4 /* command/response PDU */ | ||
62 | #define LLC_STATION_EV_TYPE_ACK_TMR 5 | ||
63 | #define LLC_STATION_EV_TYPE_RPT_STATUS 6 | ||
64 | |||
65 | /* Events */ | ||
66 | #define LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK 1 | ||
67 | #define LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK 2 | ||
68 | #define LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY 3 | ||
69 | #define LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY 4 | ||
70 | #define LLC_STATION_EV_RX_NULL_DSAP_XID_C 5 | ||
71 | #define LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ 6 | ||
72 | #define LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ 7 | ||
73 | #define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8 | ||
74 | #define LLC_STATION_EV_DISABLE_REQ 9 | ||
75 | |||
76 | struct llc_station_state_ev { | ||
77 | u8 type; | ||
78 | u8 prim; | ||
79 | u8 prim_type; | ||
80 | u8 reason; | ||
81 | struct list_head node; /* node in station->ev_q.list */ | ||
82 | }; | ||
83 | |||
84 | static __inline__ struct llc_station_state_ev * | ||
85 | llc_station_ev(struct sk_buff *skb) | ||
86 | { | ||
87 | return (struct llc_station_state_ev *)skb->cb; | ||
88 | } | ||
89 | |||
90 | typedef int (*llc_station_ev_t)(struct sk_buff *skb); | 46 | typedef int (*llc_station_ev_t)(struct sk_buff *skb); |
91 | 47 | ||
92 | #define LLC_STATION_STATE_DOWN 1 /* initial state */ | ||
93 | #define LLC_STATION_STATE_DUP_ADDR_CHK 2 | ||
94 | #define LLC_STATION_STATE_UP 3 | ||
95 | |||
96 | #define LLC_NBR_STATION_STATES 3 /* size of state table */ | ||
97 | |||
98 | typedef int (*llc_station_action_t)(struct sk_buff *skb); | 48 | typedef int (*llc_station_action_t)(struct sk_buff *skb); |
99 | 49 | ||
100 | /* Station component state table structure */ | 50 | /* Station component state table structure */ |
101 | struct llc_station_state_trans { | 51 | struct llc_station_state_trans { |
102 | llc_station_ev_t ev; | 52 | llc_station_ev_t ev; |
103 | u8 next_state; | ||
104 | llc_station_action_t *ev_actions; | 53 | llc_station_action_t *ev_actions; |
105 | }; | 54 | }; |
106 | 55 | ||
107 | struct llc_station_state { | ||
108 | u8 curr_state; | ||
109 | struct llc_station_state_trans **transitions; | ||
110 | }; | ||
111 | |||
112 | static struct llc_station llc_main_station; | 56 | static struct llc_station llc_main_station; |
113 | 57 | ||
114 | static int llc_stat_ev_enable_with_dup_addr_check(struct sk_buff *skb) | ||
115 | { | ||
116 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
117 | |||
118 | return ev->type == LLC_STATION_EV_TYPE_SIMPLE && | ||
119 | ev->prim_type == | ||
120 | LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1; | ||
121 | } | ||
122 | |||
123 | static int llc_stat_ev_enable_without_dup_addr_check(struct sk_buff *skb) | ||
124 | { | ||
125 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
126 | |||
127 | return ev->type == LLC_STATION_EV_TYPE_SIMPLE && | ||
128 | ev->prim_type == | ||
129 | LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1; | ||
130 | } | ||
131 | |||
132 | static int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct sk_buff *skb) | ||
133 | { | ||
134 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
135 | |||
136 | return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && | ||
137 | llc_main_station.retry_count < | ||
138 | llc_main_station.maximum_retry ? 0 : 1; | ||
139 | } | ||
140 | |||
141 | static int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct sk_buff *skb) | ||
142 | { | ||
143 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
144 | |||
145 | return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && | ||
146 | llc_main_station.retry_count == | ||
147 | llc_main_station.maximum_retry ? 0 : 1; | ||
148 | } | ||
149 | |||
150 | static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb) | 58 | static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb) |
151 | { | 59 | { |
152 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
153 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); | 60 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); |
154 | 61 | ||
155 | return ev->type == LLC_STATION_EV_TYPE_PDU && | 62 | return LLC_PDU_IS_CMD(pdu) && /* command PDU */ |
156 | LLC_PDU_IS_CMD(pdu) && /* command PDU */ | ||
157 | LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ | 63 | LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ |
158 | LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID && | 64 | LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID && |
159 | !pdu->dsap ? 0 : 1; /* NULL DSAP value */ | 65 | !pdu->dsap ? 0 : 1; /* NULL DSAP value */ |
160 | } | 66 | } |
161 | 67 | ||
162 | static int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct sk_buff *skb) | ||
163 | { | ||
164 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
165 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); | ||
166 | |||
167 | return ev->type == LLC_STATION_EV_TYPE_PDU && | ||
168 | LLC_PDU_IS_RSP(pdu) && /* response PDU */ | ||
169 | LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ | ||
170 | LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID && | ||
171 | !pdu->dsap && /* NULL DSAP value */ | ||
172 | !llc_main_station.xid_r_count ? 0 : 1; | ||
173 | } | ||
174 | |||
175 | static int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct sk_buff *skb) | ||
176 | { | ||
177 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
178 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); | ||
179 | |||
180 | return ev->type == LLC_STATION_EV_TYPE_PDU && | ||
181 | LLC_PDU_IS_RSP(pdu) && /* response PDU */ | ||
182 | LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ | ||
183 | LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID && | ||
184 | !pdu->dsap && /* NULL DSAP value */ | ||
185 | llc_main_station.xid_r_count == 1 ? 0 : 1; | ||
186 | } | ||
187 | |||
188 | static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb) | 68 | static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb) |
189 | { | 69 | { |
190 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
191 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); | 70 | struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); |
192 | 71 | ||
193 | return ev->type == LLC_STATION_EV_TYPE_PDU && | 72 | return LLC_PDU_IS_CMD(pdu) && /* command PDU */ |
194 | LLC_PDU_IS_CMD(pdu) && /* command PDU */ | ||
195 | LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ | 73 | LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ |
196 | LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST && | 74 | LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST && |
197 | !pdu->dsap ? 0 : 1; /* NULL DSAP */ | 75 | !pdu->dsap ? 0 : 1; /* NULL DSAP */ |
198 | } | 76 | } |
199 | 77 | ||
200 | static int llc_stat_ev_disable_req(struct sk_buff *skb) | ||
201 | { | ||
202 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
203 | |||
204 | return ev->type == LLC_STATION_EV_TYPE_PRIM && | ||
205 | ev->prim == LLC_DISABLE_PRIM && | ||
206 | ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; | ||
207 | } | ||
208 | |||
209 | /** | 78 | /** |
210 | * llc_station_send_pdu - queues PDU to send | 79 | * llc_station_send_pdu - queues PDU to send |
211 | * @skb: Address of the PDU | 80 | * @skb: Address of the PDU |
@@ -220,58 +89,6 @@ static void llc_station_send_pdu(struct sk_buff *skb) | |||
220 | break; | 89 | break; |
221 | } | 90 | } |
222 | 91 | ||
223 | static int llc_station_ac_start_ack_timer(struct sk_buff *skb) | ||
224 | { | ||
225 | mod_timer(&llc_main_station.ack_timer, | ||
226 | jiffies + sysctl_llc_station_ack_timeout); | ||
227 | return 0; | ||
228 | } | ||
229 | |||
230 | static int llc_station_ac_set_retry_cnt_0(struct sk_buff *skb) | ||
231 | { | ||
232 | llc_main_station.retry_count = 0; | ||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int llc_station_ac_inc_retry_cnt_by_1(struct sk_buff *skb) | ||
237 | { | ||
238 | llc_main_station.retry_count++; | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int llc_station_ac_set_xid_r_cnt_0(struct sk_buff *skb) | ||
243 | { | ||
244 | llc_main_station.xid_r_count = 0; | ||
245 | return 0; | ||
246 | } | ||
247 | |||
248 | static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) | ||
249 | { | ||
250 | llc_main_station.xid_r_count++; | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) | ||
255 | { | ||
256 | int rc = 1; | ||
257 | struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, | ||
258 | sizeof(struct llc_xid_info)); | ||
259 | |||
260 | if (!nskb) | ||
261 | goto out; | ||
262 | llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); | ||
263 | llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); | ||
264 | rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, skb->dev->dev_addr); | ||
265 | if (unlikely(rc)) | ||
266 | goto free; | ||
267 | llc_station_send_pdu(nskb); | ||
268 | out: | ||
269 | return rc; | ||
270 | free: | ||
271 | kfree_skb(nskb); | ||
272 | goto out; | ||
273 | } | ||
274 | |||
275 | static int llc_station_ac_send_xid_r(struct sk_buff *skb) | 92 | static int llc_station_ac_send_xid_r(struct sk_buff *skb) |
276 | { | 93 | { |
277 | u8 mac_da[ETH_ALEN], dsap; | 94 | u8 mac_da[ETH_ALEN], dsap; |
@@ -326,60 +143,6 @@ free: | |||
326 | goto out; | 143 | goto out; |
327 | } | 144 | } |
328 | 145 | ||
329 | static int llc_station_ac_report_status(struct sk_buff *skb) | ||
330 | { | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | /* DOWN STATE transitions */ | ||
335 | |||
336 | /* state transition for LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */ | ||
337 | static llc_station_action_t llc_stat_down_state_actions_1[] = { | ||
338 | [0] = llc_station_ac_start_ack_timer, | ||
339 | [1] = llc_station_ac_set_retry_cnt_0, | ||
340 | [2] = llc_station_ac_set_xid_r_cnt_0, | ||
341 | [3] = llc_station_ac_send_null_dsap_xid_c, | ||
342 | [4] = NULL, | ||
343 | }; | ||
344 | |||
345 | static struct llc_station_state_trans llc_stat_down_state_trans_1 = { | ||
346 | .ev = llc_stat_ev_enable_with_dup_addr_check, | ||
347 | .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, | ||
348 | .ev_actions = llc_stat_down_state_actions_1, | ||
349 | }; | ||
350 | |||
351 | /* state transition for LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK event */ | ||
352 | static llc_station_action_t llc_stat_down_state_actions_2[] = { | ||
353 | [0] = llc_station_ac_report_status, /* STATION UP */ | ||
354 | [1] = NULL, | ||
355 | }; | ||
356 | |||
357 | static struct llc_station_state_trans llc_stat_down_state_trans_2 = { | ||
358 | .ev = llc_stat_ev_enable_without_dup_addr_check, | ||
359 | .next_state = LLC_STATION_STATE_UP, | ||
360 | .ev_actions = llc_stat_down_state_actions_2, | ||
361 | }; | ||
362 | |||
363 | /* array of pointers; one to each transition */ | ||
364 | static struct llc_station_state_trans *llc_stat_dwn_state_trans[] = { | ||
365 | [0] = &llc_stat_down_state_trans_1, | ||
366 | [1] = &llc_stat_down_state_trans_2, | ||
367 | [2] = NULL, | ||
368 | }; | ||
369 | |||
370 | /* UP STATE transitions */ | ||
371 | /* state transition for LLC_STATION_EV_DISABLE_REQ event */ | ||
372 | static llc_station_action_t llc_stat_up_state_actions_1[] = { | ||
373 | [0] = llc_station_ac_report_status, /* STATION DOWN */ | ||
374 | [1] = NULL, | ||
375 | }; | ||
376 | |||
377 | static struct llc_station_state_trans llc_stat_up_state_trans_1 = { | ||
378 | .ev = llc_stat_ev_disable_req, | ||
379 | .next_state = LLC_STATION_STATE_DOWN, | ||
380 | .ev_actions = llc_stat_up_state_actions_1, | ||
381 | }; | ||
382 | |||
383 | /* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ | 146 | /* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ |
384 | static llc_station_action_t llc_stat_up_state_actions_2[] = { | 147 | static llc_station_action_t llc_stat_up_state_actions_2[] = { |
385 | [0] = llc_station_ac_send_xid_r, | 148 | [0] = llc_station_ac_send_xid_r, |
@@ -388,7 +151,6 @@ static llc_station_action_t llc_stat_up_state_actions_2[] = { | |||
388 | 151 | ||
389 | static struct llc_station_state_trans llc_stat_up_state_trans_2 = { | 152 | static struct llc_station_state_trans llc_stat_up_state_trans_2 = { |
390 | .ev = llc_stat_ev_rx_null_dsap_xid_c, | 153 | .ev = llc_stat_ev_rx_null_dsap_xid_c, |
391 | .next_state = LLC_STATION_STATE_UP, | ||
392 | .ev_actions = llc_stat_up_state_actions_2, | 154 | .ev_actions = llc_stat_up_state_actions_2, |
393 | }; | 155 | }; |
394 | 156 | ||
@@ -400,127 +162,14 @@ static llc_station_action_t llc_stat_up_state_actions_3[] = { | |||
400 | 162 | ||
401 | static struct llc_station_state_trans llc_stat_up_state_trans_3 = { | 163 | static struct llc_station_state_trans llc_stat_up_state_trans_3 = { |
402 | .ev = llc_stat_ev_rx_null_dsap_test_c, | 164 | .ev = llc_stat_ev_rx_null_dsap_test_c, |
403 | .next_state = LLC_STATION_STATE_UP, | ||
404 | .ev_actions = llc_stat_up_state_actions_3, | 165 | .ev_actions = llc_stat_up_state_actions_3, |
405 | }; | 166 | }; |
406 | 167 | ||
407 | /* array of pointers; one to each transition */ | 168 | /* array of pointers; one to each transition */ |
408 | static struct llc_station_state_trans *llc_stat_up_state_trans [] = { | 169 | static struct llc_station_state_trans *llc_stat_up_state_trans [] = { |
409 | [0] = &llc_stat_up_state_trans_1, | 170 | &llc_stat_up_state_trans_2, |
410 | [1] = &llc_stat_up_state_trans_2, | 171 | &llc_stat_up_state_trans_3, |
411 | [2] = &llc_stat_up_state_trans_3, | 172 | NULL, |
412 | [3] = NULL, | ||
413 | }; | ||
414 | |||
415 | /* DUP ADDR CHK STATE transitions */ | ||
416 | /* state transition for LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ | ||
417 | * event | ||
418 | */ | ||
419 | static llc_station_action_t llc_stat_dupaddr_state_actions_1[] = { | ||
420 | [0] = llc_station_ac_inc_xid_r_cnt_by_1, | ||
421 | [1] = NULL, | ||
422 | }; | ||
423 | |||
424 | static struct llc_station_state_trans llc_stat_dupaddr_state_trans_1 = { | ||
425 | .ev = llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq, | ||
426 | .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, | ||
427 | .ev_actions = llc_stat_dupaddr_state_actions_1, | ||
428 | }; | ||
429 | |||
430 | /* state transition for LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ | ||
431 | * event | ||
432 | */ | ||
433 | static llc_station_action_t llc_stat_dupaddr_state_actions_2[] = { | ||
434 | [0] = llc_station_ac_report_status, /* DUPLICATE ADDRESS FOUND */ | ||
435 | [1] = NULL, | ||
436 | }; | ||
437 | |||
438 | static struct llc_station_state_trans llc_stat_dupaddr_state_trans_2 = { | ||
439 | .ev = llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq, | ||
440 | .next_state = LLC_STATION_STATE_DOWN, | ||
441 | .ev_actions = llc_stat_dupaddr_state_actions_2, | ||
442 | }; | ||
443 | |||
444 | /* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ | ||
445 | static llc_station_action_t llc_stat_dupaddr_state_actions_3[] = { | ||
446 | [0] = llc_station_ac_send_xid_r, | ||
447 | [1] = NULL, | ||
448 | }; | ||
449 | |||
450 | static struct llc_station_state_trans llc_stat_dupaddr_state_trans_3 = { | ||
451 | .ev = llc_stat_ev_rx_null_dsap_xid_c, | ||
452 | .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, | ||
453 | .ev_actions = llc_stat_dupaddr_state_actions_3, | ||
454 | }; | ||
455 | |||
456 | /* state transition for LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY | ||
457 | * event | ||
458 | */ | ||
459 | static llc_station_action_t llc_stat_dupaddr_state_actions_4[] = { | ||
460 | [0] = llc_station_ac_start_ack_timer, | ||
461 | [1] = llc_station_ac_inc_retry_cnt_by_1, | ||
462 | [2] = llc_station_ac_set_xid_r_cnt_0, | ||
463 | [3] = llc_station_ac_send_null_dsap_xid_c, | ||
464 | [4] = NULL, | ||
465 | }; | ||
466 | |||
467 | static struct llc_station_state_trans llc_stat_dupaddr_state_trans_4 = { | ||
468 | .ev = llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry, | ||
469 | .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, | ||
470 | .ev_actions = llc_stat_dupaddr_state_actions_4, | ||
471 | }; | ||
472 | |||
473 | /* state transition for LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY | ||
474 | * event | ||
475 | */ | ||
476 | static llc_station_action_t llc_stat_dupaddr_state_actions_5[] = { | ||
477 | [0] = llc_station_ac_report_status, /* STATION UP */ | ||
478 | [1] = NULL, | ||
479 | }; | ||
480 | |||
481 | static struct llc_station_state_trans llc_stat_dupaddr_state_trans_5 = { | ||
482 | .ev = llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry, | ||
483 | .next_state = LLC_STATION_STATE_UP, | ||
484 | .ev_actions = llc_stat_dupaddr_state_actions_5, | ||
485 | }; | ||
486 | |||
487 | /* state transition for LLC_STATION_EV_DISABLE_REQ event */ | ||
488 | static llc_station_action_t llc_stat_dupaddr_state_actions_6[] = { | ||
489 | [0] = llc_station_ac_report_status, /* STATION DOWN */ | ||
490 | [1] = NULL, | ||
491 | }; | ||
492 | |||
493 | static struct llc_station_state_trans llc_stat_dupaddr_state_trans_6 = { | ||
494 | .ev = llc_stat_ev_disable_req, | ||
495 | .next_state = LLC_STATION_STATE_DOWN, | ||
496 | .ev_actions = llc_stat_dupaddr_state_actions_6, | ||
497 | }; | ||
498 | |||
499 | /* array of pointers; one to each transition */ | ||
500 | static struct llc_station_state_trans *llc_stat_dupaddr_state_trans[] = { | ||
501 | [0] = &llc_stat_dupaddr_state_trans_6, /* Request */ | ||
502 | [1] = &llc_stat_dupaddr_state_trans_4, /* Timer */ | ||
503 | [2] = &llc_stat_dupaddr_state_trans_5, | ||
504 | [3] = &llc_stat_dupaddr_state_trans_1, /* Receive frame */ | ||
505 | [4] = &llc_stat_dupaddr_state_trans_2, | ||
506 | [5] = &llc_stat_dupaddr_state_trans_3, | ||
507 | [6] = NULL, | ||
508 | }; | ||
509 | |||
510 | static struct llc_station_state | ||
511 | llc_station_state_table[LLC_NBR_STATION_STATES] = { | ||
512 | [LLC_STATION_STATE_DOWN - 1] = { | ||
513 | .curr_state = LLC_STATION_STATE_DOWN, | ||
514 | .transitions = llc_stat_dwn_state_trans, | ||
515 | }, | ||
516 | [LLC_STATION_STATE_DUP_ADDR_CHK - 1] = { | ||
517 | .curr_state = LLC_STATION_STATE_DUP_ADDR_CHK, | ||
518 | .transitions = llc_stat_dupaddr_state_trans, | ||
519 | }, | ||
520 | [LLC_STATION_STATE_UP - 1] = { | ||
521 | .curr_state = LLC_STATION_STATE_UP, | ||
522 | .transitions = llc_stat_up_state_trans, | ||
523 | }, | ||
524 | }; | 173 | }; |
525 | 174 | ||
526 | /** | 175 | /** |
@@ -557,10 +206,8 @@ static struct llc_station_state_trans * | |||
557 | int i = 0; | 206 | int i = 0; |
558 | struct llc_station_state_trans *rc = NULL; | 207 | struct llc_station_state_trans *rc = NULL; |
559 | struct llc_station_state_trans **next_trans; | 208 | struct llc_station_state_trans **next_trans; |
560 | struct llc_station_state *curr_state = | ||
561 | &llc_station_state_table[llc_main_station.state - 1]; | ||
562 | 209 | ||
563 | for (next_trans = curr_state->transitions; next_trans[i]; i++) | 210 | for (next_trans = llc_stat_up_state_trans; next_trans[i]; i++) |
564 | if (!next_trans[i]->ev(skb)) { | 211 | if (!next_trans[i]->ev(skb)) { |
565 | rc = next_trans[i]; | 212 | rc = next_trans[i]; |
566 | break; | 213 | break; |
@@ -576,10 +223,7 @@ static struct llc_station_state_trans * | |||
576 | */ | 223 | */ |
577 | static void llc_station_free_ev(struct sk_buff *skb) | 224 | static void llc_station_free_ev(struct sk_buff *skb) |
578 | { | 225 | { |
579 | struct llc_station_state_ev *ev = llc_station_ev(skb); | 226 | kfree_skb(skb); |
580 | |||
581 | if (ev->type == LLC_STATION_EV_TYPE_PDU) | ||
582 | kfree_skb(skb); | ||
583 | } | 227 | } |
584 | 228 | ||
585 | /** | 229 | /** |
@@ -594,26 +238,18 @@ static u16 llc_station_next_state(struct sk_buff *skb) | |||
594 | u16 rc = 1; | 238 | u16 rc = 1; |
595 | struct llc_station_state_trans *trans; | 239 | struct llc_station_state_trans *trans; |
596 | 240 | ||
597 | if (llc_main_station.state > LLC_NBR_STATION_STATES) | ||
598 | goto out; | ||
599 | trans = llc_find_station_trans(skb); | 241 | trans = llc_find_station_trans(skb); |
600 | if (trans) { | 242 | if (trans) |
601 | /* got the state to which we next transition; perform the | 243 | /* got the state to which we next transition; perform the |
602 | * actions associated with this transition before actually | 244 | * actions associated with this transition before actually |
603 | * transitioning to the next state | 245 | * transitioning to the next state |
604 | */ | 246 | */ |
605 | rc = llc_exec_station_trans_actions(trans, skb); | 247 | rc = llc_exec_station_trans_actions(trans, skb); |
606 | if (!rc) | 248 | else |
607 | /* transition station to next state if all actions | ||
608 | * execute successfully; done; wait for next event | ||
609 | */ | ||
610 | llc_main_station.state = trans->next_state; | ||
611 | } else | ||
612 | /* event not recognized in current state; re-queue it for | 249 | /* event not recognized in current state; re-queue it for |
613 | * processing again at a later time; return failure | 250 | * processing again at a later time; return failure |
614 | */ | 251 | */ |
615 | rc = 0; | 252 | rc = 0; |
616 | out: | ||
617 | llc_station_free_ev(skb); | 253 | llc_station_free_ev(skb); |
618 | return rc; | 254 | return rc; |
619 | } | 255 | } |
@@ -652,18 +288,6 @@ static void llc_station_state_process(struct sk_buff *skb) | |||
652 | spin_unlock_bh(&llc_main_station.ev_q.lock); | 288 | spin_unlock_bh(&llc_main_station.ev_q.lock); |
653 | } | 289 | } |
654 | 290 | ||
655 | static void llc_station_ack_tmr_cb(unsigned long timeout_data) | ||
656 | { | ||
657 | struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); | ||
658 | |||
659 | if (skb) { | ||
660 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
661 | |||
662 | ev->type = LLC_STATION_EV_TYPE_ACK_TMR; | ||
663 | llc_station_state_process(skb); | ||
664 | } | ||
665 | } | ||
666 | |||
667 | /** | 291 | /** |
668 | * llc_station_rcv - send received pdu to the station state machine | 292 | * llc_station_rcv - send received pdu to the station state machine |
669 | * @skb: received frame. | 293 | * @skb: received frame. |
@@ -672,10 +296,6 @@ static void llc_station_ack_tmr_cb(unsigned long timeout_data) | |||
672 | */ | 296 | */ |
673 | static void llc_station_rcv(struct sk_buff *skb) | 297 | static void llc_station_rcv(struct sk_buff *skb) |
674 | { | 298 | { |
675 | struct llc_station_state_ev *ev = llc_station_ev(skb); | ||
676 | |||
677 | ev->type = LLC_STATION_EV_TYPE_PDU; | ||
678 | ev->reason = 0; | ||
679 | llc_station_state_process(skb); | 299 | llc_station_state_process(skb); |
680 | } | 300 | } |
681 | 301 | ||
@@ -684,12 +304,6 @@ void __init llc_station_init(void) | |||
684 | skb_queue_head_init(&llc_main_station.mac_pdu_q); | 304 | skb_queue_head_init(&llc_main_station.mac_pdu_q); |
685 | skb_queue_head_init(&llc_main_station.ev_q.list); | 305 | skb_queue_head_init(&llc_main_station.ev_q.list); |
686 | spin_lock_init(&llc_main_station.ev_q.lock); | 306 | spin_lock_init(&llc_main_station.ev_q.lock); |
687 | setup_timer(&llc_main_station.ack_timer, llc_station_ack_tmr_cb, | ||
688 | (unsigned long)&llc_main_station); | ||
689 | llc_main_station.ack_timer.expires = jiffies + | ||
690 | sysctl_llc_station_ack_timeout; | ||
691 | llc_main_station.maximum_retry = 1; | ||
692 | llc_main_station.state = LLC_STATION_STATE_UP; | ||
693 | llc_set_station_handler(llc_station_rcv); | 307 | llc_set_station_handler(llc_station_rcv); |
694 | } | 308 | } |
695 | 309 | ||