[LLC] llc_send_disc & LLC_DISC_PRIM bites the dust

parent 72826210
......@@ -65,13 +65,6 @@ struct llc_addr {
u8 mac[IFHWADDRLEN];
};
/* Primitive-specific data */
struct llc_prim_disc {
struct sock *sk;
u16 link;
u8 reason; /* not used by request */
};
struct llc_prim_reset {
struct sock *sk;
u16 link;
......@@ -108,7 +101,6 @@ struct llc_prim_test {
};
union llc_u_prim_data {
struct llc_prim_disc disc;
struct llc_prim_reset res;
struct llc_prim_flow_ctrl fc;
struct llc_prim_unit_data udata; /* unit data */
......@@ -133,4 +125,5 @@ extern void llc_sap_close(struct llc_sap *sap);
extern int llc_establish_connection(struct sock *sk, u8 *lmac,
u8 *dmac, u8 dsap);
extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
extern int llc_send_disc(struct sock *sk);
#endif /* LLC_IF_H */
......@@ -134,19 +134,15 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
rc = 1;
}
if (!rc) {
struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap;
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->disc.sk = sk;
prim_data->disc.reason = reason;
prim_data->disc.link = llc->link;
prim->data = prim_data;
prim->prim = LLC_DISC_PRIM;
prim->sap = llc->sap;
ev->flag = 1;
ev->ind_prim = prim;
/*
* FIXME: ev needs reason field,
* perhaps the ev->status is enough,
* have to check,
* better way to signal its a disc
*/
/* prim_data->disc.reason = reason; */
ev->flag = LLC_DISC_PRIM + 1;
ev->ind_prim = (void *)1;
}
return rc;
}
......@@ -154,19 +150,11 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_disc_confirm(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_cfm_prim;
union llc_u_prim_data *prim_data = prim->data;
prim_data->disc.sk = sk;
prim_data->disc.reason = ev->status;
prim_data->disc.link = llc->link;
prim->data = prim_data;
prim->prim = LLC_DISC_PRIM;
prim->sap = sap;
ev->flag = 1;
ev->cfm_prim = prim;
/* here we use the ev->status, humm */
/* prim_data->disc.reason = ev->status; */
ev->flag = LLC_DISC_PRIM + 1;
ev->cfm_prim = (void *)1;
return 0;
}
......
......@@ -60,9 +60,10 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
struct llc_prim_if_block *cfm_prim = ev->cfm_prim;
/*
* FIXME: this will vanish as soon I get rid of the double sock crap
* FIXME: this will vanish as soon I get rid of the last prim crap
*/
if (flag != LLC_DATA_PRIM + 1 && flag != LLC_CONN_PRIM + 1)
if (flag != LLC_DATA_PRIM + 1 && flag != LLC_CONN_PRIM + 1 &&
flag != LLC_DISC_PRIM + 1)
llc_conn_free_ev(skb);
else if (ind_prim && cfm_prim)
skb_get(skb);
......@@ -76,7 +77,7 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
*/
switch (flag) {
case LLC_DATA_PRIM + 1:
if (sock_queue_rcv_skb(skb->sk, skb)) {
if (sock_queue_rcv_skb(sk, skb)) {
/*
* FIXME: have to sync the LLC state
* machine wrt mem usage with
......@@ -97,17 +98,35 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
sk->state_change(parent);
}
break;
case LLC_DISC_PRIM + 1:
sock_hold(sk);
if (sk->type == SOCK_STREAM && sk->state == TCP_ESTABLISHED) {
sk->shutdown = SHUTDOWN_MASK;
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
if (!sk->dead) {
sk->state_change(sk);
sk->dead = 1;
}
}
sock_put(sk);
break;
default:
llc->sap->ind(ind_prim);
}
}
if (!cfm_prim) /* confirmation not required */
goto out;
/* data and conn confirm have preconditions */
/* FIXME: see FIXMEs above */
if (flag == LLC_CONN_PRIM + 1) {
struct sock *sk = skb->sk;
switch (flag) {
case LLC_DATA_PRIM + 1:
if (!llc_data_accept_state(llc->state))
/* In this state, we can send I pdu */
sk->write_space(sk);
else
rc = llc->failed_data_req = 1;
break;
case LLC_CONN_PRIM + 1:
if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT)
goto out_kfree_skb;
if (ev->status) {
......@@ -118,17 +137,22 @@ int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
sk->state = TCP_ESTABLISHED;
}
sk->state_change(sk);
goto out_kfree_skb;
} else if (flag != LLC_DATA_PRIM + 1) {
break;
case LLC_DISC_PRIM + 1:
sock_hold(sk);
if (sk->type != SOCK_STREAM || sk->state != TCP_CLOSING) {
sock_put(sk);
goto out_kfree_skb;
}
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
sk->state_change(sk);
sock_put(sk);
break;
default:
llc->sap->conf(cfm_prim);
goto out;
}
if (!llc_data_accept_state(llc->state)) {
/* In this state, we can send I pdu */
if (skb->sk)
skb->sk->write_space(skb->sk);
} else
rc = llc->failed_data_req = 1;
out_kfree_skb:
kfree_skb(skb);
out:
......
......@@ -32,16 +32,15 @@ static int llc_sap_req(struct llc_prim_if_block *prim);
static int llc_unitdata_req_handler(struct llc_prim_if_block *prim);
static int llc_test_req_handler(struct llc_prim_if_block *prim);
static int llc_xid_req_handler(struct llc_prim_if_block *prim);
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_flowcontrol_req_handler(struct llc_prim_if_block *prim);
/* table of request handler functions */
static llc_prim_call_t llc_req_prim[LLC_NBR_PRIMITIVES] = {
[LLC_DATAUNIT_PRIM] = llc_unitdata_req_handler,
[LLC_CONN_PRIM] = NULL, /* replaced by + llc_establish_connection */
[LLC_CONN_PRIM] = NULL, /* replaced by llc_establish_connection */
[LLC_DATA_PRIM] = NULL, /* replaced by llc_build_and_send_pkt */
[LLC_DISC_PRIM] = llc_disc_req_handler,
[LLC_DISC_PRIM] = NULL, /* replaced by llc_send_disc */
[LLC_RESET_PRIM] = llc_rst_req_handler,
[LLC_FLOWCONTROL_PRIM] = llc_flowcontrol_req_handler,
[LLC_XID_PRIM] = llc_xid_req_handler,
......@@ -307,23 +306,23 @@ int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
}
/**
* llc_disc_req_handler - Called by upper layer to close a connection
* @prim: pointer to structure that contains service parameters.
* llc_send_disc - Called by upper layer to close a connection
* @sk: connection to be closed
*
* Upper layer calls this when it wants to close an established LLC
* connection with a remote machine. This function packages a proper event
* and sends it to connection component state machine. Returns 0 for
* success, 1 otherwise.
*/
static int llc_disc_req_handler(struct llc_prim_if_block *prim)
int llc_send_disc(struct sock *sk)
{
u16 rc = 1;
struct llc_conn_state_ev *ev;
struct sk_buff *skb;
struct sock* sk = prim->data->disc.sk;
sock_hold(sk);
if (llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED ||
llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
goto out;
/*
......@@ -333,11 +332,12 @@ static int llc_disc_req_handler(struct llc_prim_if_block *prim)
skb = alloc_skb(0, GFP_ATOMIC);
if (!skb)
goto out;
ev = llc_conn_ev(skb);
sk->state = TCP_CLOSING;
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;
ev->data.prim.data = NULL;
rc = llc_conn_state_process(sk, skb);
out:
sock_put(sk);
......
......@@ -315,8 +315,6 @@ void llc_sk_reset(struct sock *sk)
static int llc_rtn_all_conns(struct llc_sap *sap)
{
int rc = 0;
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct list_head *entry, *tmp;
spin_lock_bh(&sap->sk_list.lock);
......@@ -325,12 +323,8 @@ static int llc_rtn_all_conns(struct llc_sap *sap)
list_for_each_safe(entry, tmp, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
prim.sap = sap;
prim_data.disc.sk = llc->sk;
prim.prim = LLC_DISC_PRIM;
prim.data = &prim_data;
llc->state = LLC_CONN_STATE_TEMP;
if (sap->req(&prim))
if (llc_send_disc(llc->sk))
rc = 1;
}
out:
......
......@@ -124,36 +124,6 @@ static __inline__ u8 llc_ui_header_len(struct sock *sk,
return rc;
}
/**
* llc_ui_send_disc - send disc command to llc layer
* @sk: Socket with valid llc information.
*
* Send a disconnect command to the llc layer for an established
* llc2 connection.
* Returns 0 upon success, non-zero if action did not succeed.
*/
static int llc_ui_send_disc(struct sock *sk)
{
struct llc_opt *llc = llc_sk(sk);
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
int rc = 0;
if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) {
rc = 1;
goto out;
}
sk->state = TCP_CLOSING;
prim.data = &prim_data;
prim.sap = llc->sap;
prim.prim = LLC_DISC_PRIM;
prim_data.disc.sk = sk;
prim_data.disc.link = llc->link;
rc = llc->sap->req(&prim);
out:
return rc;
}
/**
* llc_ui_send_data - send data via reliable llc2 connection
* @sk: Connection the socket is using.
......@@ -424,7 +394,7 @@ static int llc_ui_release(struct socket *sock)
llc = llc_sk(sk);
dprintk("%s: closing local(%02X) remote(%02X)\n", __FUNCTION__,
llc->laddr.lsap, llc->daddr.lsap);
if (!llc_ui_send_disc(sk))
if (!llc_send_disc(sk))
llc_ui_wait_for_disc(sk, sk->rcvtimeo);
llc_sap_unassign_sock(llc->sap, sk);
release_sock(sk);
......@@ -614,7 +584,7 @@ static int llc_ui_shutdown(struct socket *sock, int how)
rc = -EINVAL;
if (how != 2)
goto out;
rc = llc_ui_send_disc(sk);
rc = llc_send_disc(sk);
if (!rc)
rc = llc_ui_wait_for_disc(sk, sk->rcvtimeo);
/* Wake up anyone sleeping in poll */
......@@ -1348,33 +1318,6 @@ static void llc_ui_ind_dataunit(struct llc_prim_if_block *prim)
out:;
}
/**
* llc_ui_ind_disc - handle DISC indication
* @prim: Primitive block provided by the llc layer.
*
* handle DISC indication.
*/
static void llc_ui_ind_disc(struct llc_prim_if_block *prim)
{
struct llc_prim_disc *prim_data = &prim->data->disc;
struct sock* sk = prim_data->sk;
sock_hold(sk);
if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED) {
dprintk("%s: bad socket...\n", __FUNCTION__);
goto out_put;
}
sk->shutdown = SHUTDOWN_MASK;
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
if (!sk->dead) {
sk->state_change(sk);
sk->dead = 1;
}
out_put:
sock_put(sk);
}
/**
* llc_ui_indicate - LLC user interface hook into the LLC layer.
* @prim: Primitive block provided by the llc layer.
......@@ -1401,7 +1344,9 @@ static int llc_ui_indicate(struct llc_prim_if_block *prim)
"is gone for ->ind()...\n", __FUNCTION__);
break;
case LLC_DISC_PRIM:
llc_ui_ind_disc(prim); break;
dprintk("%s: shouldn't happen, LLC_DISC_PRIM "
"is gone for ->ind()...\n", __FUNCTION__);
break;
case LLC_RESET_PRIM:
case LLC_FLOWCONTROL_PRIM:
default: break;
......@@ -1409,27 +1354,6 @@ static int llc_ui_indicate(struct llc_prim_if_block *prim)
return 0;
}
/**
* llc_ui_conf_disc - handle DISC confirm.
* @prim: Primitive block provided by the llc layer.
*
* handle DISC confirm.
*/
static void llc_ui_conf_disc(struct llc_prim_if_block *prim)
{
struct llc_prim_disc *prim_data = &prim->data->disc;
struct sock* sk = prim_data->sk;
sock_hold(sk);
if (sk->type != SOCK_STREAM || sk->state != TCP_CLOSING)
goto out_put;
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
sk->state_change(sk);
out_put:
sock_put(sk);
}
/**
* llc_ui_confirm - LLC user interface hook into the LLC layer
* @prim: Primitive block provided by the llc layer.
......@@ -1450,10 +1374,12 @@ static int llc_ui_confirm(struct llc_prim_if_block *prim)
"is gone for ->conf()...\n", __FUNCTION__);
break;
case LLC_DISC_PRIM:
llc_ui_conf_disc(prim); break;
dprintk("%s: shouldn't happen, LLC_DISC_PRIM "
"is gone for ->conf()...\n", __FUNCTION__);
break;
case LLC_RESET_PRIM: break;
default:
printk(KERN_ERR "%s: unknown prim %d\n", __FUNCTION__,
printk(KERN_ERR "%s: prim not supported%d\n", __FUNCTION__,
prim->prim);
break;
}
......
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