diff options
Diffstat (limited to 'net/llc')
-rw-r--r-- | net/llc/af_llc.c | 8 | ||||
-rw-r--r-- | net/llc/llc_input.c | 21 | ||||
-rw-r--r-- | net/llc/llc_proc.c | 2 | ||||
-rw-r--r-- | net/llc/llc_station.c | 619 | ||||
-rw-r--r-- | net/llc/sysctl_net_llc.c | 7 |
5 files changed, 33 insertions, 624 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f6fe4d40050..c2190005a11 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -969,14 +969,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_llc sllc; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = 0; + int rc = -EBADF; memset(&sllc, 0, sizeof(sllc)); lock_sock(sk); if (sock_flag(sk, SOCK_ZAPPED)) goto out; *uaddrlen = sizeof(sllc); - memset(uaddr, 0, *uaddrlen); if (peer) { rc = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) @@ -1206,7 +1205,7 @@ static int __init llc2_init(void) rc = llc_proc_init(); if (rc != 0) { printk(llc_proc_err_msg); - goto out_unregister_llc_proto; + goto out_station; } rc = llc_sysctl_init(); if (rc) { @@ -1226,7 +1225,8 @@ out_sysctl: llc_sysctl_exit(); out_proc: llc_proc_exit(); -out_unregister_llc_proto: +out_station: + llc_station_exit(); proto_unregister(&llc_proto); goto out; } diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index e32cab44ea9..dd3e83328ad 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -42,6 +42,7 @@ static void (*llc_type_handlers[2])(struct llc_sap *sap, void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, struct sk_buff *skb)) { + smp_wmb(); /* ensure initialisation is complete before it's called */ if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) llc_type_handlers[type - 1] = handler; } @@ -50,11 +51,19 @@ void llc_remove_pack(int type) { if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) llc_type_handlers[type - 1] = NULL; + synchronize_net(); } void llc_set_station_handler(void (*handler)(struct sk_buff *skb)) { + /* Ensure initialisation is complete before it's called */ + if (handler) + smp_wmb(); + llc_station_handler = handler; + + if (!handler) + synchronize_net(); } /** @@ -150,6 +159,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, int dest; int (*rcv)(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); + void (*sta_handler)(struct sk_buff *skb); + void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb); if (!net_eq(dev_net(dev), &init_net)) goto drop; @@ -182,7 +193,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, */ rcv = rcu_dereference(sap->rcv_func); dest = llc_pdu_type(skb); - if (unlikely(!dest || !llc_type_handlers[dest - 1])) { + sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL; + if (unlikely(!sap_handler)) { if (rcv) rcv(skb, dev, pt, orig_dev); else @@ -193,7 +205,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, if (cskb) rcv(cskb, dev, pt, orig_dev); } - llc_type_handlers[dest - 1](sap, skb); + sap_handler(sap, skb); } llc_sap_put(sap); out: @@ -202,9 +214,10 @@ drop: kfree_skb(skb); goto out; handle_station: - if (!llc_station_handler) + sta_handler = ACCESS_ONCE(llc_station_handler); + if (!sta_handler) goto drop; - llc_station_handler(skb); + sta_handler(skb); goto out; } diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index a1839c00435..7b4799cfbf8 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c @@ -151,7 +151,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk) - llc->copied_seq, sk->sk_state, - sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, + from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), llc->link); out: return 0; diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 6828e39ec2e..204a8351eff 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c @@ -25,253 +25,26 @@ #include <net/llc_s_st.h> #include <net/llc_pdu.h> -/** - * struct llc_station - LLC station component - * - * SAP and connection resource manager, one per adapter. - * - * @state: state of station - * @xid_r_count: XID response PDU counter - * @mac_sa: MAC source address - * @sap_list: list of related SAPs - * @ev_q: events entering state mach. - * @mac_pdu_q: PDUs ready to send to MAC - */ -struct llc_station { - u8 state; - u8 xid_r_count; - struct timer_list ack_timer; - u8 retry_count; - u8 maximum_retry; - struct { - struct sk_buff_head list; - spinlock_t lock; - } ev_q; - struct sk_buff_head mac_pdu_q; -}; - -#define LLC_STATION_ACK_TIME (3 * HZ) - -int sysctl_llc_station_ack_timeout = LLC_STATION_ACK_TIME; - -/* Types of events (possible values in 'ev->type') */ -#define LLC_STATION_EV_TYPE_SIMPLE 1 -#define LLC_STATION_EV_TYPE_CONDITION 2 -#define LLC_STATION_EV_TYPE_PRIM 3 -#define LLC_STATION_EV_TYPE_PDU 4 /* command/response PDU */ -#define LLC_STATION_EV_TYPE_ACK_TMR 5 -#define LLC_STATION_EV_TYPE_RPT_STATUS 6 - -/* Events */ -#define LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK 1 -#define LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK 2 -#define LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY 3 -#define LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY 4 -#define LLC_STATION_EV_RX_NULL_DSAP_XID_C 5 -#define LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ 6 -#define LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ 7 -#define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8 -#define LLC_STATION_EV_DISABLE_REQ 9 - -struct llc_station_state_ev { - u8 type; - u8 prim; - u8 prim_type; - u8 reason; - struct list_head node; /* node in station->ev_q.list */ -}; - -static __inline__ struct llc_station_state_ev * - llc_station_ev(struct sk_buff *skb) -{ - return (struct llc_station_state_ev *)skb->cb; -} - -typedef int (*llc_station_ev_t)(struct sk_buff *skb); - -#define LLC_STATION_STATE_DOWN 1 /* initial state */ -#define LLC_STATION_STATE_DUP_ADDR_CHK 2 -#define LLC_STATION_STATE_UP 3 - -#define LLC_NBR_STATION_STATES 3 /* size of state table */ - -typedef int (*llc_station_action_t)(struct sk_buff *skb); - -/* Station component state table structure */ -struct llc_station_state_trans { - llc_station_ev_t ev; - u8 next_state; - llc_station_action_t *ev_actions; -}; - -struct llc_station_state { - u8 curr_state; - struct llc_station_state_trans **transitions; -}; - -static struct llc_station llc_main_station; - -static int llc_stat_ev_enable_with_dup_addr_check(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - - return ev->type == LLC_STATION_EV_TYPE_SIMPLE && - ev->prim_type == - LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1; -} - -static int llc_stat_ev_enable_without_dup_addr_check(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - - return ev->type == LLC_STATION_EV_TYPE_SIMPLE && - ev->prim_type == - LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1; -} - -static int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - - return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && - llc_main_station.retry_count < - llc_main_station.maximum_retry ? 0 : 1; -} - -static int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - - return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && - llc_main_station.retry_count == - llc_main_station.maximum_retry ? 0 : 1; -} - static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb) { - struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); - return ev->type == LLC_STATION_EV_TYPE_PDU && - LLC_PDU_IS_CMD(pdu) && /* command PDU */ + return LLC_PDU_IS_CMD(pdu) && /* command PDU */ LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID && !pdu->dsap ? 0 : 1; /* NULL DSAP value */ } -static int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); - - return ev->type == LLC_STATION_EV_TYPE_PDU && - LLC_PDU_IS_RSP(pdu) && /* response PDU */ - LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ - LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID && - !pdu->dsap && /* NULL DSAP value */ - !llc_main_station.xid_r_count ? 0 : 1; -} - -static int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); - - return ev->type == LLC_STATION_EV_TYPE_PDU && - LLC_PDU_IS_RSP(pdu) && /* response PDU */ - LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ - LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID && - !pdu->dsap && /* NULL DSAP value */ - llc_main_station.xid_r_count == 1 ? 0 : 1; -} - static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb) { - struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb); - return ev->type == LLC_STATION_EV_TYPE_PDU && - LLC_PDU_IS_CMD(pdu) && /* command PDU */ + return LLC_PDU_IS_CMD(pdu) && /* command PDU */ LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST && !pdu->dsap ? 0 : 1; /* NULL DSAP */ } -static int llc_stat_ev_disable_req(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - - return ev->type == LLC_STATION_EV_TYPE_PRIM && - ev->prim == LLC_DISABLE_PRIM && - ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1; -} - -/** - * llc_station_send_pdu - queues PDU to send - * @skb: Address of the PDU - * - * Queues a PDU to send to the MAC layer. - */ -static void llc_station_send_pdu(struct sk_buff *skb) -{ - skb_queue_tail(&llc_main_station.mac_pdu_q, skb); - while ((skb = skb_dequeue(&llc_main_station.mac_pdu_q)) != NULL) - if (dev_queue_xmit(skb)) - break; -} - -static int llc_station_ac_start_ack_timer(struct sk_buff *skb) -{ - mod_timer(&llc_main_station.ack_timer, - jiffies + sysctl_llc_station_ack_timeout); - return 0; -} - -static int llc_station_ac_set_retry_cnt_0(struct sk_buff *skb) -{ - llc_main_station.retry_count = 0; - return 0; -} - -static int llc_station_ac_inc_retry_cnt_by_1(struct sk_buff *skb) -{ - llc_main_station.retry_count++; - return 0; -} - -static int llc_station_ac_set_xid_r_cnt_0(struct sk_buff *skb) -{ - llc_main_station.xid_r_count = 0; - return 0; -} - -static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb) -{ - llc_main_station.xid_r_count++; - return 0; -} - -static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) -{ - int rc = 1; - struct sk_buff *nskb = llc_alloc_frame(NULL, skb->dev, LLC_PDU_TYPE_U, - sizeof(struct llc_xid_info)); - - if (!nskb) - goto out; - llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); - llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127); - rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, skb->dev->dev_addr); - if (unlikely(rc)) - goto free; - llc_station_send_pdu(nskb); -out: - return rc; -free: - kfree_skb(nskb); - goto out; -} - static int llc_station_ac_send_xid_r(struct sk_buff *skb) { u8 mac_da[ETH_ALEN], dsap; @@ -289,7 +62,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da); if (unlikely(rc)) goto free; - llc_station_send_pdu(nskb); + dev_queue_xmit(nskb); out: return rc; free: @@ -318,7 +91,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) rc = llc_mac_hdr_init(nskb, skb->dev->dev_addr, mac_da); if (unlikely(rc)) goto free; - llc_station_send_pdu(nskb); + dev_queue_xmit(nskb); out: return rc; free: @@ -326,352 +99,6 @@ free: goto out; } -static int llc_station_ac_report_status(struct sk_buff *skb) -{ - return 0; -} - -/* COMMON STATION STATE transitions */ - -/* dummy last-transition indicator; common to all state transition groups - * last entry for this state - * all members are zeros, .bss zeroes it - */ -static struct llc_station_state_trans llc_stat_state_trans_end; - -/* DOWN STATE transitions */ - -/* state transition for LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */ -static llc_station_action_t llc_stat_down_state_actions_1[] = { - [0] = llc_station_ac_start_ack_timer, - [1] = llc_station_ac_set_retry_cnt_0, - [2] = llc_station_ac_set_xid_r_cnt_0, - [3] = llc_station_ac_send_null_dsap_xid_c, - [4] = NULL, -}; - -static struct llc_station_state_trans llc_stat_down_state_trans_1 = { - .ev = llc_stat_ev_enable_with_dup_addr_check, - .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, - .ev_actions = llc_stat_down_state_actions_1, -}; - -/* state transition for LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK event */ -static llc_station_action_t llc_stat_down_state_actions_2[] = { - [0] = llc_station_ac_report_status, /* STATION UP */ - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_down_state_trans_2 = { - .ev = llc_stat_ev_enable_without_dup_addr_check, - .next_state = LLC_STATION_STATE_UP, - .ev_actions = llc_stat_down_state_actions_2, -}; - -/* array of pointers; one to each transition */ -static struct llc_station_state_trans *llc_stat_dwn_state_trans[] = { - [0] = &llc_stat_down_state_trans_1, - [1] = &llc_stat_down_state_trans_2, - [2] = &llc_stat_state_trans_end, -}; - -/* UP STATE transitions */ -/* state transition for LLC_STATION_EV_DISABLE_REQ event */ -static llc_station_action_t llc_stat_up_state_actions_1[] = { - [0] = llc_station_ac_report_status, /* STATION DOWN */ - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_up_state_trans_1 = { - .ev = llc_stat_ev_disable_req, - .next_state = LLC_STATION_STATE_DOWN, - .ev_actions = llc_stat_up_state_actions_1, -}; - -/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ -static llc_station_action_t llc_stat_up_state_actions_2[] = { - [0] = llc_station_ac_send_xid_r, - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_up_state_trans_2 = { - .ev = llc_stat_ev_rx_null_dsap_xid_c, - .next_state = LLC_STATION_STATE_UP, - .ev_actions = llc_stat_up_state_actions_2, -}; - -/* state transition for LLC_STATION_EV_RX_NULL_DSAP_TEST_C event */ -static llc_station_action_t llc_stat_up_state_actions_3[] = { - [0] = llc_station_ac_send_test_r, - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_up_state_trans_3 = { - .ev = llc_stat_ev_rx_null_dsap_test_c, - .next_state = LLC_STATION_STATE_UP, - .ev_actions = llc_stat_up_state_actions_3, -}; - -/* array of pointers; one to each transition */ -static struct llc_station_state_trans *llc_stat_up_state_trans [] = { - [0] = &llc_stat_up_state_trans_1, - [1] = &llc_stat_up_state_trans_2, - [2] = &llc_stat_up_state_trans_3, - [3] = &llc_stat_state_trans_end, -}; - -/* DUP ADDR CHK STATE transitions */ -/* state transition for LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ - * event - */ -static llc_station_action_t llc_stat_dupaddr_state_actions_1[] = { - [0] = llc_station_ac_inc_xid_r_cnt_by_1, - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_dupaddr_state_trans_1 = { - .ev = llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq, - .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, - .ev_actions = llc_stat_dupaddr_state_actions_1, -}; - -/* state transition for LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ - * event - */ -static llc_station_action_t llc_stat_dupaddr_state_actions_2[] = { - [0] = llc_station_ac_report_status, /* DUPLICATE ADDRESS FOUND */ - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_dupaddr_state_trans_2 = { - .ev = llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq, - .next_state = LLC_STATION_STATE_DOWN, - .ev_actions = llc_stat_dupaddr_state_actions_2, -}; - -/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */ -static llc_station_action_t llc_stat_dupaddr_state_actions_3[] = { - [0] = llc_station_ac_send_xid_r, - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_dupaddr_state_trans_3 = { - .ev = llc_stat_ev_rx_null_dsap_xid_c, - .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, - .ev_actions = llc_stat_dupaddr_state_actions_3, -}; - -/* state transition for LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY - * event - */ -static llc_station_action_t llc_stat_dupaddr_state_actions_4[] = { - [0] = llc_station_ac_start_ack_timer, - [1] = llc_station_ac_inc_retry_cnt_by_1, - [2] = llc_station_ac_set_xid_r_cnt_0, - [3] = llc_station_ac_send_null_dsap_xid_c, - [4] = NULL, -}; - -static struct llc_station_state_trans llc_stat_dupaddr_state_trans_4 = { - .ev = llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry, - .next_state = LLC_STATION_STATE_DUP_ADDR_CHK, - .ev_actions = llc_stat_dupaddr_state_actions_4, -}; - -/* state transition for LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY - * event - */ -static llc_station_action_t llc_stat_dupaddr_state_actions_5[] = { - [0] = llc_station_ac_report_status, /* STATION UP */ - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_dupaddr_state_trans_5 = { - .ev = llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry, - .next_state = LLC_STATION_STATE_UP, - .ev_actions = llc_stat_dupaddr_state_actions_5, -}; - -/* state transition for LLC_STATION_EV_DISABLE_REQ event */ -static llc_station_action_t llc_stat_dupaddr_state_actions_6[] = { - [0] = llc_station_ac_report_status, /* STATION DOWN */ - [1] = NULL, -}; - -static struct llc_station_state_trans llc_stat_dupaddr_state_trans_6 = { - .ev = llc_stat_ev_disable_req, - .next_state = LLC_STATION_STATE_DOWN, - .ev_actions = llc_stat_dupaddr_state_actions_6, -}; - -/* array of pointers; one to each transition */ -static struct llc_station_state_trans *llc_stat_dupaddr_state_trans[] = { - [0] = &llc_stat_dupaddr_state_trans_6, /* Request */ - [1] = &llc_stat_dupaddr_state_trans_4, /* Timer */ - [2] = &llc_stat_dupaddr_state_trans_5, - [3] = &llc_stat_dupaddr_state_trans_1, /* Receive frame */ - [4] = &llc_stat_dupaddr_state_trans_2, - [5] = &llc_stat_dupaddr_state_trans_3, - [6] = &llc_stat_state_trans_end, -}; - -static struct llc_station_state - llc_station_state_table[LLC_NBR_STATION_STATES] = { - [LLC_STATION_STATE_DOWN - 1] = { - .curr_state = LLC_STATION_STATE_DOWN, - .transitions = llc_stat_dwn_state_trans, - }, - [LLC_STATION_STATE_DUP_ADDR_CHK - 1] = { - .curr_state = LLC_STATION_STATE_DUP_ADDR_CHK, - .transitions = llc_stat_dupaddr_state_trans, - }, - [LLC_STATION_STATE_UP - 1] = { - .curr_state = LLC_STATION_STATE_UP, - .transitions = llc_stat_up_state_trans, - }, -}; - -/** - * llc_exec_station_trans_actions - executes actions for transition - * @trans: Address of the transition - * @skb: Address of the event that caused the transition - * - * Executes actions of a transition of the station state machine. Returns - * 0 if all actions complete successfully, nonzero otherwise. - */ -static u16 llc_exec_station_trans_actions(struct llc_station_state_trans *trans, - struct sk_buff *skb) -{ - u16 rc = 0; - llc_station_action_t *next_action = trans->ev_actions; - - for (; next_action && *next_action; next_action++) - if ((*next_action)(skb)) - rc = 1; - return rc; -} - -/** - * llc_find_station_trans - finds transition for this event - * @skb: Address of the event - * - * Search thru events of the current state of the station until list - * exhausted or it's obvious that the event is not valid for the current - * state. Returns the address of the transition if cound, %NULL otherwise. - */ -static struct llc_station_state_trans * - llc_find_station_trans(struct sk_buff *skb) -{ - int i = 0; - struct llc_station_state_trans *rc = NULL; - struct llc_station_state_trans **next_trans; - struct llc_station_state *curr_state = - &llc_station_state_table[llc_main_station.state - 1]; - - for (next_trans = curr_state->transitions; next_trans[i]->ev; i++) - if (!next_trans[i]->ev(skb)) { - rc = next_trans[i]; - break; - } - return rc; -} - -/** - * llc_station_free_ev - frees an event - * @skb: Address of the event - * - * Frees an event. - */ -static void llc_station_free_ev(struct sk_buff *skb) -{ - struct llc_station_state_ev *ev = llc_station_ev(skb); - - if (ev->type == LLC_STATION_EV_TYPE_PDU) - kfree_skb(skb); -} - -/** - * llc_station_next_state - processes event and goes to the next state - * @skb: Address of the event - * - * Processes an event, executes any transitions related to that event and - * updates the state of the station. - */ -static u16 llc_station_next_state(struct sk_buff *skb) -{ - u16 rc = 1; - struct llc_station_state_trans *trans; - - if (llc_main_station.state > LLC_NBR_STATION_STATES) - goto out; - trans = llc_find_station_trans(skb); - if (trans) { - /* got the state to which we next transition; perform the - * actions associated with this transition before actually - * transitioning to the next state - */ - rc = llc_exec_station_trans_actions(trans, skb); - if (!rc) - /* transition station to next state if all actions - * execute successfully; done; wait for next event - */ - llc_main_station.state = trans->next_state; - } else - /* event not recognized in current state; re-queue it for - * processing again at a later time; return failure - */ - rc = 0; -out: - llc_station_free_ev(skb); - return rc; -} - -/** - * llc_station_service_events - service events in the queue - * - * Get an event from the station event queue (if any); attempt to service - * the event; if event serviced, get the next event (if any) on the event - * queue; if event not service, re-queue the event on the event queue and - * attempt to service the next event; when serviced all events in queue, - * finished; if don't transition to different state, just service all - * events once; if transition to new state, service all events again. - * Caller must hold llc_main_station.ev_q.lock. - */ -static void llc_station_service_events(void) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&llc_main_station.ev_q.list)) != NULL) - llc_station_next_state(skb); -} - -/** - * llc_station_state_process - queue event and try to process queue. - * @skb: Address of the event - * - * Queues an event (on the station event queue) for handling by the - * station state machine and attempts to process any queued-up events. - */ -static void llc_station_state_process(struct sk_buff *skb) -{ - spin_lock_bh(&llc_main_station.ev_q.lock); - skb_queue_tail(&llc_main_station.ev_q.list, skb); - llc_station_service_events(); - spin_unlock_bh(&llc_main_station.ev_q.lock); -} - -static void llc_station_ack_tmr_cb(unsigned long timeout_data) -{ - struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC); - - if (skb) { - struct llc_station_state_ev *ev = llc_station_ev(skb); - - ev->type = LLC_STATION_EV_TYPE_ACK_TMR; - llc_station_state_process(skb); - } -} - /** * llc_station_rcv - send received pdu to the station state machine * @skb: received frame. @@ -680,43 +107,19 @@ static void llc_station_ack_tmr_cb(unsigned long timeout_data) */ static void llc_station_rcv(struct sk_buff *skb) { - struct llc_station_state_ev *ev = llc_station_ev(skb); - - ev->type = LLC_STATION_EV_TYPE_PDU; - ev->reason = 0; - llc_station_state_process(skb); + if (llc_stat_ev_rx_null_dsap_xid_c(skb)) + llc_station_ac_send_xid_r(skb); + else if (llc_stat_ev_rx_null_dsap_test_c(skb)) + llc_station_ac_send_test_r(skb); + kfree_skb(skb); } -int __init llc_station_init(void) +void __init llc_station_init(void) { - int rc = -ENOBUFS; - struct sk_buff *skb; - struct llc_station_state_ev *ev; - - skb_queue_head_init(&llc_main_station.mac_pdu_q); - skb_queue_head_init(&llc_main_station.ev_q.list); - spin_lock_init(&llc_main_station.ev_q.lock); - setup_timer(&llc_main_station.ack_timer, llc_station_ack_tmr_cb, - (unsigned long)&llc_main_station); - llc_main_station.ack_timer.expires = jiffies + - sysctl_llc_station_ack_timeout; - skb = alloc_skb(0, GFP_ATOMIC); - if (!skb) - goto out; - rc = 0; llc_set_station_handler(llc_station_rcv); - ev = llc_station_ev(skb); - memset(ev, 0, sizeof(*ev)); - llc_main_station.maximum_retry = 1; - llc_main_station.state = LLC_STATION_STATE_DOWN; - ev->type = LLC_STATION_EV_TYPE_SIMPLE; - ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; - rc = llc_station_next_state(skb); -out: - return rc; } -void __exit llc_station_exit(void) +void llc_station_exit(void) { llc_set_station_handler(NULL); } diff --git a/net/llc/sysctl_net_llc.c b/net/llc/sysctl_net_llc.c index d75306b9c2f..612a5ddaf93 100644 --- a/net/llc/sysctl_net_llc.c +++ b/net/llc/sysctl_net_llc.c @@ -47,13 +47,6 @@ static struct ctl_table llc2_timeout_table[] = { }; static struct ctl_table llc_station_table[] = { - { - .procname = "ack_timeout", - .data = &sysctl_llc_station_ack_timeout, - .maxlen = sizeof(long), - .mode = 0644, - .proc_handler = proc_dointvec_jiffies, - }, { }, }; |