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 @@
/* All station state event action functions look like this */
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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 */
This diff is collapsed.
This diff is collapsed.
......@@ -136,12 +136,10 @@ extern void llc_sock_reset(struct sock *sk);
extern int llc_sock_init(struct sock *sk);
/* 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 llc_conn_state_ev *ev);
extern int llc_conn_send_ev(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,
struct llc_conn_state_ev *ev);
extern void llc_conn_free_ev(struct llc_conn_state_ev *ev);
extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
extern void llc_conn_free_ev(struct sk_buff *skb);
extern void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr,
u8 first_p_bit);
extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr,
......
......@@ -58,7 +58,7 @@ union llc_stat_ev_if {
struct llc_stat_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_stat_ev_prim_if prim;
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 */
};
......@@ -68,26 +68,32 @@ struct llc_station_state_ev {
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
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 *
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
#endif /* LLC_EVNT_H */
......@@ -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,
struct sk_buff *skb, u8 type);
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 */
......@@ -19,35 +19,40 @@
#define LLC_ACK_TIME 3
#define LLC_REJ_TIME 3
#define LLC_BUSY_TIME 3
#define LLC_SENDACK_TIME 50
#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */
#define LLC_DEST_SAP 1 /* Type 1 goes here */
#define LLC_DEST_CONN 2 /* Type 2 goes here */
/* LLC Layer global default parameters */
#define LLC_GLOBAL_DEFAULT_MAX_NBR_SAPS 4
#define LLC_GLOBAL_DEFAULT_MAX_NBR_CONNS 64
/* LLC station component (SAP and connection resource manager) */
/* Station component; one per adapter */
/**
* 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
* @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 {
u8 state; /* state of station */
u8 xid_r_count; /* XID response PDU counter */
struct timer_list ack_timer;
u8 ack_tmr_running; /* 1 or 0 */
u8 retry_count;
u8 maximum_retry;
u8 mac_sa[6]; /* MAC source address */
u8 state;
u8 xid_r_count;
struct timer_list ack_timer;
u8 ack_tmr_running;
u8 retry_count;
u8 maximum_retry;
u8 mac_sa[6];
struct {
spinlock_t lock;
struct list_head list;
} sap_list; /* list of related SAPs */
spinlock_t lock;
struct list_head list;
} sap_list;
struct {
spinlock_t lock;
struct list_head list;
} ev_q; /* events entering state mach. */
struct sk_buff_head mac_pdu_q; /* PDUs ready to send to MAC */
struct sk_buff_head list;
spinlock_t lock;
} ev_q;
struct sk_buff_head mac_pdu_q;
};
struct llc_station_state_ev;
......@@ -56,10 +61,8 @@ extern void llc_sap_save(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_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,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
extern void llc_station_send_pdu(struct llc_station *station,
struct sk_buff *skb);
extern struct sk_buff *llc_alloc_frame(void);
......
......@@ -23,25 +23,17 @@
#define SAP_ACT_TEST_IND 9
/* All action functions must look like this */
typedef int (*llc_sap_action_t)(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
typedef int (*llc_sap_action_t)(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_unitdata_ind(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_send_ui(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_send_xid_c(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_send_xid_r(struct llc_sap *sap,
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);
struct sk_buff *skb);
extern int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_action_report_status(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_xid_ind(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_action_test_ind(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, struct sk_buff *skb);
extern int llc_sap_action_test_ind(struct llc_sap *sap, struct sk_buff *skb);
#endif /* LLC_S_AC_H */
......@@ -11,6 +11,9 @@
*
* See the GNU General Public License for more details.
*/
#include <linux/skbuff.h>
/* Defines SAP component events */
/* Types of events (possible values in 'ev->type') */
#define LLC_SAP_EV_TYPE_SIMPLE 1
......@@ -45,9 +48,8 @@ struct llc_sap_ev_prim_if {
};
struct llc_sap_ev_pdu_if {
u8 ev;
u8 reason;
struct sk_buff *skb;
u8 ev;
u8 reason;
};
struct llc_sap_ev_tmr_if {
......@@ -75,27 +77,24 @@ struct llc_sap_state_ev {
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;
typedef int (*llc_sap_ev_t)(struct llc_sap *sap, struct llc_sap_state_ev *ev);
extern int llc_sap_ev_activation_req(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
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 llc_sap_state_ev *ev);
extern int llc_sap_ev_xid_req(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap,
struct llc_sap_state_ev *ev);
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);
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, struct sk_buff *skb);
extern int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_test_req(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb);
extern int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct sk_buff *skb);
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 */
......@@ -15,7 +15,8 @@
#define LLC_SAP_STATE_INACTIVE 1
#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 */
/* SAP state table structure */
struct llc_sap_state_trans {
......@@ -25,10 +26,10 @@ struct llc_sap_state_trans {
};
struct llc_sap_state {
u8 curr_state;
struct llc_sap_state_trans **transitions;
u8 curr_state;
struct llc_sap_state_trans **transitions;
};
/* 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 */
......@@ -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_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_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb,
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_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 */
......@@ -27,7 +27,7 @@
static void llc_station_ack_tmr_callback(unsigned long timeout_data);
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);
station->ack_timer.expires = jiffies + LLC_ACK_TIME * HZ;
......@@ -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,
struct llc_station_state_ev *ev)
struct sk_buff *skb)
{
station->retry_count = 0;
return 0;
}
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++;
return 0;
}
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;
return 0;
}
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++;
return 0;
}
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;
struct sk_buff *skb = llc_alloc_frame();
struct sk_buff *nskb = llc_alloc_frame();
if (!skb)
if (!nskb)
goto out;
rc = 0;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 127);
lan_hdrs_init(skb, station->mac_sa, station->mac_sa);
llc_station_send_pdu(station, skb);
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);
lan_hdrs_init(nskb, station->mac_sa, station->mac_sa);
llc_station_send_pdu(station, nskb);
out:
return rc;
}
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;
int rc = 1;
struct sk_buff *ev_skb;
struct sk_buff* skb = llc_alloc_frame();
struct sk_buff* nskb = llc_alloc_frame();
if (!skb)
if (!nskb)
goto out;
rc = 0;
ev_skb = ev->data.pdu.skb;
skb->dev = ev_skb->dev;
llc_pdu_decode_sa(ev_skb, mac_da);
llc_pdu_decode_ssap(ev_skb, &dsap);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(skb, LLC_XID_NULL_CLASS_2, 127);
lan_hdrs_init(skb, station->mac_sa, mac_da);
llc_station_send_pdu(station, skb);
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
lan_hdrs_init(nskb, station->mac_sa, mac_da);
llc_station_send_pdu(station, nskb);
out:
return rc;
}
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;
int rc = 1;
struct sk_buff *ev_skb;
struct sk_buff *skb = llc_alloc_frame();
struct sk_buff *nskb = llc_alloc_frame();
if (!skb)
if (!nskb)
goto out;
rc = 0;
ev_skb = ev->data.pdu.skb;
skb->dev = ev_skb->dev;
llc_pdu_decode_sa(ev_skb, mac_da);
llc_pdu_decode_ssap(ev_skb, &dsap);
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(skb, ev_skb);
lan_hdrs_init(skb, station->mac_sa, mac_da);
llc_station_send_pdu(station, skb);
nskb->dev = skb->dev;
llc_pdu_decode_sa(skb, mac_da);
llc_pdu_decode_ssap(skb, &dsap);
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
llc_pdu_init_as_test_rsp(nskb, skb);
lan_hdrs_init(nskb, station->mac_sa, mac_da);
llc_station_send_pdu(station, nskb);
out:
return rc;
}
int llc_station_ac_report_status(struct llc_station *station,
struct llc_station_state_ev *ev)
struct sk_buff *skb)
{
return 0;
}
......@@ -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)
{
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;
ev = llc_station_alloc_ev(station);
if (ev) {
if (skb) {
struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
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 @@
static int llc_find_offset(int state, int ev_type);
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,
struct llc_conn_state_trans *trans,
struct llc_conn_state_ev *ev);
static struct llc_conn_state_trans *
llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev);
struct sk_buff *ev);
static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
struct sk_buff *skb);
/* Offset table on connection states transition diagram */
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
* @sk: connection
* @ev: occurred event
* @skb: occurred event
*
* Sends an event to connection state machine. after processing event
* (executing it's actions and changing state), upper layer will be
* indicated or confirmed, if needed. Returns 0 for success, 1 for
* 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 */
int rc = llc_conn_service(sk, ev);
int rc = llc_conn_service(sk, skb);
struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
u8 flag = ev->flag;
struct llc_prim_if_block *ind_prim = ev->ind_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
/* check if the connection was freed by the state machine by
* means of llc_conn_disc */
......@@ -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
* @sk: Active connection
* @skb: Received data frame
* @ev: Occurred event
*
* Sends received data pdu to upper layer (by using indicate function).
* Prepares service parameters (prim and prim_data). calling indication
* function will be done in llc_conn_send_ev.
*/
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb,
struct llc_conn_state_ev *ev)
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
......@@ -291,34 +271,37 @@ static void llc_conn_send_pdus(struct sock *sk)
/**
* llc_conn_free_ev - free event
* @ev: event to free
* @skb: event to free
*
* 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) {
/* free the frame that binded to this event */
struct llc_pdu_sn *pdu =
(struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
/* free the frame that is bound to this event */
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim)
kfree_skb(ev->data.pdu.skb);
}
/* free event structure to free list of the same */
kfree(ev);
kfree_skb(skb);
} else if (ev->type == LLC_CONN_EV_TYPE_PRIM &&
ev->data.prim.prim != LLC_DATA_PRIM)
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
* @sk: connection
* @ev: happened event
* @skb: happened event
*
* This function finds transition that matches with happened event, then
* executes related actions and finally changes state of connection.
* 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;
struct llc_conn_state_trans *trans;
......@@ -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)
goto out;
rc = 0;
trans = llc_qualify_conn_ev(sk, ev);
trans = llc_qualify_conn_ev(sk, skb);
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)
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)
/**
* llc_qualify_conn_ev - finds transition for event
* @sk: connection
* @ev: happened event
* @skb: happened event
*
* This function finds transition that matches with happened event.
* Returns pointer to found transition on success, %NULL otherwise.
*/
static struct llc_conn_state_trans *
llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev)
static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
struct sk_buff *skb)
{
struct llc_conn_state_trans **next_trans;
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 =
&llc_conn_state_table[llc_sk(sk)->state - 1];
&llc_conn_state_table[llc->state - 1];
/* search thru events for this state until
* list exhausted or until no more
*/
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++) {
if (!((*next_trans)->ev)(sk, ev)) {
if (!((*next_trans)->ev)(sk, skb)) {
/* got POSSIBLE event match; the event may require
* qualification based on the values of a number of
* state flags; if all qualifications are met (i.e.,
......@@ -367,7 +352,7 @@ static struct llc_conn_state_trans *
*/
for (next_qualifier = (*next_trans)->ev_qualifiers;
next_qualifier && *next_qualifier &&
!(*next_qualifier)(sk, ev); next_qualifier++)
!(*next_qualifier)(sk, skb); next_qualifier++)
/* nothing */;
if (!next_qualifier || !*next_qualifier)
/* all qualifiers executed successfully; this is
......@@ -384,7 +369,7 @@ static struct llc_conn_state_trans *
* llc_exec_conn_trans_actions - executes related actions
* @sk: connection
* @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
* success, 1 to indicate failure of at least one action or 2 if the
......@@ -392,14 +377,14 @@ static struct llc_conn_state_trans *
*/
static int llc_exec_conn_trans_actions(struct sock *sk,
struct llc_conn_state_trans *trans,
struct llc_conn_state_ev *ev)
struct sk_buff *skb)
{
int rc = 0;
llc_conn_action_t *next_action;
for (next_action = trans->ev_actions;
next_action && *next_action; next_action++) {
int rc2 = (*next_action)(sk, ev);
int rc2 = (*next_action)(sk, skb);
if (rc2 == 2) {
rc = rc2;
......
......@@ -24,39 +24,48 @@
#include <net/llc_pdu.h>
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 &&
ev->data.a.ev ==
LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
}
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 &&
ev->data.a.ev ==
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,
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 &&
station->retry_count < station->maximum_retry ? 0 : 1;
}
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 &&
station->retry_count == station->maximum_retry ? 0 : 1;
}
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 &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */
......@@ -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,
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 &&
!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,
}
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 &&
!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,
}
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 &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */
......@@ -103,9 +115,10 @@ int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
!pdu->dsap ? 0 : 1; /* NULL DSAP */
}
int llc_stat_ev_disable_req(struct llc_station *station,
struct llc_station_state_ev *ev)
int llc_stat_ev_disable_req(struct llc_station *station, struct sk_buff *skb)
{
struct llc_station_state_ev *ev = llc_station_ev(skb);
return ev->type == LLC_STATION_EV_TYPE_PRIM &&
ev->data.prim.prim == LLC_DISABLE_PRIM &&
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)
if (!sap)
goto out;
ev = llc_sap_alloc_ev(sap);
if (!ev)
goto out;
ev = llc_sap_ev(prim->data->udata.skb);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATAUNIT_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = 0;
llc_sap_send_ev(sap, ev);
llc_sap_send_ev(sap, prim->data->udata.skb);
out:
return rc;
}
......@@ -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);
if (!sap)
goto out;
ev = llc_sap_alloc_ev(sap);
if (!ev)
goto out;
ev = llc_sap_ev(prim->data->udata.skb);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_TEST_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = 0;
llc_sap_send_ev(sap, ev);
llc_sap_send_ev(sap, prim->data->udata.skb);
out:
return rc;
}
......@@ -225,15 +221,13 @@ static int llc_xid_req_handler(struct llc_prim_if_block *prim)
if (!sap)
goto out;
ev = llc_sap_alloc_ev(sap);
if (!ev)
goto out;
ev = llc_sap_ev(prim->data->udata.skb);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_XID_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = 0;
llc_sap_send_ev(sap, ev);
llc_sap_send_ev(sap, prim->data->udata.skb);
out:
return rc;
}
......@@ -273,29 +267,26 @@ static int llc_data_req_handler(struct llc_prim_if_block *prim)
llc->failed_data_req = 1;
goto out;
}
rc = -ENOMEM;
ev = llc_conn_alloc_ev(sk);
if (ev) {
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATA_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
prim->data->data.skb->dev = llc->dev;
rc = llc_conn_send_ev(sk, ev);
}
ev = llc_conn_ev(prim->data->data.skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATA_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
prim->data->data.skb->dev = llc->dev;
rc = llc_conn_send_ev(sk, prim->data->data.skb);
out:
release_sock(sk);
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.
*
* Informs upper layer about failing in connection establishment. This
* 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->sap->conf(prim);
......@@ -316,7 +307,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
int rc = -EBUSY;
struct llc_opt *llc;
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,
prim->data->conn.dev->type,
prim->data->conn.daddr.mac),
......@@ -334,7 +325,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
daddr.lsap = prim->data->conn.daddr.lsap;
sk = llc_find_sock(sap, &daddr, &laddr);
if (sk) {
confirm_impossible(prim);
llc_confirm_impossible(prim);
goto out_put;
}
rc = -ENOMEM;
......@@ -345,7 +336,7 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
} else {
sk = llc_sock_alloc();
if (!sk) {
confirm_impossible(prim);
llc_confirm_impossible(prim);
goto out;
}
prim->data->conn.sk = sk;
......@@ -360,18 +351,20 @@ static int llc_conn_req_handler(struct llc_prim_if_block *prim)
llc->dev = ddev;
llc->link = prim->data->conn.link;
llc->handler = prim->data->conn.handler;
ev = llc_conn_alloc_ev(sk);
if (ev) {
skb = alloc_skb(1, GFP_ATOMIC);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_CONN_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev);
rc = llc_conn_send_ev(sk, skb);
}
if (rc) {
llc_sap_unassign_sock(sap, sk);
llc_sock_free(sk);
confirm_impossible(prim);
llc_confirm_impossible(prim);
}
release_sock(sk);
out_put:
......@@ -393,6 +386,7 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim)
{
u16 rc = 1;
struct llc_conn_state_ev *ev;
struct sk_buff *skb;
struct sock* sk = prim->data->disc.sk;
sock_hold(sk);
......@@ -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 ||
llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
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
*/
ev = llc_conn_alloc_ev(sk);
if (!ev)
skb = alloc_skb(1, GFP_ATOMIC);
if (!skb)
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.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev);
rc = llc_conn_send_ev(sk, skb);
out:
release_sock(sk);
sock_put(sk);
......@@ -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)
{
struct sk_buff *skb;
int rc = 1;
struct sock *sk = prim->data->res.sk;
struct llc_conn_state_ev *ev;
lock_sock(sk);
ev = llc_conn_alloc_ev(sk);
if (ev) {
skb = alloc_skb(1, GFP_ATOMIC);
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
ev->type = LLC_CONN_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_RESET_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_REQ;
ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev);
rc = llc_conn_send_ev(sk, skb);
}
release_sock(sk);
return rc;
......@@ -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)
{
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
*/
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->data.prim.prim = LLC_RESET_PRIM;
ev->data.prim.type = LLC_PRIM_TYPE_RESP;
ev->data.prim.data = prim;
rc = llc_conn_send_ev(sk, ev);
rc = llc_conn_send_ev(sk, skb);
}
return rc;
}
......
......@@ -27,6 +27,12 @@
#include <net/llc_s_ev.h>
#include <linux/trdevice.h>
#if 1
#define dprintk(args...) printk(KERN_DEBUG args)
#else
#define dprintk(args...)
#endif
/* function prototypes */
static void fix_up_incoming_skb(struct sk_buff *skb);
......@@ -46,7 +52,7 @@ int mac_send_pdu(struct sk_buff *skb)
int pri = GFP_ATOMIC, rc = -1;
if (!skb->dev) {
printk(KERN_ERR "%s: skb->dev == NULL!", __FUNCTION__);
dprintk(KERN_ERR "%s: skb->dev == NULL!", __FUNCTION__);
goto out;
}
if (skb->sk)
......@@ -83,7 +89,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
* receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST) {
printk(KERN_INFO "%s: PACKET_OTHERHOST\n", __FUNCTION__);
dprintk(KERN_INFO "%s: PACKET_OTHERHOST\n", __FUNCTION__);
goto drop;
}
skb = skb_share_check(skb, GFP_ATOMIC);
......@@ -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,
LLC_TYPE_2);
} 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);
rc = 0;
}
......@@ -207,38 +214,27 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
if (!pdu->dsap) {
struct llc_station *station = llc_station_get();
struct llc_station_state_ev *stat_ev =
llc_station_alloc_ev(station);
if (stat_ev) {
stat_ev->type = LLC_STATION_EV_TYPE_PDU;
stat_ev->data.pdu.skb = skb;
stat_ev->data.pdu.reason = 0;
llc_station_send_ev(station, stat_ev);
} else
rc = -ENOMEM;
struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
llc_station_send_ev(station, skb);
} 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) {
sap_ev->type = LLC_SAP_EV_TYPE_PDU;
sap_ev->data.pdu.skb = skb;
sap_ev->data.pdu.reason = 0;
llc_sap_send_ev(sap, sap_ev);
} else
rc = -ENOMEM;
ev->type = LLC_SAP_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
llc_sap_send_ev(sap, skb);
} 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);
if (!llc->dev)
llc->dev = skb->dev;
if (conn_ev) {
conn_ev->type = LLC_CONN_EV_TYPE_PDU;
conn_ev->data.pdu.skb = skb;
conn_ev->data.pdu.reason = 0;
rc = llc_conn_send_ev(sk, conn_ev);
} else
rc = -ENOMEM;
ev->type = LLC_CONN_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
rc = llc_conn_send_ev(sk, skb);
} else
rc = -EINVAL;
return rc;
......
......@@ -38,16 +38,16 @@
/* static function prototypes */
static void llc_station_service_events(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 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,
struct llc_station_state_trans *trans,
struct llc_station_state_ev *ev);
struct sk_buff *skb);
static struct llc_station_state_trans *
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 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)
int rc = 0;
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 */
rc = llc_pdu_router(llc->sap, sk, skb, LLC_TYPE_2);
else
kfree_skb(skb);
} else if (skb->cb[0] == LLC_EVENT) {
struct llc_conn_state_ev *ev =
(struct llc_conn_state_ev *)skb->data;
} else if (llc_backlog_type(skb) == LLC_EVENT) {
/* timer expiration event */
if (llc->state > 1) /* not closed */
rc = llc_conn_send_ev(sk, ev);
rc = llc_conn_send_ev(sk, skb);
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);
}
return rc;
}
......@@ -232,9 +234,11 @@ void __llc_sock_free(struct sock *sk, u8 free)
/* stop all (possibly) running timers */
llc_conn_ac_stop_all_timers(sk, NULL);
/* handle return of frames on lists */
#if 0
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
skb_queue_len(&llc->pdu_unack_q),
skb_queue_len(&sk->write_queue));
#endif
skb_queue_purge(&sk->write_queue);
skb_queue_purge(&llc->pdu_unack_q);
if (free)
......@@ -315,35 +319,18 @@ struct llc_station *llc_station_get(void)
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.
* @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
* station state machine and attempts to process any queued-up events.
*/
void llc_station_send_ev(struct llc_station *station,
struct llc_station_state_ev *ev)
void llc_station_send_ev(struct llc_station *station, struct sk_buff *skb)
{
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);
spin_unlock_bh(&station->ev_q.lock);
}
......@@ -384,18 +371,17 @@ static void llc_station_send_pdus(struct llc_station *station)
/**
* llc_station_free_ev - frees an event
* @station: Address of the station
* @event: Address of the event
* @skb: Address of the event
*
* Frees an event.
*/
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)
kfree_skb(skb);
kfree(ev);
}
/**
......@@ -412,39 +398,35 @@ static void llc_station_free_ev(struct llc_station *station,
*/
static void llc_station_service_events(struct llc_station *station)
{
struct llc_station_state_ev *ev;
struct list_head *entry, *tmp;
struct sk_buff *skb;
list_for_each_safe(entry, tmp, &station->ev_q.list) {
ev = list_entry(entry, struct llc_station_state_ev, node);
list_del(&ev->node);
llc_station_next_state(station, ev);
}
while ((skb = skb_dequeue(&station->ev_q.list)) != NULL)
llc_station_next_state(station, skb);
}
/**
* llc_station_next_state - processes event and goes to the next state
* @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
* updates the state of the station.
*/
static u16 llc_station_next_state(struct llc_station *station,
struct llc_station_state_ev *ev)
struct sk_buff *skb)
{
u16 rc = 1;
struct llc_station_state_trans *trans;
if (station->state > LLC_NBR_STATION_STATES)
goto out;
trans = llc_find_station_trans(station, ev);
trans = llc_find_station_trans(station, 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(station, trans, ev);
rc = llc_exec_station_trans_actions(station, trans, skb);
if (!rc)
/* transition station to next state if all actions
* execute successfully; done; wait for next event
......@@ -456,22 +438,22 @@ static u16 llc_station_next_state(struct llc_station *station,
*/
rc = 0;
out:
llc_station_free_ev(station, ev);
llc_station_free_ev(station, skb);
return rc;
}
/**
* llc_find_station_trans - finds transition for this event
* @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
* 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 llc_station *station,
struct llc_station_state_ev *ev)
llc_find_station_trans(struct llc_station *station,
struct sk_buff *skb)
{
int i = 0;
struct llc_station_state_trans *rc = NULL;
......@@ -480,7 +462,7 @@ static struct llc_station_state_trans *
&llc_station_state_table[station->state - 1];
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];
break;
}
......@@ -491,21 +473,20 @@ static struct llc_station_state_trans *
* llc_exec_station_trans_actions - executes actions for transition
* @station: Address of the station
* @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
* 0 if all actions complete successfully, nonzero otherwise.
*/
static u16 llc_exec_station_trans_actions(struct llc_station *station,
struct llc_station_state_trans *trans,
struct llc_station_state_ev *ev)
struct sk_buff *skb)
{
u16 rc = 0;
llc_station_action_t *next_action;
llc_station_action_t *next_action = trans->ev_actions;
for (next_action = trans->ev_actions;
next_action && *next_action; next_action++)
if ((*next_action)(station, ev))
for (; next_action && *next_action; next_action++)
if ((*next_action)(station, skb))
rc = 1;
return rc;
}
......@@ -595,21 +576,24 @@ static char llc_error_msg[] __initdata =
static int __init llc_init(void)
{
u16 rc = 0;
struct sk_buff *skb;
struct llc_station_state_ev *ev;
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);
spin_lock_init(&llc_main_station.sap_list.lock);
skb_queue_head_init(&llc_main_station.mac_pdu_q);
ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev)
skb_queue_head_init(&llc_main_station.ev_q.list);
spin_lock_init(&llc_main_station.ev_q.lock);
skb = alloc_skb(1, GFP_ATOMIC);
if (!skb)
goto err;
llc_build_offset_table();
ev = llc_station_ev(skb);
memset(ev, 0, sizeof(*ev));
if(dev_base->next)
memcpy(llc_main_station.mac_sa, dev_base->next->dev_addr, ETH_ALEN);
if (dev_base->next)
memcpy(llc_main_station.mac_sa,
dev_base->next->dev_addr, ETH_ALEN);
else
memset(llc_main_station.mac_sa, 0, ETH_ALEN);
llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
......@@ -617,7 +601,7 @@ static int __init llc_init(void)
llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE;
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);
llc_ui_init();
dev_add_pack(&llc_packet_type);
......
This diff is collapsed.
......@@ -20,82 +20,96 @@
#include <net/llc_s_ev.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 &&
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) &&
!LLC_PDU_TYPE_IS_U(pdu) &&
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 &&
ev->data.prim.prim == LLC_DATAUNIT_PRIM &&
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 &&
ev->data.prim.prim == LLC_XID_PRIM &&
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) &&
!LLC_PDU_TYPE_IS_U(pdu) &&
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) &&
!LLC_PDU_TYPE_IS_U(pdu) &&
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 &&
ev->data.prim.prim == LLC_TEST_PRIM &&
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) &&
!LLC_PDU_TYPE_IS_U(pdu) &&
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) &&
!LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
}
int llc_sap_ev_deactivation_req(struct llc_sap *sap,
struct llc_sap_state_ev *ev)
int llc_sap_ev_deactivation_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 &&
ev->data.a.ev == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1;
}
......@@ -24,7 +24,7 @@
* last entry for this state
* 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
* LLC_SAP_EV_ACTIVATION_REQ event
......@@ -43,7 +43,7 @@ static struct llc_sap_state_trans llc_sap_inactive_state_trans_1 = {
/* array of pointers; one to each transition */
static struct llc_sap_state_trans *llc_sap_inactive_state_transitions[] = {
[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 */
......@@ -167,17 +167,17 @@ static struct llc_sap_state_trans *llc_sap_active_state_transitions[] = {
[6] = &llc_sap_active_state_trans_7,
[7] = &llc_sap_active_state_trans_8,
[8] = &llc_sap_active_state_trans_9,
[9] = &llc_sap_state_trans_n,
[9] = &llc_sap_state_trans_end,
};
/* SAP state transition table */
struct llc_sap_state llc_sap_state_table[] = {
{
.curr_state = LLC_SAP_STATE_INACTIVE,
.transitions = llc_sap_inactive_state_transitions,
struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES] = {
[LLC_SAP_STATE_INACTIVE - 1] = {
.curr_state = LLC_SAP_STATE_INACTIVE,
.transitions = llc_sap_inactive_state_transitions,
},
{
.curr_state = LLC_SAP_STATE_ACTIVE,
.transitions = llc_sap_active_state_transitions,
[LLC_SAP_STATE_ACTIVE - 1] = {
.curr_state = LLC_SAP_STATE_ACTIVE,
.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