o LLC: move the connection related functions to llc_conn

parent 06f3b6fd
......@@ -69,6 +69,16 @@ struct llc_opt {
#define llc_sk(__sk) ((struct llc_opt *)(__sk)->sk_protinfo)
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];
}
extern struct sock *llc_sk_alloc(int family, int priority);
extern void llc_sk_free(struct sock *sk);
......
......@@ -19,14 +19,4 @@
extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt);
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 */
......@@ -665,7 +665,7 @@ static int llc_find_offset(int state, int ev_type)
*
* Sends received pdus to the connection state machine.
*/
int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
{
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_opt *llc = llc_sk(sk);
......@@ -729,3 +729,222 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
drop:
kfree_skb(skb);
}
#undef LLC_REFCNT_DEBUG
#ifdef LLC_REFCNT_DEBUG
static atomic_t llc_sock_nr;
#endif
/**
* llc_release_conns - releases all connections of a sap
* @sap: sap to release its connections
*
* Releases all connections of a sap. Returns 0 if all actions complete
* successfully, nonzero otherwise
*/
int llc_release_connections(struct llc_sap *sap)
{
int rc = 0;
struct sock *sk;
struct hlist_node *node;
write_lock_bh(&sap->sk_list.lock);
sk_for_each(sk, node, &sap->sk_list.list) {
llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
if (llc_send_disc(sk))
rc = 1;
}
write_unlock_bh(&sap->sk_list.lock);
return rc;
}
/**
* llc_backlog_rcv - Processes rx frames and expired timers.
* @sk: LLC sock (p8022 connection)
* @skb: queued rx frame or event
*
* This function processes frames that has received and timers that has
* expired during sending an I pdu (refer to data_req_handler). frames
* queue by llc_rcv function (llc_mac.c) and timers queue by timer
* callback functions(llc_c_ac.c).
*/
static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
int rc = 0;
struct llc_opt *llc = llc_sk(sk);
if (llc_backlog_type(skb) == LLC_PACKET) {
if (llc->state > 1) /* not closed */
rc = llc_conn_rcv(sk, skb);
else
goto out_kfree_skb;
} else if (llc_backlog_type(skb) == LLC_EVENT) {
/* timer expiration event */
if (llc->state > 1) /* not closed */
rc = llc_conn_state_process(sk, skb);
else
goto out_kfree_skb;
} else {
printk(KERN_ERR "%s: invalid skb in backlog\n", __FUNCTION__);
goto out_kfree_skb;
}
out:
return rc;
out_kfree_skb:
kfree_skb(skb);
goto out;
}
/**
* llc_sk_init - Initializes a socket with default llc values.
* @sk: socket to initialize.
*
* Initializes a socket with default llc values.
*/
int llc_sk_init(struct sock* sk)
{
struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC);
int rc = -ENOMEM;
if (!llc)
goto out;
memset(llc, 0, sizeof(*llc));
rc = 0;
llc->sk = sk;
llc->state = LLC_CONN_STATE_ADM;
llc->inc_cntr = llc->dec_cntr = 2;
llc->dec_step = llc->connect_step = 1;
init_timer(&llc->ack_timer.timer);
llc->ack_timer.expire = LLC_ACK_TIME;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
init_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.expire = LLC_P_TIME;
llc->pf_cycle_timer.timer.data = (unsigned long)sk;
llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
init_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.expire = LLC_REJ_TIME;
llc->rej_sent_timer.timer.data = (unsigned long)sk;
llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
init_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.expire = LLC_BUSY_TIME;
llc->busy_state_timer.timer.data = (unsigned long)sk;
llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
llc->n2 = 2; /* max retransmit */
llc->k = 2; /* tx win size, will adjust dynam */
llc->rw = 128; /* rx win size (opt and equal to
* tx_win of remote LLC) */
skb_queue_head_init(&llc->pdu_unack_q);
sk->sk_backlog_rcv = llc_backlog_rcv;
llc_sk(sk) = llc;
out:
return rc;
}
/**
* llc_sk_alloc - Allocates LLC sock
* @family: upper layer protocol family
* @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
*
* Allocates a LLC sock and initializes it. Returns the new LLC sock
* or %NULL if there's no memory available for one
*/
struct sock *llc_sk_alloc(int family, int priority)
{
struct sock *sk = sk_alloc(family, priority, 1, NULL);
if (!sk)
goto out;
if (llc_sk_init(sk))
goto outsk;
sock_init_data(NULL, sk);
sk_set_owner(sk, THIS_MODULE);
#ifdef LLC_REFCNT_DEBUG
atomic_inc(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
__FUNCTION__, atomic_read(&llc_sock_nr));
#endif
out:
return sk;
outsk:
sk_free(sk);
sk = NULL;
goto out;
}
/**
* llc_sk_free - Frees a LLC socket
* @sk - socket to free
*
* Frees a LLC socket
*/
void llc_sk_free(struct sock *sk)
{
struct llc_opt *llc = llc_sk(sk);
llc->state = LLC_CONN_OUT_OF_SVC;
/* Stop all (possibly) running timers */
llc_conn_ac_stop_all_timers(sk, NULL);
#ifdef DEBUG_LLC_CONN_ALLOC
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
skb_queue_len(&llc->pdu_unack_q),
skb_queue_len(&sk->sk_write_queue));
#endif
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&llc->pdu_unack_q);
#ifdef LLC_REFCNT_DEBUG
if (atomic_read(&sk->sk_refcnt) != 1) {
printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
sk, __FUNCTION__, atomic_read(&sk->sk_refcnt));
printk(KERN_DEBUG "%d LLC sockets are still alive\n",
atomic_read(&llc_sock_nr));
} else {
atomic_dec(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
__FUNCTION__, atomic_read(&llc_sock_nr));
}
#endif
sock_put(sk);
}
/**
* llc_sk_reset - resets a connection
* @sk: LLC socket to reset
*
* Resets a connection to the out of service state. Stops its timers
* and frees any frames in the queues of the connection.
*/
void llc_sk_reset(struct sock *sk)
{
struct llc_opt *llc = llc_sk(sk);
llc_conn_ac_stop_all_timers(sk, NULL);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&llc->pdu_unack_q);
llc->remote_busy_flag = 0;
llc->cause_flag = 0;
llc->retry_count = 0;
llc_conn_set_p_flag(sk, 0);
llc->f_flag = 0;
llc->s_flag = 0;
llc->ack_pf = 0;
llc->first_pdu_Ns = 0;
llc->ack_must_be_send = 0;
llc->dec_step = 1;
llc->inc_cntr = 2;
llc->dec_cntr = 2;
llc->X = 0;
llc->failed_data_req = 0 ;
llc->last_nr = 0;
}
......@@ -43,15 +43,8 @@ static u16 llc_exec_station_trans_actions(struct llc_station *station,
static struct llc_station_state_trans *
llc_find_station_trans(struct llc_station *station,
struct sk_buff *skb);
static int llc_rtn_all_conns(struct llc_sap *sap);
struct llc_station llc_main_station; /* only one of its kind */
#undef LLC_REFCNT_DEBUG
#ifdef LLC_REFCNT_DEBUG
static atomic_t llc_sock_nr;
#endif
/**
* llc_sap_alloc - allocates and initializes sap.
*
......@@ -70,6 +63,12 @@ struct llc_sap *llc_sap_alloc(void)
return sap;
}
/*
* FIXME: this will go away as soon as sap->release_connections is introduced
* in the next changesets.
*/
extern int llc_release_connections(struct llc_sap *sap);
/**
* llc_free_sap - frees a sap
* @sap: Address of the sap
......@@ -79,7 +78,7 @@ struct llc_sap *llc_sap_alloc(void)
*/
void llc_free_sap(struct llc_sap *sap)
{
llc_rtn_all_conns(sap);
llc_release_connections(sap);
write_lock_bh(&sap->station->sap_list.lock);
list_del(&sap->node);
write_unlock_bh(&sap->station->sap_list.lock);
......@@ -123,225 +122,6 @@ struct llc_sap *llc_sap_find(u8 sap_value)
return sap;
}
/*
* FIXME: this will not be needed in next changesets, when this
* will move to llc_conn
*/
extern int llc_conn_rcv(struct sock* sk, struct sk_buff *skb);
/**
* llc_backlog_rcv - Processes rx frames and expired timers.
* @sk: LLC sock (p8022 connection)
* @skb: queued rx frame or event
*
* This function processes frames that has received and timers that has
* expired during sending an I pdu (refer to data_req_handler). frames
* queue by llc_rcv function (llc_mac.c) and timers queue by timer
* callback functions(llc_c_ac.c).
*/
static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
{
int rc = 0;
struct llc_opt *llc = llc_sk(sk);
if (llc_backlog_type(skb) == LLC_PACKET) {
if (llc->state > 1) /* not closed */
rc = llc_conn_rcv(sk, skb);
else
goto out_kfree_skb;
} else if (llc_backlog_type(skb) == LLC_EVENT) {
/* timer expiration event */
if (llc->state > 1) /* not closed */
rc = llc_conn_state_process(sk, skb);
else
goto out_kfree_skb;
} else {
printk(KERN_ERR "%s: invalid skb in backlog\n", __FUNCTION__);
goto out_kfree_skb;
}
out:
return rc;
out_kfree_skb:
kfree_skb(skb);
goto out;
}
/**
* llc_sk_init - Initializes a socket with default llc values.
* @sk: socket to initialize.
*
* Initializes a socket with default llc values.
*/
int llc_sk_init(struct sock* sk)
{
struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC);
int rc = -ENOMEM;
if (!llc)
goto out;
memset(llc, 0, sizeof(*llc));
rc = 0;
llc->sk = sk;
llc->state = LLC_CONN_STATE_ADM;
llc->inc_cntr = llc->dec_cntr = 2;
llc->dec_step = llc->connect_step = 1;
init_timer(&llc->ack_timer.timer);
llc->ack_timer.expire = LLC_ACK_TIME;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
init_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.expire = LLC_P_TIME;
llc->pf_cycle_timer.timer.data = (unsigned long)sk;
llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
init_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.expire = LLC_REJ_TIME;
llc->rej_sent_timer.timer.data = (unsigned long)sk;
llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
init_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.expire = LLC_BUSY_TIME;
llc->busy_state_timer.timer.data = (unsigned long)sk;
llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
llc->n2 = 2; /* max retransmit */
llc->k = 2; /* tx win size, will adjust dynam */
llc->rw = 128; /* rx win size (opt and equal to
* tx_win of remote LLC) */
skb_queue_head_init(&llc->pdu_unack_q);
sk->sk_backlog_rcv = llc_backlog_rcv;
llc_sk(sk) = llc;
out:
return rc;
}
/**
* llc_sk_alloc - Allocates LLC sock
* @family: upper layer protocol family
* @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
*
* Allocates a LLC sock and initializes it. Returns the new LLC sock
* or %NULL if there's no memory available for one
*/
struct sock *llc_sk_alloc(int family, int priority)
{
struct sock *sk = sk_alloc(family, priority, 1, NULL);
if (!sk)
goto out;
if (llc_sk_init(sk))
goto outsk;
sock_init_data(NULL, sk);
sk_set_owner(sk, THIS_MODULE);
#ifdef LLC_REFCNT_DEBUG
atomic_inc(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
__FUNCTION__, atomic_read(&llc_sock_nr));
#endif
out:
return sk;
outsk:
sk_free(sk);
sk = NULL;
goto out;
}
/**
* llc_sk_free - Frees a LLC socket
* @sk - socket to free
*
* Frees a LLC socket
*/
void llc_sk_free(struct sock *sk)
{
struct llc_opt *llc = llc_sk(sk);
llc->state = LLC_CONN_OUT_OF_SVC;
/* Stop all (possibly) running timers */
llc_conn_ac_stop_all_timers(sk, NULL);
#ifdef DEBUG_LLC_CONN_ALLOC
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
skb_queue_len(&llc->pdu_unack_q),
skb_queue_len(&sk->sk_write_queue));
#endif
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&llc->pdu_unack_q);
#ifdef LLC_REFCNT_DEBUG
if (atomic_read(&sk->sk_refcnt) != 1) {
printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
sk, __FUNCTION__, atomic_read(&sk->sk_refcnt));
printk(KERN_DEBUG "%d LLC sockets are still alive\n",
atomic_read(&llc_sock_nr));
} else {
atomic_dec(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
__FUNCTION__, atomic_read(&llc_sock_nr));
}
#endif
sock_put(sk);
}
/**
* llc_sk_reset - resets a connection
* @sk: LLC socket to reset
*
* Resets a connection to the out of service state. Stops its timers
* and frees any frames in the queues of the connection.
*/
void llc_sk_reset(struct sock *sk)
{
struct llc_opt *llc = llc_sk(sk);
llc_conn_ac_stop_all_timers(sk, NULL);
skb_queue_purge(&sk->sk_write_queue);
skb_queue_purge(&llc->pdu_unack_q);
llc->remote_busy_flag = 0;
llc->cause_flag = 0;
llc->retry_count = 0;
llc_conn_set_p_flag(sk, 0);
llc->f_flag = 0;
llc->s_flag = 0;
llc->ack_pf = 0;
llc->first_pdu_Ns = 0;
llc->ack_must_be_send = 0;
llc->dec_step = 1;
llc->inc_cntr = 2;
llc->dec_cntr = 2;
llc->X = 0;
llc->failed_data_req = 0 ;
llc->last_nr = 0;
}
/**
* llc_rtn_all_conns - Closes all connections of a sap
* @sap: sap to close its connections
*
* Closes all connections of a sap. Returns 0 if all actions complete
* successfully, nonzero otherwise
*/
static int llc_rtn_all_conns(struct llc_sap *sap)
{
int rc = 0;
struct sock *sk;
struct hlist_node *node;
write_lock_bh(&sap->sk_list.lock);
sk_for_each(sk, node, &sap->sk_list.list) {
llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
if (llc_send_disc(sk))
rc = 1;
}
write_unlock_bh(&sap->sk_list.lock);
return rc;
}
/**
* llc_station_state_process: queue event and try to process queue.
* @station: Address of the station
......
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