[LLC] llc_send_disc & LLC_DISC_PRIM bites the dust

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