LLC: use skb->cb to store the LLC events

. this allows us to kill the shorlived kmalloc/kfree for events in the fast path.
. because of this there is no need for the skb member in the event structs
. use more labeled elements in the transition tables
. simplify llc_sock proc routine
. more kernedoc style comments
. 
. remove unused defines in llc_main.h

. create llc_set_backlog_type and llc_backlog_type
. 
parent b4878edb
...@@ -24,25 +24,25 @@ ...@@ -24,25 +24,25 @@
/* All station state event action functions look like this */ /* All station state event action functions look like this */
typedef int (*llc_station_action_t)(struct llc_station *station, typedef int (*llc_station_action_t)(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_start_ack_timer(struct llc_station *station, extern int llc_station_ac_start_ack_timer(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_set_retry_cnt_0(struct llc_station *station, extern int llc_station_ac_set_retry_cnt_0(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station, extern int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station, extern int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station, extern int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station, extern int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_send_xid_r(struct llc_station *station, extern int llc_station_ac_send_xid_r(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_send_test_r(struct llc_station *station, extern int llc_station_ac_send_test_r(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_report_status(struct llc_station *station, extern int llc_station_ac_report_status(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_station_ac_report_status(struct llc_station *station, extern int llc_station_ac_report_status(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
#endif /* LLC_ACTN_H */ #endif /* LLC_ACTN_H */
This diff is collapsed.
This diff is collapsed.
...@@ -136,12 +136,10 @@ extern void llc_sock_reset(struct sock *sk); ...@@ -136,12 +136,10 @@ extern void llc_sock_reset(struct sock *sk);
extern int llc_sock_init(struct sock *sk); extern int llc_sock_init(struct sock *sk);
/* Access to a connection */ /* Access to a connection */
extern struct llc_conn_state_ev *llc_conn_alloc_ev(struct sock *sk); extern int llc_conn_send_ev(struct sock *sk, struct sk_buff *skb);
extern int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev);
extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb, extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
struct llc_conn_state_ev *ev); extern void llc_conn_free_ev(struct sk_buff *skb);
extern void llc_conn_free_ev(struct llc_conn_state_ev *ev);
extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr,
u8 first_p_bit); u8 first_p_bit);
extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr,
......
...@@ -58,7 +58,7 @@ union llc_stat_ev_if { ...@@ -58,7 +58,7 @@ union llc_stat_ev_if {
struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */ struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_stat_ev_prim_if prim; struct llc_stat_ev_prim_if prim;
struct llc_stat_ev_pdu_if pdu; struct llc_stat_ev_pdu_if pdu;
struct llc_stat_ev_tmr_if tmr; struct llc_stat_ev_tmr_if tmr;
struct llc_stat_ev_rpt_sts_if rsts; /* report status */ struct llc_stat_ev_rpt_sts_if rsts; /* report status */
}; };
...@@ -68,26 +68,32 @@ struct llc_station_state_ev { ...@@ -68,26 +68,32 @@ struct llc_station_state_ev {
struct list_head node; /* node in station->ev_q.list */ 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 llc_station *station, typedef int (*llc_station_ev_t)(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station, extern int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station, extern int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station * extern int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *
station, station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station, extern int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, extern int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, extern int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, extern int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, extern int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern int llc_stat_ev_disable_req(struct llc_station *station, extern int llc_stat_ev_disable_req(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
#endif /* LLC_EVNT_H */ #endif /* LLC_EVNT_H */
...@@ -20,4 +20,15 @@ extern struct net_device *mac_dev_peer(struct net_device *current_dev, ...@@ -20,4 +20,15 @@ extern struct net_device *mac_dev_peer(struct net_device *current_dev,
extern int llc_pdu_router(struct llc_sap *sap, struct sock *sk, extern int llc_pdu_router(struct llc_sap *sap, struct sock *sk,
struct sk_buff *skb, u8 type); struct sk_buff *skb, u8 type);
extern u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da); extern u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da);
static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type)
{
skb->cb[sizeof(skb->cb) - 1] = type;
}
static __inline__ char llc_backlog_type(struct sk_buff *skb)
{
return skb->cb[sizeof(skb->cb) - 1];
}
#endif /* LLC_MAC_H */ #endif /* LLC_MAC_H */
...@@ -19,35 +19,40 @@ ...@@ -19,35 +19,40 @@
#define LLC_ACK_TIME 3 #define LLC_ACK_TIME 3
#define LLC_REJ_TIME 3 #define LLC_REJ_TIME 3
#define LLC_BUSY_TIME 3 #define LLC_BUSY_TIME 3
#define LLC_SENDACK_TIME 50
#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ #define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */
#define LLC_DEST_SAP 1 /* Type 1 goes here */ #define LLC_DEST_SAP 1 /* Type 1 goes here */
#define LLC_DEST_CONN 2 /* Type 2 goes here */ #define LLC_DEST_CONN 2 /* Type 2 goes here */
/* LLC Layer global default parameters */ /**
* struct llc_station - LLC station component
#define LLC_GLOBAL_DEFAULT_MAX_NBR_SAPS 4 *
#define LLC_GLOBAL_DEFAULT_MAX_NBR_CONNS 64 * SAP and connection resource manager, one per adapter.
*
/* LLC station component (SAP and connection resource manager) */ * @state - state of station
/* Station component; one per adapter */ * @xid_r_count - XID response PDU counter
* @ack_tmr_running - 1 or 0
* @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 { struct llc_station {
u8 state; /* state of station */ u8 state;
u8 xid_r_count; /* XID response PDU counter */ u8 xid_r_count;
struct timer_list ack_timer; struct timer_list ack_timer;
u8 ack_tmr_running; /* 1 or 0 */ u8 ack_tmr_running;
u8 retry_count; u8 retry_count;
u8 maximum_retry; u8 maximum_retry;
u8 mac_sa[6]; /* MAC source address */ u8 mac_sa[6];
struct { struct {
spinlock_t lock; spinlock_t lock;
struct list_head list; struct list_head list;
} sap_list; /* list of related SAPs */ } sap_list;
struct { struct {
spinlock_t lock; struct sk_buff_head list;
struct list_head list; spinlock_t lock;
} ev_q; /* events entering state mach. */ } ev_q;
struct sk_buff_head mac_pdu_q; /* PDUs ready to send to MAC */ struct sk_buff_head mac_pdu_q;
}; };
struct llc_station_state_ev; struct llc_station_state_ev;
...@@ -56,10 +61,8 @@ extern void llc_sap_save(struct llc_sap *sap); ...@@ -56,10 +61,8 @@ extern void llc_sap_save(struct llc_sap *sap);
extern void llc_free_sap(struct llc_sap *sap); extern void llc_free_sap(struct llc_sap *sap);
extern struct llc_sap *llc_sap_find(u8 lsap); extern struct llc_sap *llc_sap_find(u8 lsap);
extern struct llc_station *llc_station_get(void); extern struct llc_station *llc_station_get(void);
extern struct llc_station_state_ev *
llc_station_alloc_ev(struct llc_station *station);
extern void llc_station_send_ev(struct llc_station *station, extern void llc_station_send_ev(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
extern void llc_station_send_pdu(struct llc_station *station, extern void llc_station_send_pdu(struct llc_station *station,
struct sk_buff *skb); struct sk_buff *skb);
extern struct sk_buff *llc_alloc_frame(void); extern struct sk_buff *llc_alloc_frame(void);
......
...@@ -23,25 +23,17 @@ ...@@ -23,25 +23,17 @@
#define SAP_ACT_TEST_IND 9 #define SAP_ACT_TEST_IND 9
/* All action functions must look like this */ /* All action functions must look like this */
typedef int (*llc_sap_action_t)(struct llc_sap *sap, typedef int (*llc_sap_action_t)(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev);
extern int llc_sap_action_unitdata_ind(struct llc_sap *sap, extern int llc_sap_action_unitdata_ind(struct llc_sap *sap,
struct llc_sap_state_ev *ev); struct sk_buff *skb);
extern int llc_sap_action_send_ui(struct llc_sap *sap, extern int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_send_xid_c(struct llc_sap *sap, extern int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_send_xid_r(struct llc_sap *sap, extern int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev);
extern int llc_sap_action_send_test_c(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_send_test_r(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_report_status(struct llc_sap *sap, extern int llc_sap_action_report_status(struct llc_sap *sap,
struct llc_sap_state_ev *ev); struct sk_buff *skb);
extern int llc_sap_action_xid_ind(struct llc_sap *sap, extern int llc_sap_action_xid_ind(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_test_ind(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
#endif /* LLC_S_AC_H */ #endif /* LLC_S_AC_H */
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
* *
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#include <linux/skbuff.h>
/* Defines SAP component events */ /* Defines SAP component events */
/* Types of events (possible values in 'ev->type') */ /* Types of events (possible values in 'ev->type') */
#define LLC_SAP_EV_TYPE_SIMPLE 1 #define LLC_SAP_EV_TYPE_SIMPLE 1
...@@ -45,9 +48,8 @@ struct llc_sap_ev_prim_if { ...@@ -45,9 +48,8 @@ struct llc_sap_ev_prim_if {
}; };
struct llc_sap_ev_pdu_if { struct llc_sap_ev_pdu_if {
u8 ev; u8 ev;
u8 reason; u8 reason;
struct sk_buff *skb;
}; };
struct llc_sap_ev_tmr_if { struct llc_sap_ev_tmr_if {
...@@ -75,27 +77,24 @@ struct llc_sap_state_ev { ...@@ -75,27 +77,24 @@ struct llc_sap_state_ev {
union llc_sap_ev_if data; union llc_sap_ev_if data;
}; };
static __inline__ struct llc_sap_state_ev *llc_sap_ev(struct sk_buff *skb)
{
return (struct llc_sap_state_ev *)skb->cb;
}
struct llc_sap; struct llc_sap;
typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct llc_sap_state_ev *ev); typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_activation_req(struct llc_sap *sap, extern int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev); extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, extern int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_xid_req(struct llc_sap *sap, extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, extern int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev); extern int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_ev_test_req(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_ev_rx_test_c(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_ev_rx_test_r(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_ev_deactivation_req(struct llc_sap *sap, extern int llc_sap_ev_deactivation_req(struct llc_sap *sap,
struct llc_sap_state_ev *ev); struct sk_buff *skb);
#endif /* LLC_S_EV_H */ #endif /* LLC_S_EV_H */
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
#define LLC_SAP_STATE_INACTIVE 1 #define LLC_SAP_STATE_INACTIVE 1
#define LLC_SAP_STATE_ACTIVE 2 #define LLC_SAP_STATE_ACTIVE 2
#define LLC_NBR_SAP_STATES 2 /* size of state table */ #define LLC_NR_SAP_STATES 2 /* size of state table */
/* structures and types */ /* structures and types */
/* SAP state table structure */ /* SAP state table structure */
struct llc_sap_state_trans { struct llc_sap_state_trans {
...@@ -25,10 +26,10 @@ struct llc_sap_state_trans { ...@@ -25,10 +26,10 @@ struct llc_sap_state_trans {
}; };
struct llc_sap_state { struct llc_sap_state {
u8 curr_state; u8 curr_state;
struct llc_sap_state_trans **transitions; struct llc_sap_state_trans **transitions;
}; };
/* only access to SAP state table */ /* only access to SAP state table */
extern struct llc_sap_state llc_sap_state_table[LLC_NBR_SAP_STATES]; extern struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES];
#endif /* LLC_S_ST_H */ #endif /* LLC_S_ST_H */
...@@ -49,9 +49,7 @@ struct llc_sap_state_ev; ...@@ -49,9 +49,7 @@ struct llc_sap_state_ev;
extern void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk); extern void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk);
extern void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk); extern void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk);
extern void llc_sap_send_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev); extern void llc_sap_send_ev(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb, extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
struct llc_sap_state_ev *ev);
extern void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb);
extern struct llc_sap_state_ev *llc_sap_alloc_ev(struct llc_sap *sap);
#endif /* LLC_SAP_H */ #endif /* LLC_SAP_H */
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
static void llc_station_ack_tmr_callback(unsigned long timeout_data); static void llc_station_ack_tmr_callback(unsigned long timeout_data);
int llc_station_ac_start_ack_timer(struct llc_station *station, int llc_station_ac_start_ack_timer(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
del_timer(&station->ack_timer); del_timer(&station->ack_timer);
station->ack_timer.expires = jiffies + LLC_ACK_TIME * HZ; station->ack_timer.expires = jiffies + LLC_ACK_TIME * HZ;
...@@ -39,98 +39,94 @@ int llc_station_ac_start_ack_timer(struct llc_station *station, ...@@ -39,98 +39,94 @@ int llc_station_ac_start_ack_timer(struct llc_station *station,
} }
int llc_station_ac_set_retry_cnt_0(struct llc_station *station, int llc_station_ac_set_retry_cnt_0(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
station->retry_count = 0; station->retry_count = 0;
return 0; return 0;
} }
int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station, int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
station->retry_count++; station->retry_count++;
return 0; return 0;
} }
int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station, int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
station->xid_r_count = 0; station->xid_r_count = 0;
return 0; return 0;
} }
int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station, int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
station->xid_r_count++; station->xid_r_count++;
return 0; return 0;
} }
int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station, int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
int rc = 1; int rc = 1;
struct sk_buff *skb = llc_alloc_frame(); struct sk_buff *nskb = llc_alloc_frame();
if (!skb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 127); llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
lan_hdrs_init(skb, station->mac_sa, station->mac_sa); lan_hdrs_init(nskb, station->mac_sa, station->mac_sa);
llc_station_send_pdu(station, skb); llc_station_send_pdu(station, nskb);
out: out:
return rc; return rc;
} }
int llc_station_ac_send_xid_r(struct llc_station *station, int llc_station_ac_send_xid_r(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
u8 mac_da[ETH_ALEN], dsap; u8 mac_da[ETH_ALEN], dsap;
int rc = 1; int rc = 1;
struct sk_buff *ev_skb; struct sk_buff* nskb = llc_alloc_frame();
struct sk_buff* skb = llc_alloc_frame();
if (!skb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
ev_skb = ev->data.pdu.skb; nskb->dev = skb->dev;
skb->dev = ev_skb->dev; llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_sa(ev_skb, mac_da); llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_decode_ssap(ev_skb, &dsap); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
llc_pdu_init_as_xid_rsp(skb, LLC_XID_NULL_CLASS_2, 127); lan_hdrs_init(nskb, station->mac_sa, mac_da);
lan_hdrs_init(skb, station->mac_sa, mac_da); llc_station_send_pdu(station, nskb);
llc_station_send_pdu(station, skb);
out: out:
return rc; return rc;
} }
int llc_station_ac_send_test_r(struct llc_station *station, int llc_station_ac_send_test_r(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
u8 mac_da[ETH_ALEN], dsap; u8 mac_da[ETH_ALEN], dsap;
int rc = 1; int rc = 1;
struct sk_buff *ev_skb; struct sk_buff *nskb = llc_alloc_frame();
struct sk_buff *skb = llc_alloc_frame();
if (!skb) if (!nskb)
goto out; goto out;
rc = 0; rc = 0;
ev_skb = ev->data.pdu.skb; nskb->dev = skb->dev;
skb->dev = ev_skb->dev; llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_sa(ev_skb, mac_da); llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_decode_ssap(ev_skb, &dsap); llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP); llc_pdu_init_as_test_rsp(nskb, skb);
llc_pdu_init_as_test_rsp(skb, ev_skb); lan_hdrs_init(nskb, station->mac_sa, mac_da);
lan_hdrs_init(skb, station->mac_sa, mac_da); llc_station_send_pdu(station, nskb);
llc_station_send_pdu(station, skb);
out: out:
return rc; return rc;
} }
int llc_station_ac_report_status(struct llc_station *station, int llc_station_ac_report_status(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
return 0; return 0;
} }
...@@ -138,13 +134,14 @@ int llc_station_ac_report_status(struct llc_station *station, ...@@ -138,13 +134,14 @@ int llc_station_ac_report_status(struct llc_station *station,
static void llc_station_ack_tmr_callback(unsigned long timeout_data) static void llc_station_ack_tmr_callback(unsigned long timeout_data)
{ {
struct llc_station *station = (struct llc_station *)timeout_data; struct llc_station *station = (struct llc_station *)timeout_data;
struct llc_station_state_ev *ev; struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC);
station->ack_tmr_running = 0; station->ack_tmr_running = 0;
ev = llc_station_alloc_ev(station); if (skb) {
if (ev) { struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_ACK_TMR; ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
ev->data.tmr.timer_specific = NULL; ev->data.tmr.timer_specific = NULL;
llc_station_send_ev(station, ev); llc_station_send_ev(station, skb);
} }
} }
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -28,56 +28,37 @@ ...@@ -28,56 +28,37 @@
static int llc_find_offset(int state, int ev_type); static int llc_find_offset(int state, int ev_type);
static void llc_conn_send_pdus(struct sock *sk); static void llc_conn_send_pdus(struct sock *sk);
static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev); static int llc_conn_service(struct sock *sk, struct sk_buff *skb);
static int llc_exec_conn_trans_actions(struct sock *sk, static int llc_exec_conn_trans_actions(struct sock *sk,
struct llc_conn_state_trans *trans, struct llc_conn_state_trans *trans,
struct llc_conn_state_ev *ev); struct sk_buff *ev);
static struct llc_conn_state_trans * static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev); struct sk_buff *skb);
/* Offset table on connection states transition diagram */ /* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
/**
* llc_conn_alloc_event: allocates an event
* @sk: socket that event is associated
*
* Returns pointer to allocated connection on success, %NULL on failure.
*/
struct llc_conn_state_ev *llc_conn_alloc_ev(struct sock *sk)
{
struct llc_conn_state_ev *ev = NULL;
/* verify connection is valid, active and open */
if (llc_sk(sk)->state != LLC_CONN_OUT_OF_SVC) {
/* get event structure to build a station event */
ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
if (ev)
memset(ev, 0, sizeof(*ev));
}
return ev;
}
/** /**
* llc_conn_send_event - sends event to connection state machine * llc_conn_send_event - sends event to connection state machine
* @sk: connection * @sk: connection
* @ev: occurred event * @skb: occurred event
* *
* Sends an event to connection state machine. after processing event * Sends an event to connection state machine. after processing event
* (executing it's actions and changing state), upper layer will be * (executing it's actions and changing state), upper layer will be
* indicated or confirmed, if needed. Returns 0 for success, 1 for * indicated or confirmed, if needed. Returns 0 for success, 1 for
* failure. The socket lock has to be held before calling this function. * failure. The socket lock has to be held before calling this function.
*/ */
int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_send_ev(struct sock *sk, struct sk_buff *skb)
{ {
/* sending event to state machine */ /* sending event to state machine */
int rc = llc_conn_service(sk, ev); int rc = llc_conn_service(sk, skb);
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
u8 flag = ev->flag; u8 flag = ev->flag;
struct llc_prim_if_block *ind_prim = ev->ind_prim; struct llc_prim_if_block *ind_prim = ev->ind_prim;
struct llc_prim_if_block *cfm_prim = ev->cfm_prim; struct llc_prim_if_block *cfm_prim = ev->cfm_prim;
llc_conn_free_ev(ev); llc_conn_free_ev(skb);
#ifdef THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY #ifdef THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY
/* check if the connection was freed by the state machine by /* check if the connection was freed by the state machine by
* means of llc_conn_disc */ * means of llc_conn_disc */
...@@ -125,15 +106,14 @@ void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) ...@@ -125,15 +106,14 @@ void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
* llc_conn_rtn_pdu - sends received data pdu to upper layer * llc_conn_rtn_pdu - sends received data pdu to upper layer
* @sk: Active connection * @sk: Active connection
* @skb: Received data frame * @skb: Received data frame
* @ev: Occurred event
* *
* Sends received data pdu to upper layer (by using indicate function). * Sends received data pdu to upper layer (by using indicate function).
* Prepares service parameters (prim and prim_data). calling indication * Prepares service parameters (prim and prim_data). calling indication
* function will be done in llc_conn_send_ev. * function will be done in llc_conn_send_ev.
*/ */
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb, void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb)
struct llc_conn_state_ev *ev)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_ind_prim; struct llc_prim_if_block *prim = &sap->llc_ind_prim;
...@@ -291,34 +271,37 @@ static void llc_conn_send_pdus(struct sock *sk) ...@@ -291,34 +271,37 @@ static void llc_conn_send_pdus(struct sock *sk)
/** /**
* llc_conn_free_ev - free event * llc_conn_free_ev - free event
* @ev: event to free * @skb: event to free
* *
* Free allocated event. * Free allocated event.
*/ */
void llc_conn_free_ev(struct llc_conn_state_ev *ev) void llc_conn_free_ev(struct sk_buff *skb)
{ {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
if (ev->type == LLC_CONN_EV_TYPE_PDU) { if (ev->type == LLC_CONN_EV_TYPE_PDU) {
/* free the frame that binded to this event */ /* free the frame that is bound to this event */
struct llc_pdu_sn *pdu = struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
(struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim) if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim)
kfree_skb(ev->data.pdu.skb); kfree_skb(skb);
} } else if (ev->type == LLC_CONN_EV_TYPE_PRIM &&
/* free event structure to free list of the same */ ev->data.prim.prim != LLC_DATA_PRIM)
kfree(ev); kfree_skb(skb);
else if (ev->type == LLC_CONN_EV_TYPE_P_TMR)
kfree_skb(skb);
} }
/** /**
* llc_conn_service - finds transition and changes state of connection * llc_conn_service - finds transition and changes state of connection
* @sk: connection * @sk: connection
* @ev: happened event * @skb: happened event
* *
* This function finds transition that matches with happened event, then * This function finds transition that matches with happened event, then
* executes related actions and finally changes state of connection. * executes related actions and finally changes state of connection.
* Returns 0 for success, 1 for failure. * Returns 0 for success, 1 for failure.
*/ */
static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev) static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
{ {
int rc = 1; int rc = 1;
struct llc_conn_state_trans *trans; struct llc_conn_state_trans *trans;
...@@ -326,9 +309,9 @@ static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -326,9 +309,9 @@ static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev)
if (llc_sk(sk)->state > NBR_CONN_STATES) if (llc_sk(sk)->state > NBR_CONN_STATES)
goto out; goto out;
rc = 0; rc = 0;
trans = llc_qualify_conn_ev(sk, ev); trans = llc_qualify_conn_ev(sk, skb);
if (trans) { if (trans) {
rc = llc_exec_conn_trans_actions(sk, trans, ev); rc = llc_exec_conn_trans_actions(sk, trans, skb);
if (!rc && trans->next_state != NO_STATE_CHANGE) if (!rc && trans->next_state != NO_STATE_CHANGE)
llc_sk(sk)->state = trans->next_state; llc_sk(sk)->state = trans->next_state;
} }
...@@ -339,26 +322,28 @@ static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -339,26 +322,28 @@ static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev)
/** /**
* llc_qualify_conn_ev - finds transition for event * llc_qualify_conn_ev - finds transition for event
* @sk: connection * @sk: connection
* @ev: happened event * @skb: happened event
* *
* This function finds transition that matches with happened event. * This function finds transition that matches with happened event.
* Returns pointer to found transition on success, %NULL otherwise. * Returns pointer to found transition on success, %NULL otherwise.
*/ */
static struct llc_conn_state_trans * static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_conn_state_trans **next_trans; struct llc_conn_state_trans **next_trans;
llc_conn_ev_qfyr_t *next_qualifier; llc_conn_ev_qfyr_t *next_qualifier;
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state *curr_state = struct llc_conn_state *curr_state =
&llc_conn_state_table[llc_sk(sk)->state - 1]; &llc_conn_state_table[llc->state - 1];
/* search thru events for this state until /* search thru events for this state until
* list exhausted or until no more * list exhausted or until no more
*/ */
for (next_trans = curr_state->transitions + for (next_trans = curr_state->transitions +
llc_find_offset(llc_sk(sk)->state - 1, ev->type); llc_find_offset(llc->state - 1, ev->type);
(*next_trans)->ev; next_trans++) { (*next_trans)->ev; next_trans++) {
if (!((*next_trans)->ev)(sk, ev)) { if (!((*next_trans)->ev)(sk, skb)) {
/* got POSSIBLE event match; the event may require /* got POSSIBLE event match; the event may require
* qualification based on the values of a number of * qualification based on the values of a number of
* state flags; if all qualifications are met (i.e., * state flags; if all qualifications are met (i.e.,
...@@ -367,7 +352,7 @@ static struct llc_conn_state_trans * ...@@ -367,7 +352,7 @@ static struct llc_conn_state_trans *
*/ */
for (next_qualifier = (*next_trans)->ev_qualifiers; for (next_qualifier = (*next_trans)->ev_qualifiers;
next_qualifier && *next_qualifier && next_qualifier && *next_qualifier &&
!(*next_qualifier)(sk, ev); next_qualifier++) !(*next_qualifier)(sk, skb); next_qualifier++)
/* nothing */; /* nothing */;
if (!next_qualifier || !*next_qualifier) if (!next_qualifier || !*next_qualifier)
/* all qualifiers executed successfully; this is /* all qualifiers executed successfully; this is
...@@ -384,7 +369,7 @@ static struct llc_conn_state_trans * ...@@ -384,7 +369,7 @@ static struct llc_conn_state_trans *
* llc_exec_conn_trans_actions - executes related actions * llc_exec_conn_trans_actions - executes related actions
* @sk: connection * @sk: connection
* @trans: transition that it's actions must be performed * @trans: transition that it's actions must be performed
* @ev: happened event * @skb: happened event
* *
* Executes actions that is related to happened event. Returns 0 for * Executes actions that is related to happened event. Returns 0 for
* success, 1 to indicate failure of at least one action or 2 if the * success, 1 to indicate failure of at least one action or 2 if the
...@@ -392,14 +377,14 @@ static struct llc_conn_state_trans * ...@@ -392,14 +377,14 @@ static struct llc_conn_state_trans *
*/ */
static int llc_exec_conn_trans_actions(struct sock *sk, static int llc_exec_conn_trans_actions(struct sock *sk,
struct llc_conn_state_trans *trans, struct llc_conn_state_trans *trans,
struct llc_conn_state_ev *ev) struct sk_buff *skb)
{ {
int rc = 0; int rc = 0;
llc_conn_action_t *next_action; llc_conn_action_t *next_action;
for (next_action = trans->ev_actions; for (next_action = trans->ev_actions;
next_action && *next_action; next_action++) { next_action && *next_action; next_action++) {
int rc2 = (*next_action)(sk, ev); int rc2 = (*next_action)(sk, skb);
if (rc2 == 2) { if (rc2 == 2) {
rc = rc2; rc = rc2;
......
...@@ -24,39 +24,48 @@ ...@@ -24,39 +24,48 @@
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station, int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_SIMPLE && return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
ev->data.a.ev == ev->data.a.ev ==
LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1; LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
} }
int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station, int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_SIMPLE && return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
ev->data.a.ev == ev->data.a.ev ==
LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1; LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
} }
int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *station, int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
station->retry_count < station->maximum_retry ? 0 : 1; station->retry_count < station->maximum_retry ? 0 : 1;
} }
int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station, int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_ACK_TMR && return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
station->retry_count == station->maximum_retry ? 0 : 1; station->retry_count == station->maximum_retry ? 0 : 1;
} }
int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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 && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
...@@ -66,9 +75,10 @@ int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, ...@@ -66,9 +75,10 @@ int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
} }
int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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 && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_RSP(pdu) && /* response PDU */ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
...@@ -79,9 +89,10 @@ int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, ...@@ -79,9 +89,10 @@ int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
} }
int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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 && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_RSP(pdu) && /* response PDU */ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
...@@ -92,9 +103,10 @@ int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, ...@@ -92,9 +103,10 @@ int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
} }
int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.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 && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
...@@ -103,9 +115,10 @@ int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, ...@@ -103,9 +115,10 @@ int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
!pdu->dsap ? 0 : 1; /* NULL DSAP */ !pdu->dsap ? 0 : 1; /* NULL DSAP */
} }
int llc_stat_ev_disable_req(struct llc_station *station, int llc_stat_ev_disable_req(struct llc_station *station, struct sk_buff *skb)
struct llc_station_state_ev *ev)
{ {
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_PRIM && return ev->type == LLC_STATION_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_DISABLE_PRIM && ev->data.prim.prim == LLC_DISABLE_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
......
...@@ -168,15 +168,13 @@ static int llc_unitdata_req_handler(struct llc_prim_if_block *prim) ...@@ -168,15 +168,13 @@ static int llc_unitdata_req_handler(struct llc_prim_if_block *prim)
if (!sap) if (!sap)
goto out; goto out;
ev = llc_sap_alloc_ev(sap); ev = llc_sap_ev(prim->data->udata.skb);
if (!ev)
goto out;
ev->type = LLC_SAP_EV_TYPE_PRIM; ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATAUNIT_PRIM; ev->data.prim.prim = LLC_DATAUNIT_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = 0; rc = 0;
llc_sap_send_ev(sap, ev); llc_sap_send_ev(sap, prim->data->udata.skb);
out: out:
return rc; return rc;
} }
...@@ -196,15 +194,13 @@ static int llc_test_req_handler(struct llc_prim_if_block *prim) ...@@ -196,15 +194,13 @@ static int llc_test_req_handler(struct llc_prim_if_block *prim)
struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap); struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap);
if (!sap) if (!sap)
goto out; goto out;
ev = llc_sap_alloc_ev(sap); ev = llc_sap_ev(prim->data->udata.skb);
if (!ev)
goto out;
ev->type = LLC_SAP_EV_TYPE_PRIM; ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_TEST_PRIM; ev->data.prim.prim = LLC_TEST_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = 0; rc = 0;
llc_sap_send_ev(sap, ev); llc_sap_send_ev(sap, prim->data->udata.skb);
out: out:
return rc; return rc;
} }
...@@ -225,15 +221,13 @@ static int llc_xid_req_handler(struct llc_prim_if_block *prim) ...@@ -225,15 +221,13 @@ static int llc_xid_req_handler(struct llc_prim_if_block *prim)
if (!sap) if (!sap)
goto out; goto out;
ev = llc_sap_alloc_ev(sap); ev = llc_sap_ev(prim->data->udata.skb);
if (!ev)
goto out;
ev->type = LLC_SAP_EV_TYPE_PRIM; ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_XID_PRIM; ev->data.prim.prim = LLC_XID_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = 0; rc = 0;
llc_sap_send_ev(sap, ev); llc_sap_send_ev(sap, prim->data->udata.skb);
out: out:
return rc; return rc;
} }
...@@ -273,29 +267,26 @@ static int llc_data_req_handler(struct llc_prim_if_block *prim) ...@@ -273,29 +267,26 @@ static int llc_data_req_handler(struct llc_prim_if_block *prim)
llc->failed_data_req = 1; llc->failed_data_req = 1;
goto out; goto out;
} }
rc = -ENOMEM; ev = llc_conn_ev(prim->data->data.skb);
ev = llc_conn_alloc_ev(sk); ev->type = LLC_CONN_EV_TYPE_PRIM;
if (ev) { ev->data.prim.prim = LLC_DATA_PRIM;
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.prim = LLC_DATA_PRIM; ev->data.prim.data = prim;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; prim->data->data.skb->dev = llc->dev;
ev->data.prim.data = prim; rc = llc_conn_send_ev(sk, prim->data->data.skb);
prim->data->data.skb->dev = llc->dev;
rc = llc_conn_send_ev(sk, ev);
}
out: out:
release_sock(sk); release_sock(sk);
return rc; return rc;
} }
/** /**
* confirm_impossible - Informs upper layer about failed connection * llc_confirm_impossible - Informs upper layer about failed connection
* @prim: pointer to structure that contains confirmation data. * @prim: pointer to structure that contains confirmation data.
* *
* Informs upper layer about failing in connection establishment. This * Informs upper layer about failing in connection establishment. This
* function is called by llc_conn_req_handler. * function is called by llc_conn_req_handler.
*/ */
static void confirm_impossible(struct llc_prim_if_block *prim) static void llc_confirm_impossible(struct llc_prim_if_block *prim)
{ {
prim->data->conn.status = LLC_STATUS_IMPOSSIBLE; prim->data->conn.status = LLC_STATUS_IMPOSSIBLE;
prim->sap->conf(prim); prim->sap->conf(prim);
...@@ -316,7 +307,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) ...@@ -316,7 +307,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
int rc = -EBUSY; int rc = -EBUSY;
struct llc_opt *llc; struct llc_opt *llc;
struct llc_sap *sap = prim->sap; struct llc_sap *sap = prim->sap;
struct llc_conn_state_ev *ev; struct sk_buff *skb;
struct net_device *ddev = mac_dev_peer(prim->data->conn.dev, struct net_device *ddev = mac_dev_peer(prim->data->conn.dev,
prim->data->conn.dev->type, prim->data->conn.dev->type,
prim->data->conn.daddr.mac), prim->data->conn.daddr.mac),
...@@ -334,7 +325,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) ...@@ -334,7 +325,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
daddr.lsap = prim->data->conn.daddr.lsap; daddr.lsap = prim->data->conn.daddr.lsap;
sk = llc_find_sock(sap, &daddr, &laddr); sk = llc_find_sock(sap, &daddr, &laddr);
if (sk) { if (sk) {
confirm_impossible(prim); llc_confirm_impossible(prim);
goto out_put; goto out_put;
} }
rc = -ENOMEM; rc = -ENOMEM;
...@@ -345,7 +336,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) ...@@ -345,7 +336,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
} else { } else {
sk = llc_sock_alloc(); sk = llc_sock_alloc();
if (!sk) { if (!sk) {
confirm_impossible(prim); llc_confirm_impossible(prim);
goto out; goto out;
} }
prim->data->conn.sk = sk; prim->data->conn.sk = sk;
...@@ -360,18 +351,20 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim) ...@@ -360,18 +351,20 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
llc->dev = ddev; llc->dev = ddev;
llc->link = prim->data->conn.link; llc->link = prim->data->conn.link;
llc->handler = prim->data->conn.handler; llc->handler = prim->data->conn.handler;
ev = llc_conn_alloc_ev(sk); skb = alloc_skb(1, GFP_ATOMIC);
if (ev) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_CONN_PRIM; ev->data.prim.prim = LLC_CONN_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev); rc = llc_conn_send_ev(sk, skb);
} }
if (rc) { if (rc) {
llc_sap_unassign_sock(sap, sk); llc_sap_unassign_sock(sap, sk);
llc_sock_free(sk); llc_sock_free(sk);
confirm_impossible(prim); llc_confirm_impossible(prim);
} }
release_sock(sk); release_sock(sk);
out_put: out_put:
...@@ -393,6 +386,7 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim) ...@@ -393,6 +386,7 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_conn_state_ev *ev; struct llc_conn_state_ev *ev;
struct sk_buff *skb;
struct sock* sk = prim->data->disc.sk; struct sock* sk = prim->data->disc.sk;
sock_hold(sk); sock_hold(sk);
...@@ -400,17 +394,19 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim) ...@@ -400,17 +394,19 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim)
if (llc_sk(sk)->state == LLC_CONN_STATE_ADM || if (llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
goto out; goto out;
/* postpone unassigning the connection from its SAP and returning the /*
* Postpone unassigning the connection from its SAP and returning the
* connection until all ACTIONs have been completely executed * connection until all ACTIONs have been completely executed
*/ */
ev = llc_conn_alloc_ev(sk); skb = alloc_skb(1, GFP_ATOMIC);
if (!ev) if (!skb)
goto out; goto out;
ev->type = LLC_CONN_EV_TYPE_PRIM; ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DISC_PRIM; ev->data.prim.prim = LLC_DISC_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev); rc = llc_conn_send_ev(sk, skb);
out: out:
release_sock(sk); release_sock(sk);
sock_put(sk); sock_put(sk);
...@@ -428,18 +424,20 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim) ...@@ -428,18 +424,20 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim)
*/ */
static int llc_rst_req_handler(struct llc_prim_if_block *prim) static int llc_rst_req_handler(struct llc_prim_if_block *prim)
{ {
struct sk_buff *skb;
int rc = 1; int rc = 1;
struct sock *sk = prim->data->res.sk; struct sock *sk = prim->data->res.sk;
struct llc_conn_state_ev *ev;
lock_sock(sk); lock_sock(sk);
ev = llc_conn_alloc_ev(sk); skb = alloc_skb(1, GFP_ATOMIC);
if (ev) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_RESET_PRIM; ev->data.prim.prim = LLC_RESET_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ; ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev); rc = llc_conn_send_ev(sk, skb);
} }
release_sock(sk); release_sock(sk);
return rc; return rc;
...@@ -497,18 +495,21 @@ static int llc_conn_rsp_handler(struct llc_prim_if_block *prim) ...@@ -497,18 +495,21 @@ static int llc_conn_rsp_handler(struct llc_prim_if_block *prim)
static int llc_rst_rsp_handler(struct llc_prim_if_block *prim) static int llc_rst_rsp_handler(struct llc_prim_if_block *prim)
{ {
int rc = 1; int rc = 1;
/* network layer supplies connection handle; map it to a connection; /*
* Network layer supplies connection handle; map it to a connection;
* package as event and send it to connection event handler * package as event and send it to connection event handler
*/ */
struct sock *sk = prim->data->res.sk; struct sock *sk = prim->data->res.sk;
struct llc_conn_state_ev *ev = llc_conn_alloc_ev(sk); struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
if (ev) {
ev->type = LLC_CONN_EV_TYPE_PRIM; ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_RESET_PRIM; ev->data.prim.prim = LLC_RESET_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_RESP; ev->data.prim.type = LLC_PRIM_TYPE_RESP;
ev->data.prim.data = prim; ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev); rc = llc_conn_send_ev(sk, skb);
} }
return rc; return rc;
} }
......
...@@ -27,6 +27,12 @@ ...@@ -27,6 +27,12 @@
#include <net/llc_s_ev.h> #include <net/llc_s_ev.h>
#include <linux/trdevice.h> #include <linux/trdevice.h>
#if 1
#define dprintk(args...) printk(KERN_DEBUG args)
#else
#define dprintk(args...)
#endif
/* function prototypes */ /* function prototypes */
static void fix_up_incoming_skb(struct sk_buff *skb); static void fix_up_incoming_skb(struct sk_buff *skb);
...@@ -46,7 +52,7 @@ int mac_send_pdu(struct sk_buff *skb) ...@@ -46,7 +52,7 @@ int mac_send_pdu(struct sk_buff *skb)
int pri = GFP_ATOMIC, rc = -1; int pri = GFP_ATOMIC, rc = -1;
if (!skb->dev) { if (!skb->dev) {
printk(KERN_ERR "%s: skb->dev == NULL!", __FUNCTION__); dprintk(KERN_ERR "%s: skb->dev == NULL!", __FUNCTION__);
goto out; goto out;
} }
if (skb->sk) if (skb->sk)
...@@ -83,7 +89,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -83,7 +89,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
* receives, do not try to analyse it. * receives, do not try to analyse it.
*/ */
if (skb->pkt_type == PACKET_OTHERHOST) { if (skb->pkt_type == PACKET_OTHERHOST) {
printk(KERN_INFO "%s: PACKET_OTHERHOST\n", __FUNCTION__); dprintk(KERN_INFO "%s: PACKET_OTHERHOST\n", __FUNCTION__);
goto drop; goto drop;
} }
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
...@@ -140,7 +146,8 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -140,7 +146,8 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
rc = llc_pdu_router(llc_sk(sk)->sap, sk, skb, rc = llc_pdu_router(llc_sk(sk)->sap, sk, skb,
LLC_TYPE_2); LLC_TYPE_2);
} else { } else {
skb->cb[0] = LLC_PACKET; dprintk(KERN_INFO "%s: add to backlog\n", __FUNCTION__);
llc_set_backlog_type(skb, LLC_PACKET);
sk_add_backlog(sk, skb); sk_add_backlog(sk, skb);
rc = 0; rc = 0;
} }
...@@ -207,38 +214,27 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk, ...@@ -207,38 +214,27 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
if (!pdu->dsap) { if (!pdu->dsap) {
struct llc_station *station = llc_station_get(); struct llc_station *station = llc_station_get();
struct llc_station_state_ev *stat_ev = struct llc_station_state_ev *ev = llc_station_ev(skb);
llc_station_alloc_ev(station);
if (stat_ev) { ev->type = LLC_STATION_EV_TYPE_PDU;
stat_ev->type = LLC_STATION_EV_TYPE_PDU; ev->data.pdu.reason = 0;
stat_ev->data.pdu.skb = skb; llc_station_send_ev(station, skb);
stat_ev->data.pdu.reason = 0;
llc_station_send_ev(station, stat_ev);
} else
rc = -ENOMEM;
} else if (type == LLC_TYPE_1) { } else if (type == LLC_TYPE_1) {
struct llc_sap_state_ev *sap_ev = llc_sap_alloc_ev(sap); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
if (sap_ev) { ev->type = LLC_SAP_EV_TYPE_PDU;
sap_ev->type = LLC_SAP_EV_TYPE_PDU; ev->data.pdu.reason = 0;
sap_ev->data.pdu.skb = skb; llc_sap_send_ev(sap, skb);
sap_ev->data.pdu.reason = 0;
llc_sap_send_ev(sap, sap_ev);
} else
rc = -ENOMEM;
} else if (type == LLC_TYPE_2) { } else if (type == LLC_TYPE_2) {
struct llc_conn_state_ev *conn_ev = llc_conn_alloc_ev(sk); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
if (!llc->dev) if (!llc->dev)
llc->dev = skb->dev; llc->dev = skb->dev;
if (conn_ev) {
conn_ev->type = LLC_CONN_EV_TYPE_PDU; ev->type = LLC_CONN_EV_TYPE_PDU;
conn_ev->data.pdu.skb = skb; ev->data.pdu.reason = 0;
conn_ev->data.pdu.reason = 0; rc = llc_conn_send_ev(sk, skb);
rc = llc_conn_send_ev(sk, conn_ev);
} else
rc = -ENOMEM;
} else } else
rc = -EINVAL; rc = -EINVAL;
return rc; return rc;
......
...@@ -38,16 +38,16 @@ ...@@ -38,16 +38,16 @@
/* static function prototypes */ /* static function prototypes */
static void llc_station_service_events(struct llc_station *station); static void llc_station_service_events(struct llc_station *station);
static void llc_station_free_ev(struct llc_station *station, static void llc_station_free_ev(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
static void llc_station_send_pdus(struct llc_station *station); static void llc_station_send_pdus(struct llc_station *station);
static u16 llc_station_next_state(struct llc_station *station, static u16 llc_station_next_state(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
static u16 llc_exec_station_trans_actions(struct llc_station *station, static u16 llc_exec_station_trans_actions(struct llc_station *station,
struct llc_station_state_trans *trans, struct llc_station_state_trans *trans,
struct llc_station_state_ev *ev); struct sk_buff *skb);
static struct llc_station_state_trans * static struct llc_station_state_trans *
llc_find_station_trans(struct llc_station *station, llc_find_station_trans(struct llc_station *station,
struct llc_station_state_ev *ev); struct sk_buff *skb);
static int llc_rtn_all_conns(struct llc_sap *sap); static int llc_rtn_all_conns(struct llc_sap *sap);
static struct llc_station llc_main_station; /* only one of its kind */ static struct llc_station llc_main_station; /* only one of its kind */
...@@ -144,21 +144,23 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -144,21 +144,23 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
int rc = 0; int rc = 0;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
if (skb->cb[0] == LLC_PACKET) { if (llc_backlog_type(skb) == LLC_PACKET) {
if (llc->state > 1) /* not closed */ if (llc->state > 1) /* not closed */
rc = llc_pdu_router(llc->sap, sk, skb, LLC_TYPE_2); rc = llc_pdu_router(llc->sap, sk, skb, LLC_TYPE_2);
else else
kfree_skb(skb); kfree_skb(skb);
} else if (skb->cb[0] == LLC_EVENT) { } else if (llc_backlog_type(skb) == LLC_EVENT) {
struct llc_conn_state_ev *ev =
(struct llc_conn_state_ev *)skb->data;
/* timer expiration event */ /* timer expiration event */
if (llc->state > 1) /* not closed */ if (llc->state > 1) /* not closed */
rc = llc_conn_send_ev(sk, ev); rc = llc_conn_send_ev(sk, skb);
else else
llc_conn_free_ev(ev); llc_conn_free_ev(skb);
kfree_skb(skb);
} else {
printk(KERN_ERR "%s: invalid skb in backlog\n", __FUNCTION__);
kfree_skb(skb); kfree_skb(skb);
} }
return rc; return rc;
} }
...@@ -232,9 +234,11 @@ void __llc_sock_free(struct sock *sk, u8 free) ...@@ -232,9 +234,11 @@ void __llc_sock_free(struct sock *sk, u8 free)
/* stop all (possibly) running timers */ /* stop all (possibly) running timers */
llc_conn_ac_stop_all_timers(sk, NULL); llc_conn_ac_stop_all_timers(sk, NULL);
/* handle return of frames on lists */ /* handle return of frames on lists */
#if 0
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__, printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
skb_queue_len(&llc->pdu_unack_q), skb_queue_len(&llc->pdu_unack_q),
skb_queue_len(&sk->write_queue)); skb_queue_len(&sk->write_queue));
#endif
skb_queue_purge(&sk->write_queue); skb_queue_purge(&sk->write_queue);
skb_queue_purge(&llc->pdu_unack_q); skb_queue_purge(&llc->pdu_unack_q);
if (free) if (free)
...@@ -315,35 +319,18 @@ struct llc_station *llc_station_get(void) ...@@ -315,35 +319,18 @@ struct llc_station *llc_station_get(void)
return &llc_main_station; return &llc_main_station;
} }
/**
* llc_station_alloc_ev - allocates an event
* @station: Address of the station
*
* Allocates an event in this station. Returns the allocated event on
* success, %NULL otherwise.
*/
struct llc_station_state_ev *llc_station_alloc_ev(struct llc_station *station)
{
struct llc_station_state_ev *ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
if (ev)
memset(ev, 0, sizeof(*ev));
return ev;
}
/** /**
* llc_station_send_ev: queue event and try to process queue. * llc_station_send_ev: queue event and try to process queue.
* @station: Address of the station * @station: Address of the station
* @ev: Address of the event * @skb: Address of the event
* *
* Queues an event (on the station event queue) for handling by the * Queues an event (on the station event queue) for handling by the
* station state machine and attempts to process any queued-up events. * station state machine and attempts to process any queued-up events.
*/ */
void llc_station_send_ev(struct llc_station *station, void llc_station_send_ev(struct llc_station *station, struct sk_buff *skb)
struct llc_station_state_ev *ev)
{ {
spin_lock_bh(&station->ev_q.lock); spin_lock_bh(&station->ev_q.lock);
list_add_tail(&ev->node, &station->ev_q.list); skb_queue_tail(&station->ev_q.list, skb);
llc_station_service_events(station); llc_station_service_events(station);
spin_unlock_bh(&station->ev_q.lock); spin_unlock_bh(&station->ev_q.lock);
} }
...@@ -384,18 +371,17 @@ static void llc_station_send_pdus(struct llc_station *station) ...@@ -384,18 +371,17 @@ static void llc_station_send_pdus(struct llc_station *station)
/** /**
* llc_station_free_ev - frees an event * llc_station_free_ev - frees an event
* @station: Address of the station * @station: Address of the station
* @event: Address of the event * @skb: Address of the event
* *
* Frees an event. * Frees an event.
*/ */
static void llc_station_free_ev(struct llc_station *station, static void llc_station_free_ev(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
struct sk_buff *skb = ev->data.pdu.skb; struct llc_station_state_ev *ev = llc_station_ev(skb);
if (ev->type == LLC_STATION_EV_TYPE_PDU) if (ev->type == LLC_STATION_EV_TYPE_PDU)
kfree_skb(skb); kfree_skb(skb);
kfree(ev);
} }
/** /**
...@@ -412,39 +398,35 @@ static void llc_station_free_ev(struct llc_station *station, ...@@ -412,39 +398,35 @@ static void llc_station_free_ev(struct llc_station *station,
*/ */
static void llc_station_service_events(struct llc_station *station) static void llc_station_service_events(struct llc_station *station)
{ {
struct llc_station_state_ev *ev; struct sk_buff *skb;
struct list_head *entry, *tmp;
list_for_each_safe(entry, tmp, &station->ev_q.list) { while ((skb = skb_dequeue(&station->ev_q.list)) != NULL)
ev = list_entry(entry, struct llc_station_state_ev, node); llc_station_next_state(station, skb);
list_del(&ev->node);
llc_station_next_state(station, ev);
}
} }
/** /**
* llc_station_next_state - processes event and goes to the next state * llc_station_next_state - processes event and goes to the next state
* @station: Address of the station * @station: Address of the station
* @ev: Address of the event * @skb: Address of the event
* *
* Processes an event, executes any transitions related to that event and * Processes an event, executes any transitions related to that event and
* updates the state of the station. * updates the state of the station.
*/ */
static u16 llc_station_next_state(struct llc_station *station, static u16 llc_station_next_state(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
u16 rc = 1; u16 rc = 1;
struct llc_station_state_trans *trans; struct llc_station_state_trans *trans;
if (station->state > LLC_NBR_STATION_STATES) if (station->state > LLC_NBR_STATION_STATES)
goto out; goto out;
trans = llc_find_station_trans(station, ev); trans = llc_find_station_trans(station, skb);
if (trans) { if (trans) {
/* got the state to which we next transition; perform the /* got the state to which we next transition; perform the
* actions associated with this transition before actually * actions associated with this transition before actually
* transitioning to the next state * transitioning to the next state
*/ */
rc = llc_exec_station_trans_actions(station, trans, ev); rc = llc_exec_station_trans_actions(station, trans, skb);
if (!rc) if (!rc)
/* transition station to next state if all actions /* transition station to next state if all actions
* execute successfully; done; wait for next event * execute successfully; done; wait for next event
...@@ -456,22 +438,22 @@ static u16 llc_station_next_state(struct llc_station *station, ...@@ -456,22 +438,22 @@ static u16 llc_station_next_state(struct llc_station *station,
*/ */
rc = 0; rc = 0;
out: out:
llc_station_free_ev(station, ev); llc_station_free_ev(station, skb);
return rc; return rc;
} }
/** /**
* llc_find_station_trans - finds transition for this event * llc_find_station_trans - finds transition for this event
* @station: Address of the station * @station: Address of the station
* @ev: Address of the event * @skb: Address of the event
* *
* Search thru events of the current state of the station until list * 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 * 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. * state. Returns the address of the transition if cound, %NULL otherwise.
*/ */
static struct llc_station_state_trans * static struct llc_station_state_trans *
llc_find_station_trans(struct llc_station *station, llc_find_station_trans(struct llc_station *station,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
int i = 0; int i = 0;
struct llc_station_state_trans *rc = NULL; struct llc_station_state_trans *rc = NULL;
...@@ -480,7 +462,7 @@ static struct llc_station_state_trans * ...@@ -480,7 +462,7 @@ static struct llc_station_state_trans *
&llc_station_state_table[station->state - 1]; &llc_station_state_table[station->state - 1];
for (next_trans = curr_state->transitions; next_trans[i]->ev; i++) for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
if (!next_trans[i]->ev(station, ev)) { if (!next_trans[i]->ev(station, skb)) {
rc = next_trans[i]; rc = next_trans[i];
break; break;
} }
...@@ -491,21 +473,20 @@ static struct llc_station_state_trans * ...@@ -491,21 +473,20 @@ static struct llc_station_state_trans *
* llc_exec_station_trans_actions - executes actions for transition * llc_exec_station_trans_actions - executes actions for transition
* @station: Address of the station * @station: Address of the station
* @trans: Address of the transition * @trans: Address of the transition
* @ev: Address of the event that caused the transition * @skb: Address of the event that caused the transition
* *
* Executes actions of a transition of the station state machine. Returns * Executes actions of a transition of the station state machine. Returns
* 0 if all actions complete successfully, nonzero otherwise. * 0 if all actions complete successfully, nonzero otherwise.
*/ */
static u16 llc_exec_station_trans_actions(struct llc_station *station, static u16 llc_exec_station_trans_actions(struct llc_station *station,
struct llc_station_state_trans *trans, struct llc_station_state_trans *trans,
struct llc_station_state_ev *ev) struct sk_buff *skb)
{ {
u16 rc = 0; u16 rc = 0;
llc_station_action_t *next_action; llc_station_action_t *next_action = trans->ev_actions;
for (next_action = trans->ev_actions; for (; next_action && *next_action; next_action++)
next_action && *next_action; next_action++) if ((*next_action)(station, skb))
if ((*next_action)(station, ev))
rc = 1; rc = 1;
return rc; return rc;
} }
...@@ -595,21 +576,24 @@ static char llc_error_msg[] __initdata = ...@@ -595,21 +576,24 @@ static char llc_error_msg[] __initdata =
static int __init llc_init(void) static int __init llc_init(void)
{ {
u16 rc = 0; u16 rc = 0;
struct sk_buff *skb;
struct llc_station_state_ev *ev; struct llc_station_state_ev *ev;
printk(llc_banner); printk(llc_banner);
INIT_LIST_HEAD(&llc_main_station.ev_q.list);
spin_lock_init(&llc_main_station.ev_q.lock);
INIT_LIST_HEAD(&llc_main_station.sap_list.list); INIT_LIST_HEAD(&llc_main_station.sap_list.list);
spin_lock_init(&llc_main_station.sap_list.lock); spin_lock_init(&llc_main_station.sap_list.lock);
skb_queue_head_init(&llc_main_station.mac_pdu_q); skb_queue_head_init(&llc_main_station.mac_pdu_q);
ev = kmalloc(sizeof(*ev), GFP_ATOMIC); skb_queue_head_init(&llc_main_station.ev_q.list);
if (!ev) spin_lock_init(&llc_main_station.ev_q.lock);
skb = alloc_skb(1, GFP_ATOMIC);
if (!skb)
goto err; goto err;
llc_build_offset_table(); llc_build_offset_table();
ev = llc_station_ev(skb);
memset(ev, 0, sizeof(*ev)); memset(ev, 0, sizeof(*ev));
if(dev_base->next) if (dev_base->next)
memcpy(llc_main_station.mac_sa, dev_base->next->dev_addr, ETH_ALEN); memcpy(llc_main_station.mac_sa,
dev_base->next->dev_addr, ETH_ALEN);
else else
memset(llc_main_station.mac_sa, 0, ETH_ALEN); memset(llc_main_station.mac_sa, 0, ETH_ALEN);
llc_main_station.ack_timer.expires = jiffies + 3 * HZ; llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
...@@ -617,7 +601,7 @@ static int __init llc_init(void) ...@@ -617,7 +601,7 @@ static int __init llc_init(void)
llc_main_station.state = LLC_STATION_STATE_DOWN; llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
rc = llc_station_next_state(&llc_main_station, ev); rc = llc_station_next_state(&llc_main_station, skb);
proc_net_create("802.2", 0, llc_proc_get_info); proc_net_create("802.2", 0, llc_proc_get_info);
llc_ui_init(); llc_ui_init();
dev_add_pack(&llc_packet_type); dev_add_pack(&llc_packet_type);
......
This diff is collapsed.
...@@ -20,82 +20,96 @@ ...@@ -20,82 +20,96 @@
#include <net/llc_s_ev.h> #include <net/llc_s_ev.h>
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
int llc_sap_ev_activation_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_activation_req(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_SIMPLE && return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1; ev->data.a.ev == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1;
} }
int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_UI ? 0 : 1; LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_UI ? 0 : 1;
} }
int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM && return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_DATAUNIT_PRIM && ev->data.prim.prim == LLC_DATAUNIT_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_sap_ev_xid_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM && return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_XID_PRIM && ev->data.prim.prim == LLC_XID_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1; LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1;
} }
int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1; LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1;
} }
int llc_sap_ev_test_req(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_PRIM && return ev->type == LLC_SAP_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_TEST_PRIM && ev->data.prim.prim == LLC_TEST_PRIM &&
ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1; ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
} }
int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1; LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
} }
int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev) int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_pdu_un *pdu = llc_pdu_un_hdr(ev->data.pdu.skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) && return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1; LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
} }
int llc_sap_ev_deactivation_req(struct llc_sap *sap, int llc_sap_ev_deactivation_req(struct llc_sap *sap, struct sk_buff *skb)
struct llc_sap_state_ev *ev)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
return ev->type == LLC_SAP_EV_TYPE_SIMPLE && return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
ev->data.a.ev == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1; ev->data.a.ev == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1;
} }
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
* last entry for this state * last entry for this state
* all members are zeros, .bss zeroes it * all members are zeros, .bss zeroes it
*/ */
static struct llc_sap_state_trans llc_sap_state_trans_n; static struct llc_sap_state_trans llc_sap_state_trans_end;
/* state LLC_SAP_STATE_INACTIVE transition for /* state LLC_SAP_STATE_INACTIVE transition for
* LLC_SAP_EV_ACTIVATION_REQ event * LLC_SAP_EV_ACTIVATION_REQ event
...@@ -43,7 +43,7 @@ static struct llc_sap_state_trans llc_sap_inactive_state_trans_1 = { ...@@ -43,7 +43,7 @@ static struct llc_sap_state_trans llc_sap_inactive_state_trans_1 = {
/* array of pointers; one to each transition */ /* array of pointers; one to each transition */
static struct llc_sap_state_trans *llc_sap_inactive_state_transitions[] = { static struct llc_sap_state_trans *llc_sap_inactive_state_transitions[] = {
[0] = &llc_sap_inactive_state_trans_1, [0] = &llc_sap_inactive_state_trans_1,
[1] = &llc_sap_state_trans_n, [1] = &llc_sap_state_trans_end,
}; };
/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_UI event */ /* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_UI event */
...@@ -167,17 +167,17 @@ static struct llc_sap_state_trans *llc_sap_active_state_transitions[] = { ...@@ -167,17 +167,17 @@ static struct llc_sap_state_trans *llc_sap_active_state_transitions[] = {
[6] = &llc_sap_active_state_trans_7, [6] = &llc_sap_active_state_trans_7,
[7] = &llc_sap_active_state_trans_8, [7] = &llc_sap_active_state_trans_8,
[8] = &llc_sap_active_state_trans_9, [8] = &llc_sap_active_state_trans_9,
[9] = &llc_sap_state_trans_n, [9] = &llc_sap_state_trans_end,
}; };
/* SAP state transition table */ /* SAP state transition table */
struct llc_sap_state llc_sap_state_table[] = { struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES] = {
{ [LLC_SAP_STATE_INACTIVE - 1] = {
.curr_state = LLC_SAP_STATE_INACTIVE, .curr_state = LLC_SAP_STATE_INACTIVE,
.transitions = llc_sap_inactive_state_transitions, .transitions = llc_sap_inactive_state_transitions,
}, },
{ [LLC_SAP_STATE_ACTIVE - 1] = {
.curr_state = LLC_SAP_STATE_ACTIVE, .curr_state = LLC_SAP_STATE_ACTIVE,
.transitions = llc_sap_active_state_transitions, .transitions = llc_sap_active_state_transitions,
}, },
}; };
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment