162306a36Sopenharmony_ci#ifndef LLC_H 262306a36Sopenharmony_ci#define LLC_H 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * Copyright (c) 1997 by Procom Technology, Inc. 562306a36Sopenharmony_ci * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This program can be redistributed or modified under the terms of the 862306a36Sopenharmony_ci * GNU General Public License as published by the Free Software Foundation. 962306a36Sopenharmony_ci * This program is distributed without any warranty or implied warranty 1062306a36Sopenharmony_ci * of merchantability or fitness for a particular purpose. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * See the GNU General Public License for more details. 1362306a36Sopenharmony_ci */ 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/if.h> 1662306a36Sopenharmony_ci#include <linux/if_ether.h> 1762306a36Sopenharmony_ci#include <linux/list.h> 1862306a36Sopenharmony_ci#include <linux/spinlock.h> 1962306a36Sopenharmony_ci#include <linux/rculist_nulls.h> 2062306a36Sopenharmony_ci#include <linux/hash.h> 2162306a36Sopenharmony_ci#include <linux/jhash.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include <linux/atomic.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct net_device; 2662306a36Sopenharmony_cistruct packet_type; 2762306a36Sopenharmony_cistruct sk_buff; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct llc_addr { 3062306a36Sopenharmony_ci unsigned char lsap; 3162306a36Sopenharmony_ci unsigned char mac[IFHWADDRLEN]; 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define LLC_SAP_STATE_INACTIVE 1 3562306a36Sopenharmony_ci#define LLC_SAP_STATE_ACTIVE 2 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define LLC_SK_DEV_HASH_BITS 6 3862306a36Sopenharmony_ci#define LLC_SK_DEV_HASH_ENTRIES (1<<LLC_SK_DEV_HASH_BITS) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define LLC_SK_LADDR_HASH_BITS 6 4162306a36Sopenharmony_ci#define LLC_SK_LADDR_HASH_ENTRIES (1<<LLC_SK_LADDR_HASH_BITS) 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/** 4462306a36Sopenharmony_ci * struct llc_sap - Defines the SAP component 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * @station - station this sap belongs to 4762306a36Sopenharmony_ci * @state - sap state 4862306a36Sopenharmony_ci * @p_bit - only lowest-order bit used 4962306a36Sopenharmony_ci * @f_bit - only lowest-order bit used 5062306a36Sopenharmony_ci * @laddr - SAP value in this 'lsap' 5162306a36Sopenharmony_ci * @node - entry in station sap_list 5262306a36Sopenharmony_ci * @sk_list - LLC sockets this one manages 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cistruct llc_sap { 5562306a36Sopenharmony_ci unsigned char state; 5662306a36Sopenharmony_ci unsigned char p_bit; 5762306a36Sopenharmony_ci unsigned char f_bit; 5862306a36Sopenharmony_ci refcount_t refcnt; 5962306a36Sopenharmony_ci int (*rcv_func)(struct sk_buff *skb, 6062306a36Sopenharmony_ci struct net_device *dev, 6162306a36Sopenharmony_ci struct packet_type *pt, 6262306a36Sopenharmony_ci struct net_device *orig_dev); 6362306a36Sopenharmony_ci struct llc_addr laddr; 6462306a36Sopenharmony_ci struct list_head node; 6562306a36Sopenharmony_ci spinlock_t sk_lock; 6662306a36Sopenharmony_ci int sk_count; 6762306a36Sopenharmony_ci struct hlist_nulls_head sk_laddr_hash[LLC_SK_LADDR_HASH_ENTRIES]; 6862306a36Sopenharmony_ci struct hlist_head sk_dev_hash[LLC_SK_DEV_HASH_ENTRIES]; 6962306a36Sopenharmony_ci struct rcu_head rcu; 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic inline 7362306a36Sopenharmony_cistruct hlist_head *llc_sk_dev_hash(struct llc_sap *sap, int ifindex) 7462306a36Sopenharmony_ci{ 7562306a36Sopenharmony_ci u32 bucket = hash_32(ifindex, LLC_SK_DEV_HASH_BITS); 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return &sap->sk_dev_hash[bucket]; 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_cistatic inline 8162306a36Sopenharmony_ciu32 llc_sk_laddr_hashfn(struct llc_sap *sap, const struct llc_addr *laddr) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci return hash_32(jhash(laddr->mac, sizeof(laddr->mac), 0), 8462306a36Sopenharmony_ci LLC_SK_LADDR_HASH_BITS); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic inline 8862306a36Sopenharmony_cistruct hlist_nulls_head *llc_sk_laddr_hash(struct llc_sap *sap, 8962306a36Sopenharmony_ci const struct llc_addr *laddr) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci return &sap->sk_laddr_hash[llc_sk_laddr_hashfn(sap, laddr)]; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define LLC_DEST_INVALID 0 /* Invalid LLC PDU type */ 9562306a36Sopenharmony_ci#define LLC_DEST_SAP 1 /* Type 1 goes here */ 9662306a36Sopenharmony_ci#define LLC_DEST_CONN 2 /* Type 2 goes here */ 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciextern struct list_head llc_sap_list; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ciint llc_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, 10162306a36Sopenharmony_ci struct net_device *orig_dev); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciint llc_mac_hdr_init(struct sk_buff *skb, const unsigned char *sa, 10462306a36Sopenharmony_ci const unsigned char *da); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_civoid llc_add_pack(int type, 10762306a36Sopenharmony_ci void (*handler)(struct llc_sap *sap, struct sk_buff *skb)); 10862306a36Sopenharmony_civoid llc_remove_pack(int type); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_civoid llc_set_station_handler(void (*handler)(struct sk_buff *skb)); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistruct llc_sap *llc_sap_open(unsigned char lsap, 11362306a36Sopenharmony_ci int (*rcv)(struct sk_buff *skb, 11462306a36Sopenharmony_ci struct net_device *dev, 11562306a36Sopenharmony_ci struct packet_type *pt, 11662306a36Sopenharmony_ci struct net_device *orig_dev)); 11762306a36Sopenharmony_cistatic inline void llc_sap_hold(struct llc_sap *sap) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci refcount_inc(&sap->refcnt); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic inline bool llc_sap_hold_safe(struct llc_sap *sap) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci return refcount_inc_not_zero(&sap->refcnt); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_civoid llc_sap_close(struct llc_sap *sap); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic inline void llc_sap_put(struct llc_sap *sap) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci if (refcount_dec_and_test(&sap->refcnt)) 13262306a36Sopenharmony_ci llc_sap_close(sap); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistruct llc_sap *llc_sap_find(unsigned char sap_value); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ciint llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, 13862306a36Sopenharmony_ci const unsigned char *dmac, unsigned char dsap); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_civoid llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb); 14162306a36Sopenharmony_civoid llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_civoid llc_station_init(void); 14462306a36Sopenharmony_civoid llc_station_exit(void); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#ifdef CONFIG_PROC_FS 14762306a36Sopenharmony_ciint llc_proc_init(void); 14862306a36Sopenharmony_civoid llc_proc_exit(void); 14962306a36Sopenharmony_ci#else 15062306a36Sopenharmony_ci#define llc_proc_init() (0) 15162306a36Sopenharmony_ci#define llc_proc_exit() do { } while(0) 15262306a36Sopenharmony_ci#endif /* CONFIG_PROC_FS */ 15362306a36Sopenharmony_ci#ifdef CONFIG_SYSCTL 15462306a36Sopenharmony_ciint llc_sysctl_init(void); 15562306a36Sopenharmony_civoid llc_sysctl_exit(void); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ciextern int sysctl_llc2_ack_timeout; 15862306a36Sopenharmony_ciextern int sysctl_llc2_busy_timeout; 15962306a36Sopenharmony_ciextern int sysctl_llc2_p_timeout; 16062306a36Sopenharmony_ciextern int sysctl_llc2_rej_timeout; 16162306a36Sopenharmony_ci#else 16262306a36Sopenharmony_ci#define llc_sysctl_init() (0) 16362306a36Sopenharmony_ci#define llc_sysctl_exit() do { } while(0) 16462306a36Sopenharmony_ci#endif /* CONFIG_SYSCTL */ 16562306a36Sopenharmony_ci#endif /* LLC_H */ 166