⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 llc_station.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	.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. * *	Sends data unit to station state machine. */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);}int __init llc_station_init(void){	u16 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);	init_timer(&llc_main_station.ack_timer);	llc_main_station.ack_timer.data     = (unsigned long)&llc_main_station;	llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;	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){	llc_set_station_handler(NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -