Commit ad2bce43 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Linus Torvalds

[LLC] remove all tmr ev structs & fix psnap and p8022 wrt ui sending

. No need for the timer_running member on llc_timer,
  we only need it in one place, and timer_pending is
  equivalent. One more procom OS generalisation killed.
. Move the skb->protocol assignment in llc_build_and_send_pkt
  routines and llc_ui_send_data to the caller, this is the common
  practice in Linux networking code (think netif_rx) and required
  to keep the request functions in psnap and p8022 simple.
. Remove the rpt_status (report status) ev members, not
  used at all, not even in the original procom code.
. Convert psnap and p8022 request functions to use
  llc_ui_build_and_send_ui_pkt, removing all the prim cruft.
parent acf7aa2c
......@@ -122,27 +122,14 @@ struct llc_conn_ev_prim_if {
/* Event LLC_CONN_EV_TYPE_PDU interface */
struct llc_conn_ev_pdu_if {
u8 ev;
u8 reason;
};
/* Event interface for timer-generated events */
struct llc_conn_ev_tmr_if {
struct sock *sk;
u32 component_handle;
void *timer_specific;
};
struct llc_conn_ev_rpt_sts_if {
u8 status;
u8 ev;
u8 reason;
};
union llc_conn_ev_if {
struct llc_conn_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_conn_ev_prim_if prim;
struct llc_conn_ev_pdu_if pdu;
struct llc_conn_ev_tmr_if tmr;
struct llc_conn_ev_rpt_sts_if rsts; /* report status */
};
struct llc_conn_state_ev {
......
......@@ -17,7 +17,6 @@
struct llc_timer {
struct timer_list timer;
u8 running; /* timer is running or no */
u16 expire; /* timer expire time */
};
......
......@@ -43,29 +43,18 @@ struct llc_stat_ev_prim_if {
struct llc_stat_ev_pdu_if {
u8 reason;
struct sk_buff *skb;
};
struct llc_stat_ev_tmr_if {
void *timer_specific;
};
struct llc_stat_ev_rpt_sts_if {
u8 status;
};
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_rpt_sts_if rsts; /* report status */
};
struct llc_station_state_ev {
u8 type;
u8 type;
union llc_stat_ev_if data;
struct list_head node; /* node in station->ev_q.list */
struct list_head node; /* node in station->ev_q.list */
};
static __inline__ struct llc_station_state_ev *
......
......@@ -122,24 +122,12 @@ extern int llc_establish_connection(struct sock *sk, u8 *lmac,
extern int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb);
extern void llc_build_and_send_ui_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr);
u8 *dmac, u8 dsap);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr);
u8 *dmac, u8 dsap);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr);
u8 *dmac, u8 dsap);
extern int llc_send_disc(struct sock *sk);
/**
* llc_proto_type - return eth protocol for ARP header type
* @arphrd: ARP header type.
*
* Given an ARP header type return the corresponding ethernet protocol.
*/
static __inline__ u16 llc_proto_type(u16 arphrd)
{
return arphrd == ARPHRD_IEEE802_TR ?
htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
}
#endif /* LLC_IF_H */
......@@ -30,7 +30,6 @@
*
* @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.
......@@ -40,7 +39,6 @@ struct llc_station {
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];
......
......@@ -52,20 +52,10 @@ struct llc_sap_ev_pdu_if {
u8 reason;
};
struct llc_sap_ev_tmr_if {
void *timer_specific;
};
struct llc_sap_ev_rpt_sts_if {
u8 status;
};
union llc_sap_ev_if {
struct llc_sap_ev_simple_if a; /* 'a' for simple, easy ... */
struct llc_sap_ev_prim_if prim;
struct llc_sap_ev_pdu_if pdu;
struct llc_sap_ev_tmr_if tmr;
struct llc_sap_ev_rpt_sts_if rsts; /* report status */
};
struct llc_prim_if_block;
......
......@@ -17,7 +17,6 @@
*
* @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used
* @req - provided by LLC layer
* @ind - provided by network layer
* @conf - provided by network layer
* @laddr - SAP value in this 'lsap'
......@@ -30,7 +29,6 @@ struct llc_sap {
u8 state;
u8 p_bit;
u8 f_bit;
llc_prim_call_t req;
llc_prim_call_t ind;
llc_prim_call_t conf;
struct llc_prim_if_block llc_ind_prim, llc_cfm_prim;
......
......@@ -28,18 +28,8 @@
static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
unsigned char *dest)
{
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
prim.data = &prim_data;
prim.sap = dl->sap;
prim.prim = LLC_DATAUNIT_PRIM;
prim_data.test.skb = skb;
prim_data.test.saddr.lsap = dl->sap->laddr.lsap;
prim_data.test.daddr.lsap = dl->sap->laddr.lsap;
memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, dest, IFHWADDRLEN);
return dl->sap->req(&prim);
llc_build_and_send_ui_pkt(dl->sap, skb, dest, dl->sap->laddr.lsap);
return 0;
}
struct datalink_proto *register_8022_client(unsigned char type,
......
......@@ -86,19 +86,9 @@ static int snap_indicate(struct llc_prim_if_block *prim)
static int snap_request(struct datalink_proto *dl,
struct sk_buff *skb, u8 *dest)
{
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
memcpy(skb_push(skb, 5), dl->type, 5);
prim.data = &prim_data;
prim.sap = snap_sap;
prim.prim = LLC_DATAUNIT_PRIM;
prim_data.test.skb = skb;
prim_data.test.saddr.lsap = snap_sap->laddr.lsap;
prim_data.test.daddr.lsap = snap_sap->laddr.lsap;
memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, dest, IFHWADDRLEN);
return snap_sap->req(&prim);
llc_build_and_send_ui_pkt(snap_sap, skb, dest, snap_sap->laddr.lsap);
return 0;
}
/*
......
......@@ -34,7 +34,6 @@ int llc_station_ac_start_ack_timer(struct llc_station *station,
station->ack_timer.data = (unsigned long)station;
station->ack_timer.function = llc_station_ack_tmr_callback;
add_timer(&station->ack_timer);
station->ack_tmr_running = 1;
return 0;
}
......@@ -136,12 +135,10 @@ static void llc_station_ack_tmr_callback(unsigned long timeout_data)
struct llc_station *station = (struct llc_station *)timeout_data;
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
station->ack_tmr_running = 0;
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_state_process(station, skb);
}
}
......@@ -48,7 +48,6 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
llc->remote_busy_flag = 0;
del_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.running = 0;
nr = LLC_I_GET_NR(pdu);
llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
}
......@@ -252,10 +251,8 @@ int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
{
struct llc_opt *llc = llc_sk(sk);
if (llc->data_flag == 2) {
if (llc->data_flag == 2)
del_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.running = 0;
}
return 0;
}
......@@ -672,7 +669,6 @@ int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
llc->busy_state_timer.timer.data = (unsigned long)sk;
llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
add_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.running = 1;
}
return 0;
}
......@@ -915,7 +911,6 @@ int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
llc->pf_cycle_timer.timer.data = (unsigned long)sk;
llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
add_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.running = 1;
return 0;
}
......@@ -1162,13 +1157,9 @@ int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb)
struct llc_opt *llc = llc_sk(sk);
del_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.running = 0;
del_timer(&llc->ack_timer.timer);
llc->ack_timer.running = 0;
del_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.running = 0;
del_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.running = 0;
llc->ack_must_be_send = 0;
llc->ack_pf = 0;
return 0;
......@@ -1179,11 +1170,8 @@ int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb)
struct llc_opt *llc = llc_sk(sk);
del_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.running = 0;
del_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.running = 0;
del_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.running = 0;
llc->ack_must_be_send = 0;
llc->ack_pf = 0;
return 0;
......@@ -1198,7 +1186,6 @@ int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
add_timer(&llc->ack_timer.timer);
llc->ack_timer.running = 1;
return 0;
}
......@@ -1212,7 +1199,6 @@ int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
llc->rej_sent_timer.timer.data = (unsigned long)sk;
llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
add_timer(&llc->rej_sent_timer.timer);
llc->rej_sent_timer.running = 1;
return 0;
}
......@@ -1221,13 +1207,12 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
{
struct llc_opt *llc = llc_sk(sk);
if (!llc->ack_timer.running) {
if (!timer_pending(&llc->ack_timer.timer)) {
llc->ack_timer.timer.expires = jiffies +
llc->ack_timer.expire * HZ;
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
add_timer(&llc->ack_timer.timer);
llc->ack_timer.running = 1;
}
return 0;
}
......@@ -1235,7 +1220,6 @@ int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb)
{
del_timer(&llc_sk(sk)->ack_timer.timer);
llc_sk(sk)->ack_timer.running = 0;
return 0;
}
......@@ -1244,7 +1228,6 @@ int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb)
struct llc_opt *llc = llc_sk(sk);
del_timer(&llc->pf_cycle_timer.timer);
llc->pf_cycle_timer.running = 0;
llc->p_flag = 0;
return 0;
}
......@@ -1252,7 +1235,6 @@ int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb)
{
del_timer(&llc_sk(sk)->rej_sent_timer.timer);
llc_sk(sk)->rej_sent_timer.running = 0;
return 0;
}
......@@ -1270,7 +1252,6 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) {
llc->retry_count = 0;
del_timer(&llc->ack_timer.timer);
llc->ack_timer.running = 0;
if (llc->failed_data_req) {
/* already, we did not accept data from upper layer
* (tx_window full or unacceptable state). Now, we
......@@ -1285,7 +1266,6 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
llc->ack_timer.timer.data = (unsigned long)sk;
llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
add_timer(&llc->ack_timer.timer);
llc->ack_timer.running = 1;
}
} else if (llc->failed_data_req) {
llc_pdu_decode_pf_bit(skb, &fbit);
......@@ -1423,13 +1403,11 @@ void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->pf_cycle_timer.running = 0;
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_P_TMR;
ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb);
}
bh_unlock_sock(sk);
......@@ -1441,13 +1419,11 @@ static void llc_conn_busy_tmr_cb(unsigned long timeout_data)
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->busy_state_timer.running = 0;
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_BUSY_TMR;
ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb);
}
bh_unlock_sock(sk);
......@@ -1459,13 +1435,11 @@ void llc_conn_ack_tmr_cb(unsigned long timeout_data)
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->ack_timer.running = 0;
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_ACK_TMR;
ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb);
}
bh_unlock_sock(sk);
......@@ -1477,13 +1451,11 @@ static void llc_conn_rej_tmr_cb(unsigned long timeout_data)
struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->rej_sent_timer.running = 0;
if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_REJ_TMR;
ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb);
}
bh_unlock_sock(sk);
......
......@@ -86,7 +86,8 @@ void llc_sap_close(struct llc_sap *sap)
* llc_build_and_send_ui_pkt - unitdata request interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @addr: destination address
* @dmac: destination mac address
* @dsap: destination sap
*
* Upper layers calls this function when upper layer wants to send data
* using connection-less mode communication (UI pdu).
......@@ -95,25 +96,22 @@ void llc_sap_close(struct llc_sap *sap)
* less mode communication; timeout/retries handled by network layer;
* package primitive as an event and send to SAP event handler
*/
void llc_build_and_send_ui_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr)
void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap)
{
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
skb->protocol = llc_proto_type(addr->sllc_arphrd);
prim.data = &prim_data;
prim.sap = sap;
prim.prim = LLC_DATAUNIT_PRIM;
prim_data.udata.skb = skb;
prim_data.udata.saddr.lsap = sap->laddr.lsap;
prim_data.udata.daddr.lsap = addr->sllc_dsap;
prim_data.udata.daddr.lsap = dsap;
memcpy(prim_data.udata.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.udata.daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
memcpy(prim_data.udata.daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_DATAUNIT_PRIM;
......@@ -126,30 +124,28 @@ void llc_build_and_send_ui_pkt(struct llc_sap *sap,
* llc_build_and_send_test_pkt - TEST interface for upper layers.
* @sap: sap to use
* @skb: packet to send
* @addr: destination address
* @dmac: destination mac address
* @dsap: destination sap
*
* This function is called when upper layer wants to send a TEST pdu.
* Returns 0 for success, 1 otherwise.
*/
void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr)
void llc_build_and_send_test_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap)
{
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
skb->protocol = llc_proto_type(addr->sllc_arphrd);
prim.data = &prim_data;
prim.sap = sap;
prim.prim = LLC_TEST_PRIM;
prim_data.test.skb = skb;
prim_data.test.saddr.lsap = sap->laddr.lsap;
prim_data.test.daddr.lsap = addr->sllc_dsap;
prim_data.test.daddr.lsap = dsap;
memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
memcpy(prim_data.test.daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_TEST_PRIM;
......@@ -162,30 +158,28 @@ void llc_build_and_send_test_pkt(struct llc_sap *sap,
* llc_build_and_send_xid_pkt - XID interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @addr: destination address
* @dmac: destination mac address
* @dsap: destination sap
*
* This function is called when upper layer wants to send a XID pdu.
* Returns 0 for success, 1 otherwise.
*/
void llc_build_and_send_xid_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr)
void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap)
{
union llc_u_prim_data prim_data;
struct llc_prim_if_block prim;
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
skb->protocol = llc_proto_type(addr->sllc_arphrd);
prim.data = &prim_data;
prim.sap = sap;
prim.prim = LLC_XID_PRIM;
prim_data.xid.skb = skb;
prim_data.xid.saddr.lsap = sap->laddr.lsap;
prim_data.xid.daddr.lsap = addr->sllc_dsap;
prim_data.xid.daddr.lsap = dsap;
memcpy(prim_data.xid.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(prim_data.xid.daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
memcpy(prim_data.xid.daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->data.prim.prim = LLC_XID_PRIM;
......@@ -196,7 +190,8 @@ void llc_build_and_send_xid_pkt(struct llc_sap *sap,
/**
* llc_build_and_send_pkt - Connection data sending for upper layers.
* @prim: pointer to structure that contains service parameters
* @sk: connection
* @skb: packet to send
*
* This function is called when upper layer wants to send data using
* connection oriented communication mode. During sending data, connection
......@@ -352,3 +347,4 @@ int llc_build_and_send_reset_pkt(struct sock *sk,
EXPORT_SYMBOL(llc_sap_open);
EXPORT_SYMBOL(llc_sap_close);
EXPORT_SYMBOL(llc_build_and_send_ui_pkt);
......@@ -78,9 +78,6 @@ void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
sap->ind(ev->prim);
else if (ev->type == LLC_SAP_EV_TYPE_PDU)
kfree_skb(skb);
else
printk(KERN_INFO ":%s !kfree_skb & it is %s in a list\n",
__FUNCTION__, skb->list ? "" : "NOT");
}
/**
......
......@@ -77,6 +77,18 @@ static __inline__ u16 llc_ui_next_link_no(int sap)
return llc_ui_sap_link_no_max[sap]++;
}
/**
* llc_proto_type - return eth protocol for ARP header type
* @arphrd: ARP header type.
*
* Given an ARP header type return the corresponding ethernet protocol.
*/
static __inline__ u16 llc_proto_type(u16 arphrd)
{
return arphrd == ARPHRD_IEEE802_TR ?
htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
}
/**
* llc_ui_addr_null - determines if a address structure is null
* @addr: Address to test if null.
......@@ -117,13 +129,11 @@ static __inline__ u8 llc_ui_header_len(struct sock *sk,
* Send data via reliable llc2 connection.
* Returns 0 upon success, non-zero if action did not succeed.
*/
static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb,
struct sockaddr_llc *addr, int noblock)
static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
{
struct llc_opt* llc = llc_sk(sk);
int rc = 0;
skb->protocol = llc_proto_type(addr->sllc_arphrd);
if (llc_data_accept_state(llc->state) || llc->p_flag) {
int timeout = sock_sndtimeo(sk, noblock);
......@@ -940,28 +950,32 @@ static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len,
skb = sock_alloc_send_skb(sk, size, noblock, &rc);
if (!skb)
goto release;
skb->sk = sk;
skb->dev = dev;
skb->sk = sk;
skb->dev = dev;
skb->protocol = llc_proto_type(addr->sllc_arphrd);
skb_reserve(skb, dev->hard_header_len + llc_ui_header_len(sk, addr));
rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
if (rc)
goto out;
if (addr->sllc_test) {
llc_build_and_send_test_pkt(llc->sap, skb, addr);
llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_dmac,
addr->sllc_dsap);
goto out;
}
if (addr->sllc_xid) {
llc_build_and_send_xid_pkt(llc->sap, skb, addr);
llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_dmac,
addr->sllc_dsap);
goto out;
}
if (sk->type == SOCK_DGRAM || addr->sllc_ua) {
llc_build_and_send_ui_pkt(llc->sap, skb, addr);
llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_dmac,
addr->sllc_dsap);
goto out;
}
rc = -ENOPROTOOPT;
if (!(sk->type == SOCK_STREAM && !addr->sllc_ua))
goto out;
rc = llc_ui_send_data(sk, skb, addr, noblock);
rc = llc_ui_send_data(sk, skb, noblock);
if (rc)
dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc);
out:
......
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