o LLC: trim down llc_core to the very basic support needed by IPX et all

Renaming the basic support module to llc.ko and introducing llc_core.c,
that has just the basic output path for llc_build_and_send_ui_pkt.

Next step will be to rename llc_main.c to llc_station.c, then consolidate
all the llc station code in this file, removing all the not needed
llc_station parameters and killing struct llc_station altogether,
no sense in having it as there is just one station, always. BTW in
this changeset parts of llc_main_station was already moved to llc_core.c,
namely the sap list and lock.
parent 4d44110b
...@@ -9,7 +9,7 @@ menu "Token Ring devices" ...@@ -9,7 +9,7 @@ menu "Token Ring devices"
config TR config TR
bool "Token Ring driver support" bool "Token Ring driver support"
depends on (PCI || ISA || MCA || CCW) depends on (PCI || ISA || MCA || CCW)
select LLC_CORE select LLC
help help
Token Ring is IBM's way of communication on a local network; the Token Ring is IBM's way of communication on a local network; the
rest of the world uses Ethernet. To participate on a Token Ring rest of the world uses Ethernet. To participate on a Token Ring
......
...@@ -12,15 +12,55 @@ ...@@ -12,15 +12,55 @@
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ #include <linux/if.h>
#define LLC_DEST_SAP 1 /* Type 1 goes here */ #include <linux/list.h>
#define LLC_DEST_CONN 2 /* Type 2 goes here */ #include <linux/spinlock.h>
struct llc_sap;
struct net_device; struct net_device;
struct packet_type; struct packet_type;
struct sk_buff; struct sk_buff;
struct llc_addr {
unsigned char lsap;
unsigned char mac[IFHWADDRLEN];
};
#define LLC_SAP_STATE_INACTIVE 1
#define LLC_SAP_STATE_ACTIVE 2
/**
* 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
* @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list
* @sk_list - LLC sockets this one manages
*/
struct llc_sap {
unsigned char state;
unsigned char p_bit;
unsigned char 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 {
rwlock_t lock;
struct hlist_head list;
} sk_list;
};
#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */
#define LLC_DEST_SAP 1 /* Type 1 goes here */
#define LLC_DEST_CONN 2 /* Type 2 goes here */
extern struct list_head llc_sap_list;
extern rwlock_t llc_sap_list_lock;
extern int llc_rcv(struct sk_buff *skb, struct net_device *dev, extern int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt); struct packet_type *pt);
...@@ -29,4 +69,13 @@ extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, ...@@ -29,4 +69,13 @@ extern void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
extern void llc_remove_pack(int type); extern void llc_remove_pack(int type);
extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb)); extern void llc_set_station_handler(void (*handler)(struct sk_buff *skb));
extern struct llc_sap *llc_sap_open(unsigned char lsap,
int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt));
extern void llc_sap_close(struct llc_sap *sap);
extern int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap);
#endif /* LLC_H */ #endif /* LLC_H */
...@@ -45,6 +45,8 @@ static __inline__ struct llc_station_state_ev * ...@@ -45,6 +45,8 @@ static __inline__ struct llc_station_state_ev *
return (struct llc_station_state_ev *)skb->cb; return (struct llc_station_state_ev *)skb->cb;
} }
struct llc_station;
typedef int (*llc_station_ev_t)(struct llc_station *station, typedef int (*llc_station_ev_t)(struct llc_station *station,
struct sk_buff *skb); struct sk_buff *skb);
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/llc.h> #include <linux/llc.h>
#include <net/llc.h>
#define LLC_DATAUNIT_PRIM 1 #define LLC_DATAUNIT_PRIM 1
#define LLC_CONN_PRIM 2 #define LLC_CONN_PRIM 2
...@@ -60,13 +61,6 @@ ...@@ -60,13 +61,6 @@
#define LLC_STATUS_CONFLICT 7 /* disconnect conn */ #define LLC_STATUS_CONFLICT 7 /* disconnect conn */
#define LLC_STATUS_RESET_DONE 8 /* */ #define LLC_STATUS_RESET_DONE 8 /* */
/* Structures and types */
/* SAP/MAC Address pair */
struct llc_addr {
u8 lsap;
u8 mac[IFHWADDRLEN];
};
extern u8 llc_mac_null_var[IFHWADDRLEN]; extern u8 llc_mac_null_var[IFHWADDRLEN];
/** /**
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
* *
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#include <linux/skbuff.h>
#define LLC_EVENT 1 #define LLC_EVENT 1
#define LLC_PACKET 2 #define LLC_PACKET 2
#define LLC_TYPE_1 1 #define LLC_TYPE_1 1
...@@ -39,10 +42,6 @@ struct llc_station { ...@@ -39,10 +42,6 @@ struct llc_station {
u8 retry_count; u8 retry_count;
u8 maximum_retry; u8 maximum_retry;
u8 mac_sa[6]; u8 mac_sa[6];
struct {
rwlock_t lock;
struct list_head list;
} sap_list;
struct { struct {
struct sk_buff_head list; struct sk_buff_head list;
spinlock_t lock; spinlock_t lock;
...@@ -50,15 +49,10 @@ struct llc_station { ...@@ -50,15 +49,10 @@ struct llc_station {
struct sk_buff_head mac_pdu_q; struct sk_buff_head mac_pdu_q;
}; };
extern struct llc_sap *llc_sap_alloc(void);
extern void llc_sap_save(struct llc_sap *sap);
extern void llc_free_sap(struct llc_sap *sap);
extern struct llc_sap *llc_sap_find(u8 lsap);
extern void llc_station_state_process(struct llc_station *station, extern void llc_station_state_process(struct llc_station *station,
struct sk_buff *skb); struct sk_buff *skb);
extern void llc_station_send_pdu(struct llc_station *station, extern void llc_station_send_pdu(struct llc_station *station,
struct sk_buff *skb); struct sk_buff *skb);
extern struct sk_buff *llc_alloc_frame(void); extern int __init llc_station_init(void);
extern void __exit llc_station_exit(void);
extern struct llc_station llc_main_station;
#endif /* LLC_MAIN_H */ #endif /* LLC_MAIN_H */
...@@ -11,10 +11,7 @@ ...@@ -11,10 +11,7 @@
* *
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
/* Defines SAP component states */
#define LLC_SAP_STATE_INACTIVE 1
#define LLC_SAP_STATE_ACTIVE 2
#define LLC_NR_SAP_STATES 2 /* size of state table */ #define LLC_NR_SAP_STATES 2 /* size of state table */
/* structures and types */ /* structures and types */
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define LLC_SAP_H #define LLC_SAP_H
/* /*
* Copyright (c) 1997 by Procom Technology,Inc. * Copyright (c) 1997 by Procom Technology,Inc.
* 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* *
* This program can be redistributed or modified under the terms of the * This program can be redistributed or modified under the terms of the
* GNU General Public License as published by the Free Software Foundation. * GNU General Public License as published by the Free Software Foundation.
...@@ -11,50 +11,20 @@ ...@@ -11,50 +11,20 @@
* *
* See the GNU General Public License for more details. * See the GNU General Public License for more details.
*/ */
#include <linux/skbuff.h> struct llc_sap;
#include <net/llc_if.h> struct sk_buff;
/**
* 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
* @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list
* @sk_list - LLC sockets this one manages
*/
struct llc_sap {
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 {
rwlock_t lock;
struct hlist_head list;
} sk_list;
};
extern void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb); extern void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb);
extern void llc_save_primitive(struct sk_buff* skb, u8 prim); extern void llc_save_primitive(struct sk_buff* skb, unsigned char prim);
extern struct sk_buff *llc_alloc_frame(void);
extern struct llc_sap *llc_sap_open(u8 lsap,
int (*rcv)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt));
extern void llc_sap_close(struct llc_sap *sap);
extern void llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
u8 *dmac, u8 dsap);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap, extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb, u8 *dmac, u8 dsap); struct sk_buff *skb,
unsigned char *dmac,
unsigned char dsap);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap,
struct sk_buff *skb,
unsigned char *dmac,
unsigned char dsap);
#endif /* LLC_SAP_H */ #endif /* LLC_SAP_H */
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/init.h> #include <linux/init.h>
#include <net/llc.h>
#include <net/p8022.h> #include <net/p8022.h>
#include <net/llc_sap.h>
static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb, static int p8022_request(struct datalink_proto *dl, struct sk_buff *skb,
unsigned char *dest) unsigned char *dest)
......
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/datalink.h> #include <net/datalink.h>
#include <net/llc.h>
#include <net/psnap.h> #include <net/psnap.h>
#include <net/llc_sap.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/in.h> #include <linux/in.h>
#include <linux/init.h> #include <linux/init.h>
......
...@@ -374,7 +374,7 @@ source "net/llc/Kconfig" ...@@ -374,7 +374,7 @@ source "net/llc/Kconfig"
config IPX config IPX
tristate "The IPX protocol" tristate "The IPX protocol"
select LLC_CORE select LLC
---help--- ---help---
This is support for the Novell networking protocol, IPX, commonly This is support for the Novell networking protocol, IPX, commonly
used for local networks of Windows machines. You need it if you used for local networks of Windows machines. You need it if you
...@@ -411,7 +411,7 @@ source "net/ipx/Kconfig" ...@@ -411,7 +411,7 @@ source "net/ipx/Kconfig"
config ATALK config ATALK
tristate "Appletalk protocol support" tristate "Appletalk protocol support"
select LLC_CORE select LLC
---help--- ---help---
AppleTalk is the protocol that Apple computers can use to communicate AppleTalk is the protocol that Apple computers can use to communicate
on a network. If your Linux box is connected to such a network and you on a network. If your Linux box is connected to such a network and you
......
...@@ -12,7 +12,7 @@ obj-$(CONFIG_NET) := socket.o core/ ...@@ -12,7 +12,7 @@ obj-$(CONFIG_NET) := socket.o core/
obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_COMPAT) += compat.o
# LLC has to be linked before the files in net/802/ # LLC has to be linked before the files in net/802/
obj-$(CONFIG_LLC_CORE) += llc/ obj-$(CONFIG_LLC) += llc/
obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/ obj-$(CONFIG_NET) += ethernet/ 802/ sched/ netlink/
obj-$(CONFIG_INET) += ipv4/ xfrm/ obj-$(CONFIG_INET) += ipv4/ xfrm/
obj-$(CONFIG_UNIX) += unix/ obj-$(CONFIG_UNIX) += unix/
......
config LLC_CORE config LLC
tristate tristate
depends on NET depends on NET
config LLC2 config LLC2
tristate "ANSI/IEEE 802.2 LLC type 2 Support" tristate "ANSI/IEEE 802.2 LLC type 2 Support"
select LLC_CORE select LLC
help help
This is a Logical Link Layer type 2, connection oriented support. This is a Logical Link Layer type 2, connection oriented support.
Select this if you want to have support for PF_LLC sockets. Select this if you want to have support for PF_LLC sockets.
...@@ -12,14 +12,14 @@ ...@@ -12,14 +12,14 @@
# See the GNU General Public License for more details. # See the GNU General Public License for more details.
########################################################################### ###########################################################################
obj-$(CONFIG_LLC_CORE) += llc_core.o obj-$(CONFIG_LLC) += llc.o
llc_core-y := llc_input.o llc_output.o llc_s_st.o llc_s_ac.o llc_s_ev.o \ llc-y := llc_core.o llc_input.o llc_output.o
llc_main.o llc_actn.o llc_stat.o llc_evnt.o llc_sap.o
obj-$(CONFIG_LLC2) += llc2.o obj-$(CONFIG_LLC2) += llc2.o
llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \ llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
af_llc.o llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_main.o \
llc_actn.o llc_stat.o llc_evnt.o
llc2-$(CONFIG_PROC_FS) += llc_proc.o llc2-$(CONFIG_PROC_FS) += llc_proc.o
...@@ -1053,6 +1053,7 @@ static int __init llc2_init(void) ...@@ -1053,6 +1053,7 @@ static int __init llc2_init(void)
int rc; int rc;
llc_build_offset_table(); llc_build_offset_table();
llc_station_init();
llc_ui_sap_last_autoport = LLC_SAP_DYN_START; llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
rc = llc_proc_init(); rc = llc_proc_init();
if (!rc) { if (!rc) {
...@@ -1065,6 +1066,7 @@ static int __init llc2_init(void) ...@@ -1065,6 +1066,7 @@ static int __init llc2_init(void)
static void __exit llc2_exit(void) static void __exit llc2_exit(void)
{ {
llc_station_exit();
llc_remove_pack(LLC_DEST_SAP); llc_remove_pack(LLC_DEST_SAP);
llc_remove_pack(LLC_DEST_CONN); llc_remove_pack(LLC_DEST_CONN);
sock_unregister(PF_LLC); sock_unregister(PF_LLC);
......
/*
* llc_core.c - Minimum needed routines for sap handling and module init/exit
*
* Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
*
* This program can be redistributed or modified under the terms of the
* GNU General Public License as published by the Free Software Foundation.
* This program is distributed without any warranty or implied warranty
* of merchantability or fitness for a particular purpose.
*
* See the GNU General Public License for more details.
*/
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <net/llc.h>
LIST_HEAD(llc_sap_list);
rwlock_t llc_sap_list_lock = RW_LOCK_UNLOCKED;
unsigned char llc_station_mac_sa[ETH_ALEN];
/**
* llc_sap_alloc - allocates and initializes sap.
*
* Allocates and initializes sap.
*/
struct llc_sap *llc_sap_alloc(void)
{
struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
if (sap) {
memset(sap, 0, sizeof(*sap));
sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock);
}
return sap;
}
/**
* llc_add_sap - add sap to station list
* @sap: Address of the sap
*
* Adds a sap to the LLC's station sap list.
*/
void llc_add_sap(struct llc_sap *sap)
{
write_lock_bh(&llc_sap_list_lock);
list_add_tail(&sap->node, &llc_sap_list);
write_unlock_bh(&llc_sap_list_lock);
}
/**
* llc_del_sap - del sap from station list
* @sap: Address of the sap
*
* Removes a sap to the LLC's station sap list.
*/
void llc_del_sap(struct llc_sap *sap)
{
write_lock_bh(&llc_sap_list_lock);
list_del(&sap->node);
write_unlock_bh(&llc_sap_list_lock);
}
/**
* llc_sap_find - searchs a SAP in station
* @sap_value: sap to be found
*
* Searchs for a sap in the sap list of the LLC's station upon the sap ID.
* Returns the sap or %NULL if not found.
*/
struct llc_sap *llc_sap_find(unsigned char sap_value)
{
struct llc_sap* sap = NULL;
struct list_head *entry;
read_lock_bh(&llc_sap_list_lock);
list_for_each(entry, &llc_sap_list) {
sap = list_entry(entry, struct llc_sap, node);
if (sap->laddr.lsap == sap_value)
break;
}
if (entry == &llc_sap_list) /* not found */
sap = NULL;
read_unlock_bh(&llc_sap_list_lock);
return sap;
}
/**
* llc_sap_open - open interface to the upper layers.
* @lsap: SAP number.
* @func: rcv func for datalink protos
*
* Interface function to upper layer. Each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns the opened
* SAP for success, NULL for failure.
*/
struct llc_sap *llc_sap_open(unsigned char lsap,
int (*func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt))
{
struct llc_sap *sap = llc_sap_find(lsap);
if (sap) { /* SAP already exists */
sap = NULL;
goto out;
}
sap = llc_sap_alloc();
if (!sap)
goto out;
sap->laddr.lsap = lsap;
sap->rcv_func = func;
llc_add_sap(sap);
out:
return sap;
}
/**
* llc_sap_close - close interface for upper layers.
* @sap: SAP to be closed.
*
* Close interface function to upper layer. Each one who wants to
* close an open SAP (for example NetBEUI) should call this function.
* Removes this sap from the list of saps in the station and then
* frees the memory for this sap.
*/
void llc_sap_close(struct llc_sap *sap)
{
WARN_ON(!hlist_empty(&sap->sk_list.list));
llc_del_sap(sap);
kfree(sap);
}
static struct packet_type llc_packet_type = {
.type = __constant_htons(ETH_P_802_2),
.func = llc_rcv,
.data = (void *)1,
};
static struct packet_type llc_tr_packet_type = {
.type = __constant_htons(ETH_P_TR_802_2),
.func = llc_rcv,
.data = (void *)1,
};
static int __init llc_init(void)
{
if (dev_base->next)
memcpy(llc_station_mac_sa, dev_base->next->dev_addr, ETH_ALEN);
else
memset(llc_station_mac_sa, 0, ETH_ALEN);
dev_add_pack(&llc_packet_type);
dev_add_pack(&llc_tr_packet_type);
return 0;
}
static void __exit llc_exit(void)
{
dev_remove_pack(&llc_packet_type);
dev_remove_pack(&llc_tr_packet_type);
}
module_init(llc_init);
module_exit(llc_exit);
EXPORT_SYMBOL(llc_sap_list);
EXPORT_SYMBOL(llc_sap_list_lock);
EXPORT_SYMBOL(llc_sap_find);
EXPORT_SYMBOL(llc_sap_open);
EXPORT_SYMBOL(llc_sap_close);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
MODULE_DESCRIPTION("LLC IEEE 802.2 core support");
...@@ -43,44 +43,8 @@ static u16 llc_exec_station_trans_actions(struct llc_station *station, ...@@ -43,44 +43,8 @@ static u16 llc_exec_station_trans_actions(struct llc_station *station,
static struct llc_station_state_trans * static struct llc_station_state_trans *
llc_find_station_trans(struct llc_station *station, llc_find_station_trans(struct llc_station *station,
struct sk_buff *skb); struct sk_buff *skb);
struct llc_station llc_main_station; /* only one of its kind */
/** static struct llc_station llc_main_station;
* llc_sap_save - add sap to station list
* @sap: Address of the sap
*
* Adds a sap to the LLC's station sap list.
*/
void llc_sap_save(struct llc_sap *sap)
{
write_lock_bh(&llc_main_station.sap_list.lock);
list_add_tail(&sap->node, &llc_main_station.sap_list.list);
write_unlock_bh(&llc_main_station.sap_list.lock);
}
/**
* llc_sap_find - searchs a SAP in station
* @sap_value: sap to be found
*
* Searchs for a sap in the sap list of the LLC's station upon the sap ID.
* Returns the sap or %NULL if not found.
*/
struct llc_sap *llc_sap_find(u8 sap_value)
{
struct llc_sap* sap = NULL;
struct list_head *entry;
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)
break;
}
if (entry == &llc_main_station.sap_list.list) /* not found */
sap = NULL;
read_unlock_bh(&llc_main_station.sap_list.lock);
return sap;
}
/** /**
* llc_station_state_process: queue event and try to process queue. * llc_station_state_process: queue event and try to process queue.
...@@ -265,49 +229,12 @@ static void llc_station_rcv(struct sk_buff *skb) ...@@ -265,49 +229,12 @@ static void llc_station_rcv(struct sk_buff *skb)
llc_station_state_process(&llc_main_station, skb); llc_station_state_process(&llc_main_station, skb);
} }
/** int __init llc_station_init(void)
* llc_alloc_frame - allocates sk_buff for frame
*
* Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory.
*/
struct sk_buff *llc_alloc_frame(void)
{
struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
if (skb) {
skb_reserve(skb, 50);
skb->nh.raw = skb->h.raw = skb->data;
skb->protocol = htons(ETH_P_802_2);
skb->dev = dev_base->next;
skb->mac.raw = skb->head;
}
return skb;
}
static struct packet_type llc_packet_type = {
.type = __constant_htons(ETH_P_802_2),
.func = llc_rcv,
.data = (void *)1,
};
static struct packet_type llc_tr_packet_type = {
.type = __constant_htons(ETH_P_TR_802_2),
.func = llc_rcv,
.data = (void *)1,
};
static char llc_error_msg[] __initdata =
KERN_ERR "LLC install NOT successful.\n";
static int __init llc_init(void)
{ {
u16 rc = 0; u16 rc = -ENOBUFS;
struct sk_buff *skb; struct sk_buff *skb;
struct llc_station_state_ev *ev; struct llc_station_state_ev *ev;
INIT_LIST_HEAD(&llc_main_station.sap_list.list);
rwlock_init(&llc_main_station.sap_list.lock);
skb_queue_head_init(&llc_main_station.mac_pdu_q); skb_queue_head_init(&llc_main_station.mac_pdu_q);
skb_queue_head_init(&llc_main_station.ev_q.list); skb_queue_head_init(&llc_main_station.ev_q.list);
spin_lock_init(&llc_main_station.ev_q.lock); spin_lock_init(&llc_main_station.ev_q.lock);
...@@ -317,46 +244,22 @@ static int __init llc_init(void) ...@@ -317,46 +244,22 @@ static int __init llc_init(void)
skb = alloc_skb(0, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto err; goto out;
rc = 0;
llc_set_station_handler(llc_station_rcv); llc_set_station_handler(llc_station_rcv);
ev = llc_station_ev(skb); ev = llc_station_ev(skb);
memset(ev, 0, sizeof(*ev)); memset(ev, 0, sizeof(*ev));
if (dev_base->next)
memcpy(llc_main_station.mac_sa,
dev_base->next->dev_addr, ETH_ALEN);
else
memset(llc_main_station.mac_sa, 0, ETH_ALEN);
llc_main_station.ack_timer.expires = jiffies + 3 * HZ; llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
llc_main_station.maximum_retry = 1; llc_main_station.maximum_retry = 1;
llc_main_station.state = LLC_STATION_STATE_DOWN; llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
rc = llc_station_next_state(&llc_main_station, skb); rc = llc_station_next_state(&llc_main_station, skb);
dev_add_pack(&llc_packet_type);
dev_add_pack(&llc_tr_packet_type);
out: out:
return rc; return rc;
err:
printk(llc_error_msg);
rc = 1;
goto out;
} }
static void __exit llc_exit(void) void __exit llc_station_exit(void)
{ {
dev_remove_pack(&llc_packet_type);
dev_remove_pack(&llc_tr_packet_type);
llc_set_station_handler(NULL); llc_set_station_handler(NULL);
} }
module_init(llc_init);
module_exit(llc_exit);
EXPORT_SYMBOL(llc_sap_find);
EXPORT_SYMBOL(llc_alloc_frame);
EXPORT_SYMBOL(llc_main_station);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
MODULE_DESCRIPTION("LLC IEEE 802.2 extended support");
MODULE_ALIAS_NETPROTO(PF_LLC);
/* /*
* llc_output.c - LLC output path * llc_output.c - LLC minimal output path
* *
* Copyright (c) 1997 by Procom Technology, Inc. * Copyright (c) 1997 by Procom Technology, Inc.
* 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
#include <linux/if_tr.h> #include <linux/if_tr.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/llc.h>
#include <net/llc_pdu.h>
/** /**
* llc_mac_hdr_init - fills MAC header fields * llc_mac_hdr_init - fills MAC header fields
...@@ -72,4 +74,32 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da) ...@@ -72,4 +74,32 @@ int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
return rc; return rc;
} }
/**
* llc_build_and_send_ui_pkt - unitdata request interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @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).
*
* Accept data frame from network layer to be sent using connection-
* less mode communication; timeout/retries handled by network layer;
* package primitive as an event and send to SAP event handler
*/
int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
unsigned char *dmac, unsigned char dsap)
{
int rc;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
dsap, LLC_PDU_CMD);
llc_pdu_init_as_ui_cmd(skb);
rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
if (!rc)
rc = dev_queue_xmit(skb);
return rc;
}
EXPORT_SYMBOL(llc_mac_hdr_init); EXPORT_SYMBOL(llc_mac_hdr_init);
EXPORT_SYMBOL(llc_build_and_send_ui_pkt);
...@@ -20,12 +20,11 @@ ...@@ -20,12 +20,11 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/llc.h>
#include <net/llc_c_ac.h> #include <net/llc_c_ac.h>
#include <net/llc_c_ev.h> #include <net/llc_c_ev.h>
#include <net/llc_c_st.h> #include <net/llc_c_st.h>
#include <net/llc_conn.h> #include <net/llc_conn.h>
#include <net/llc_main.h>
#include <net/llc_sap.h>
static void llc_ui_format_mac(struct seq_file *seq, unsigned char *mac) static void llc_ui_format_mac(struct seq_file *seq, unsigned char *mac)
{ {
...@@ -40,7 +39,7 @@ static struct sock *llc_get_sk_idx(loff_t pos) ...@@ -40,7 +39,7 @@ static struct sock *llc_get_sk_idx(loff_t pos)
struct hlist_node *node; struct hlist_node *node;
struct sock *sk = NULL; struct sock *sk = NULL;
list_for_each(sap_entry, &llc_main_station.sap_list.list) { list_for_each(sap_entry, &llc_sap_list) {
sap = list_entry(sap_entry, struct llc_sap, node); sap = list_entry(sap_entry, struct llc_sap, node);
read_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
...@@ -65,7 +64,7 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos) ...@@ -65,7 +64,7 @@ static void *llc_seq_start(struct seq_file *seq, loff_t *pos)
{ {
loff_t l = *pos; loff_t l = *pos;
read_lock_bh(&llc_main_station.sap_list.lock); read_lock_bh(&llc_sap_list_lock);
return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN; return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN;
} }
...@@ -91,7 +90,7 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos) ...@@ -91,7 +90,7 @@ static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
read_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
sk = NULL; sk = NULL;
for (;;) { for (;;) {
if (sap->node.next == &llc_main_station.sap_list.list) if (sap->node.next == &llc_sap_list)
break; break;
sap = list_entry(sap->node.next, struct llc_sap, node); sap = list_entry(sap->node.next, struct llc_sap, node);
read_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
...@@ -114,7 +113,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v) ...@@ -114,7 +113,7 @@ static void llc_seq_stop(struct seq_file *seq, void *v)
read_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
} }
read_unlock_bh(&llc_main_station.sap_list.lock); read_unlock_bh(&llc_sap_list_lock);
} }
static int llc_seq_socket_show(struct seq_file *seq, void *v) static int llc_seq_socket_show(struct seq_file *seq, void *v)
......
...@@ -23,6 +23,26 @@ ...@@ -23,6 +23,26 @@
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
#include <linux/if_tr.h> #include <linux/if_tr.h>
/**
* llc_alloc_frame - allocates sk_buff for frame
*
* Allocates an sk_buff for frame and initializes sk_buff fields.
* Returns allocated skb or %NULL when out of memory.
*/
struct sk_buff *llc_alloc_frame(void)
{
struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
if (skb) {
skb_reserve(skb, 50);
skb->nh.raw = skb->h.raw = skb->data;
skb->protocol = htons(ETH_P_802_2);
skb->dev = dev_base->next;
skb->mac.raw = skb->head;
}
return skb;
}
void llc_save_primitive(struct sk_buff* skb, u8 prim) void llc_save_primitive(struct sk_buff* skb, u8 prim)
{ {
struct sockaddr_llc *addr = llc_ui_skb_cb(skb); struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
...@@ -180,36 +200,6 @@ void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb) ...@@ -180,36 +200,6 @@ void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
/**
* llc_build_and_send_ui_pkt - unitdata request interface for upper layers
* @sap: sap to use
* @skb: packet to send
* @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).
*
* Accept data frame from network layer to be sent using connection-
* 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,
u8 *dmac, u8 dsap)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->saddr.lsap = sap->laddr.lsap;
ev->daddr.lsap = dsap;
memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
ev->type = LLC_SAP_EV_TYPE_PRIM;
ev->prim = LLC_DATAUNIT_PRIM;
ev->prim_type = LLC_PRIM_TYPE_REQ;
llc_sap_state_process(sap, skb);
}
/** /**
* llc_build_and_send_test_pkt - TEST interface for upper layers. * llc_build_and_send_test_pkt - TEST interface for upper layers.
* @sap: sap to use * @sap: sap to use
...@@ -325,79 +315,6 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb) ...@@ -325,79 +315,6 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
/**
* llc_sap_alloc - allocates and initializes sap.
*
* Allocates and initializes sap.
*/
struct llc_sap *llc_sap_alloc(void)
{
struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
if (sap) {
memset(sap, 0, sizeof(*sap));
sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN);
rwlock_init(&sap->sk_list.lock);
}
return sap;
}
/**
* llc_sap_open - open interface to the upper layers.
* @lsap: SAP number.
* @func: rcv func for datalink protos
*
* Interface function to upper layer. Each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns the opened
* SAP for success, NULL for failure.
*/
struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt))
{
/* verify this SAP is not already open; if so, return error */
struct llc_sap *sap;
sap = llc_sap_find(lsap);
if (sap) { /* SAP already exists */
sap = NULL;
goto out;
}
/* sap requested does not yet exist */
sap = llc_sap_alloc();
if (!sap)
goto out;
/* allocated a SAP; initialize it and clear out its memory pool */
sap->laddr.lsap = lsap;
sap->rcv_func = func;
sap->station = &llc_main_station;
/* initialized SAP; add it to list of SAPs this station manages */
llc_sap_save(sap);
out:
return sap;
}
/**
* llc_sap_close - close interface for upper layers.
* @sap: SAP to be closed.
*
* Close interface function to upper layer. Each one who wants to
* close an open SAP (for example NetBEUI) should call this function.
* Removes this sap from the list of saps in the station and then
* frees the memory for this sap.
*/
void llc_sap_close(struct llc_sap *sap)
{
WARN_ON(!hlist_empty(&sap->sk_list.list));
write_lock_bh(&sap->station->sap_list.lock);
list_del(&sap->node);
write_unlock_bh(&sap->station->sap_list.lock);
kfree(sap);
}
EXPORT_SYMBOL(llc_sap_open);
EXPORT_SYMBOL(llc_sap_close);
EXPORT_SYMBOL(llc_save_primitive); EXPORT_SYMBOL(llc_save_primitive);
EXPORT_SYMBOL(llc_build_and_send_test_pkt); EXPORT_SYMBOL(llc_build_and_send_test_pkt);
EXPORT_SYMBOL(llc_build_and_send_ui_pkt); EXPORT_SYMBOL(llc_build_and_send_ui_pkt);
......
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