Commit 2aceaa81 authored by David S. Miller's avatar David S. Miller

Merge master.kernel.org:/home/acme/BK/llc-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents c5c44cfd 0284d996
......@@ -70,8 +70,6 @@ struct llc_opt {
#define llc_sk(__sk) ((struct llc_opt *)(__sk)->protinfo)
struct llc_conn_state_ev;
extern struct sock *llc_sk_alloc(int family, int priority);
extern void llc_sk_free(struct sock *sk);
......
......@@ -43,7 +43,7 @@ struct llc_station {
u8 maximum_retry;
u8 mac_sa[6];
struct {
spinlock_t lock;
rwlock_t lock;
struct list_head list;
} sap_list;
struct {
......@@ -52,7 +52,6 @@ struct llc_station {
} ev_q;
struct sk_buff_head mac_pdu_q;
};
struct llc_station_state_ev;
extern struct llc_sap *llc_sap_alloc(void);
extern void llc_sap_save(struct llc_sap *sap);
......
......@@ -16,32 +16,29 @@
/**
* struct llc_sap - Defines the SAP component
*
* @station - station this sap belongs to
* @state - sap state
* @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used
* @ind - provided by network layer
* @conf - provided by network layer
* @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list
* @sk_list - LLC sockets this one manages
* @mac_pdu_q - PDUs ready to send to MAC
*/
struct llc_sap {
struct llc_station *parent_station;
u8 state;
u8 p_bit;
u8 f_bit;
int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt);
struct llc_addr laddr;
struct list_head node;
struct llc_station *station;
u8 state;
u8 p_bit;
u8 f_bit;
int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt);
struct llc_addr laddr;
struct list_head node;
struct {
spinlock_t lock;
struct list_head list;
rwlock_t lock;
struct sock *list;
} sk_list;
struct sk_buff_head mac_pdu_q;
};
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);
......
......@@ -493,27 +493,21 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
struct llc_addr *laddr)
{
struct sock *rc = NULL;
struct list_head *entry;
struct sock *rc;
spin_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list))
goto out;
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
read_lock_bh(&sap->sk_list.lock);
for (rc = sap->sk_list.list; rc; rc = rc->next) {
struct llc_opt *llc = llc_sk(rc);
if (llc->laddr.lsap == laddr->lsap &&
llc->daddr.lsap == daddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac) &&
llc_mac_match(llc->daddr.mac, daddr->mac)) {
rc = llc->sk;
llc_mac_match(llc->daddr.mac, daddr->mac))
break;
}
}
if (rc)
sock_hold(rc);
out:
spin_unlock_bh(&sap->sk_list.lock);
read_unlock_bh(&sap->sk_list.lock);
return rc;
}
......@@ -528,25 +522,20 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
*/
struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr)
{
struct sock *rc = NULL;
struct list_head *entry;
struct sock *rc;
spin_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list))
goto out;
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
if (llc->sk->type != SOCK_STREAM || llc->sk->state != TCP_LISTEN ||
llc->laddr.lsap != laddr->lsap ||
!llc_mac_match(llc->laddr.mac, laddr->mac))
continue;
rc = llc->sk;
read_lock_bh(&sap->sk_list.lock);
for (rc = sap->sk_list.list; rc; rc = rc->next) {
struct llc_opt *llc = llc_sk(rc);
if (rc->type == SOCK_STREAM && rc->state == TCP_LISTEN &&
llc->laddr.lsap == laddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac))
break;
}
if (rc)
sock_hold(rc);
out:
spin_unlock_bh(&sap->sk_list.lock);
read_unlock_bh(&sap->sk_list.lock);
return rc;
}
......@@ -560,26 +549,20 @@ struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr)
*/
struct sock *llc_lookup_dgram(struct llc_sap *sap, struct llc_addr *laddr)
{
struct sock *rc = NULL;
struct list_head *entry;
struct sock *rc;
spin_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list))
goto out;
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
read_lock_bh(&sap->sk_list.lock);
for (rc = sap->sk_list.list; rc; rc = rc->next) {
struct llc_opt *llc = llc_sk(rc);
if (llc->sk->type == SOCK_DGRAM &&
if (rc->type == SOCK_DGRAM &&
llc->laddr.lsap == laddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac)) {
rc = llc->sk;
llc_mac_match(llc->laddr.mac, laddr->mac))
break;
}
}
if (rc)
sock_hold(rc);
out:
spin_unlock_bh(&sap->sk_list.lock);
read_unlock_bh(&sap->sk_list.lock);
return rc;
}
/**
......
......@@ -56,8 +56,8 @@ struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb,
goto err;
/* allocated a SAP; initialize it and clear out its memory pool */
sap->laddr.lsap = lsap;
sap->rcv_func = func;
sap->parent_station = llc_station_get();
sap->rcv_func = func;
sap->station = llc_station_get();
/* initialized SAP; add it to list of SAPs this station manages */
llc_sap_save(sap);
out:
......
......@@ -71,8 +71,6 @@ struct llc_sap *llc_sap_alloc(void)
sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN);
spin_lock_init(&sap->sk_list.lock);
INIT_LIST_HEAD(&sap->sk_list.list);
skb_queue_head_init(&sap->mac_pdu_q);
}
return sap;
}
......@@ -86,12 +84,10 @@ struct llc_sap *llc_sap_alloc(void)
*/
void llc_free_sap(struct llc_sap *sap)
{
struct llc_station *station = sap->parent_station;
llc_rtn_all_conns(sap);
spin_lock_bh(&station->sap_list.lock);
write_lock_bh(&sap->station->sap_list.lock);
list_del(&sap->node);
spin_unlock_bh(&station->sap_list.lock);
write_unlock_bh(&sap->station->sap_list.lock);
kfree(sap);
}
......@@ -103,9 +99,9 @@ void llc_free_sap(struct llc_sap *sap)
*/
void llc_sap_save(struct llc_sap *sap)
{
spin_lock_bh(&llc_main_station.sap_list.lock);
write_lock_bh(&llc_main_station.sap_list.lock);
list_add_tail(&sap->node, &llc_main_station.sap_list.list);
spin_unlock_bh(&llc_main_station.sap_list.lock);
write_unlock_bh(&llc_main_station.sap_list.lock);
}
/**
......@@ -120,7 +116,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
struct llc_sap* sap = NULL;
struct list_head *entry;
spin_lock_bh(&llc_main_station.sap_list.lock);
read_lock_bh(&llc_main_station.sap_list.lock);
list_for_each(entry, &llc_main_station.sap_list.list) {
sap = list_entry(entry, struct llc_sap, node);
if (sap->laddr.lsap == sap_value)
......@@ -128,7 +124,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
}
if (entry == &llc_main_station.sap_list.list) /* not found */
sap = NULL;
spin_unlock_bh(&llc_main_station.sap_list.lock);
read_unlock_bh(&llc_main_station.sap_list.lock);
return sap;
}
......@@ -326,20 +322,18 @@ void llc_sk_reset(struct sock *sk)
static int llc_rtn_all_conns(struct llc_sap *sap)
{
int rc = 0;
struct list_head *entry, *tmp;
struct sock *sk;
spin_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list))
goto out;
list_for_each_safe(entry, tmp, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
write_lock_bh(&sap->sk_list.lock);
for (sk = sap->sk_list.list; sk; sk = sk->next) {
llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
llc->state = LLC_CONN_STATE_TEMP;
if (llc_send_disc(llc->sk))
if (llc_send_disc(sk))
rc = 1;
}
out:
spin_unlock_bh(&sap->sk_list.lock);
write_unlock_bh(&sap->sk_list.lock);
return rc;
}
......@@ -562,19 +556,19 @@ static char *llc_conn_state_names[] = {
static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
{
struct llc_opt *llc;
struct list_head *sap_entry, *llc_entry;
struct list_head *sap_entry;
struct sock *sk;
off_t begin = 0, pos = 0;
int len = 0;
spin_lock_bh(&llc_main_station.sap_list.lock);
read_lock_bh(&llc_main_station.sap_list.lock);
list_for_each(sap_entry, &llc_main_station.sap_list.list) {
struct llc_sap *sap = list_entry(sap_entry, struct llc_sap,
node);
len += sprintf(bf + len, "lsap=%02X\n", sap->laddr.lsap);
spin_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) {
read_lock_bh(&sap->sk_list.lock);
if (!sap->sk_list.list) {
len += sprintf(bf + len, "no connections\n");
goto unlock;
}
......@@ -582,8 +576,9 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
"dsap state retr txw rxw "
"pf ff sf df rs cs "
"tack tpfc trs tbs blog busr\n");
list_for_each(llc_entry, &sap->sk_list.list) {
llc = list_entry(llc_entry, struct llc_opt, node);
for (sk = sap->sk_list.list; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk);
len += sprintf(bf + len, " %02X %-10s %3d %3d %3d "
"%2d %2d %2d "
"%2d %2d %2d "
......@@ -598,11 +593,10 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
timer_pending(&llc->pf_cycle_timer.timer),
timer_pending(&llc->rej_sent_timer.timer),
timer_pending(&llc->busy_state_timer.timer),
!!llc->sk->backlog.tail,
llc->sk->lock.users);
!!sk->backlog.tail, sk->lock.users);
}
unlock:
spin_unlock_bh(&sap->sk_list.lock);
read_unlock_bh(&sap->sk_list.lock);
pos = begin + len;
if (pos < offset) {
len = 0; /* Keep dumping into the buffer start */
......@@ -611,7 +605,7 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */
break;
}
spin_unlock_bh(&llc_main_station.sap_list.lock);
read_unlock_bh(&llc_main_station.sap_list.lock);
/* The data in question runs from begin to begin + len */
*start = bf + (offset - begin); /* Start of wanted data */
......@@ -632,8 +626,8 @@ static struct packet_type llc_tr_packet_type = {
};
static char llc_banner[] __initdata =
KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n"
KERN_INFO "NET4.0 IEEE 802.2 extended support\n";
KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001, 2002\n"
KERN_INFO "NET 4.0 IEEE 802.2 extended support\n";
static char llc_error_msg[] __initdata =
KERN_ERR "LLC install NOT successful.\n";
......@@ -693,5 +687,5 @@ module_init(llc_init);
module_exit(llc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001");
MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001, 2002");
MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support");
......@@ -40,11 +40,15 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
*/
void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
{
spin_lock_bh(&sap->sk_list.lock);
write_lock_bh(&sap->sk_list.lock);
llc_sk(sk)->sap = sap;
list_add_tail(&llc_sk(sk)->node, &sap->sk_list.list);
sk->next = sap->sk_list.list;
if (sk->next)
sap->sk_list.list->pprev = &sk->next;
sap->sk_list.list = sk;
sk->pprev = &sap->sk_list.list;
sock_hold(sk);
spin_unlock_bh(&sap->sk_list.lock);
write_unlock_bh(&sap->sk_list.lock);
}
/**
......@@ -56,10 +60,19 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
*/
void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk)
{
spin_lock_bh(&sap->sk_list.lock);
list_del(&llc_sk(sk)->node);
sock_put(sk);
spin_unlock_bh(&sap->sk_list.lock);
write_lock_bh(&sap->sk_list.lock);
if (sk->pprev) {
if (sk->next)
sk->next->pprev = sk->pprev;
*sk->pprev = sk->next;
sk->pprev = NULL;
/*
* This only makes sense if the socket was inserted on the
* list, if sk->pprev is NULL it wasn't
*/
sock_put(sk);
}
write_unlock_bh(&sap->sk_list.lock);
}
/**
......@@ -77,32 +90,30 @@ void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb,
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
/*
* We have to hold the skb, because llc_sap_next_state
* will kfree it in the sending path and we need to
* look at the skb->cb, where we encode llc_sap_state_ev.
*/
skb_get(skb);
ev->ind_cfm_flag = 0;
llc_sap_next_state(sap, skb);
if (ev->ind_cfm_flag == LLC_IND) {
if (sap->rcv_func) {
/* FIXME:
* Ugly hack, still trying to figure it
* out if this is a bug in IPX or here
* in LLC Land... But hey, it even works,
* no leaks 8)
*/
if (skb->list)
skb_get(skb);
if (sap->rcv_func)
sap->rcv_func(skb, skb->dev, pt);
} else {
else {
if (skb->sk->state == TCP_LISTEN)
goto drop;
llc_save_primitive(skb, ev->prim);
/* queue skb to the user. */
if (sock_queue_rcv_skb(skb->sk, skb))
kfree_skb(skb);
else {
llc_save_primitive(skb, ev->prim);
/* queue skb to the user. */
if (sock_queue_rcv_skb(skb->sk, skb))
kfree_skb(skb);
}
}
} else if (ev->type == LLC_SAP_EV_TYPE_PDU) {
drop:
kfree_skb(skb);
}
}
kfree_skb(skb);
}
/**
......
......@@ -198,7 +198,7 @@ static int llc_ui_release(struct socket *sock)
if (!sk->zapped)
llc_sap_unassign_sock(llc->sap, sk);
release_sock(sk);
if (llc->sap && list_empty(&llc->sap->sk_list.list))
if (llc->sap && !llc->sap->sk_list.list)
llc_sap_close(llc->sap);
sock_put(sk);
llc_sk_free(sk);
......@@ -1042,25 +1042,24 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
{
off_t pos = 0;
off_t begin = 0;
struct llc_opt *llc;
struct llc_sap *sap;
struct list_head *sap_entry, *llc_entry;
struct sock *sk;
struct list_head *sap_entry;
struct llc_station *station = llc_station_get();
int len = sprintf(buffer, "SKt Mc local_mac_sap "
"remote_mac_sap tx_queue rx_queue st uid "
"link\n");
/* Output the LLC socket data for the /proc filesystem */
spin_lock_bh(&station->sap_list.lock);
read_lock_bh(&station->sap_list.lock);
list_for_each(sap_entry, &station->sap_list.list) {
sap = list_entry(sap_entry, struct llc_sap, node);
spin_lock_bh(&sap->sk_list.lock);
list_for_each(llc_entry, &sap->sk_list.list) {
llc = list_entry(llc_entry, struct llc_opt, node);
read_lock_bh(&sap->sk_list.lock);
for (sk = sap->sk_list.list; sk; sk = sk->next) {
struct llc_opt *llc = llc_sk(sk);
len += sprintf(buffer + len, "%2X %2X ",
llc->sk->type,
len += sprintf(buffer + len, "%2X %2X ", sk->type,
!llc_mac_null(llc->addr.sllc_mmac));
if (llc->dev && llc_mac_null(llc->addr.sllc_mmac))
llc_ui_format_mac(buffer + len,
......@@ -1080,12 +1079,11 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
len += sprintf(buffer + len,
"@%02X %8d %8d %2d %3d ",
llc->addr.sllc_dsap,
atomic_read(&llc->sk->wmem_alloc),
atomic_read(&llc->sk->rmem_alloc),
llc->sk->state,
llc->sk->socket ?
SOCK_INODE(llc->sk->socket)->i_uid :
-1);
atomic_read(&sk->wmem_alloc),
atomic_read(&sk->rmem_alloc),
sk->state,
sk->socket ?
SOCK_INODE(sk->socket)->i_uid : -1);
len += sprintf(buffer + len, "%4d\n", llc->link);
/* Are we still dumping unwanted data then discard the record */
pos = begin + len;
......@@ -1097,9 +1095,9 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */
break;
}
spin_unlock_bh(&sap->sk_list.lock);
read_unlock_bh(&sap->sk_list.lock);
}
spin_unlock_bh(&station->sap_list.lock);
read_unlock_bh(&station->sap_list.lock);
/* The data in question runs from begin to begin + len */
*start = buffer + offset - begin; /* Start of wanted data */
......
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