Commit d038b8c5 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/davem/BK/net-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents d1a75a97 1a2c129e
This diff is collapsed.
...@@ -58,6 +58,11 @@ ...@@ -58,6 +58,11 @@
#define TG3PCI_MAX_LAT 0x0000003f #define TG3PCI_MAX_LAT 0x0000003f
#define TG3PCI_X_CAPS 0x00000040 #define TG3PCI_X_CAPS 0x00000040
#define PCIX_CAPS_RELAXED_ORDERING 0x00020000 #define PCIX_CAPS_RELAXED_ORDERING 0x00020000
#define PCIX_CAPS_SPLIT_MASK 0x00700000
#define PCIX_CAPS_SPLIT_SHIFT 20
#define PCIX_CAPS_BURST_MASK 0x000c0000
#define PCIX_CAPS_BURST_SHIFT 18
#define PCIX_CAPS_MAX_BURST_5704 2
#define TG3PCI_PM_CAP_PTR 0x00000041 #define TG3PCI_PM_CAP_PTR 0x00000041
#define TG3PCI_X_COMMAND 0x00000042 #define TG3PCI_X_COMMAND 0x00000042
#define TG3PCI_X_STATUS 0x00000044 #define TG3PCI_X_STATUS 0x00000044
...@@ -109,10 +114,13 @@ ...@@ -109,10 +114,13 @@
#define CHIPREV_ID_5703_A0 0x1000 #define CHIPREV_ID_5703_A0 0x1000
#define CHIPREV_ID_5703_A1 0x1001 #define CHIPREV_ID_5703_A1 0x1001
#define CHIPREV_ID_5703_A2 0x1002 #define CHIPREV_ID_5703_A2 0x1002
#define CHIPREV_ID_5703_A3 0x1003
#define CHIPREV_ID_5704_A0 0x2000
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12) #define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07 #define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00 #define ASIC_REV_5701 0x00
#define ASIC_REV_5703 0x01 #define ASIC_REV_5703 0x01
#define ASIC_REV_5704 0x02
#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8) #define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
#define CHIPREV_5700_AX 0x70 #define CHIPREV_5700_AX 0x70
#define CHIPREV_5700_BX 0x71 #define CHIPREV_5700_BX 0x71
...@@ -165,6 +173,7 @@ ...@@ -165,6 +173,7 @@
#define PCISTATE_ROM_ENABLE 0x00000020 #define PCISTATE_ROM_ENABLE 0x00000020
#define PCISTATE_ROM_RETRY_ENABLE 0x00000040 #define PCISTATE_ROM_RETRY_ENABLE 0x00000040
#define PCISTATE_FLAT_VIEW 0x00000100 #define PCISTATE_FLAT_VIEW 0x00000100
#define PCISTATE_RETRY_SAME_DMA 0x00002000
#define TG3PCI_CLOCK_CTRL 0x00000074 #define TG3PCI_CLOCK_CTRL 0x00000074
#define CLOCK_CTRL_CORECLK_DISABLE 0x00000200 #define CLOCK_CTRL_CORECLK_DISABLE 0x00000200
#define CLOCK_CTRL_RXCLK_DISABLE 0x00000400 #define CLOCK_CTRL_RXCLK_DISABLE 0x00000400
...@@ -843,6 +852,8 @@ ...@@ -843,6 +852,8 @@
#define RDMAC_MODE_FIFOURUN_ENAB 0x00000080 #define RDMAC_MODE_FIFOURUN_ENAB 0x00000080
#define RDMAC_MODE_FIFOOREAD_ENAB 0x00000100 #define RDMAC_MODE_FIFOOREAD_ENAB 0x00000100
#define RDMAC_MODE_LNGREAD_ENAB 0x00000200 #define RDMAC_MODE_LNGREAD_ENAB 0x00000200
#define RDMAC_MODE_SPLIT_ENABLE 0x00000800
#define RDMAC_MODE_SPLIT_RESET 0x00001000
#define RDMAC_STATUS 0x00004804 #define RDMAC_STATUS 0x00004804
#define RDMAC_STATUS_TGTABORT 0x00000004 #define RDMAC_STATUS_TGTABORT 0x00000004
#define RDMAC_STATUS_MSTABORT 0x00000008 #define RDMAC_STATUS_MSTABORT 0x00000008
...@@ -1126,6 +1137,8 @@ ...@@ -1126,6 +1137,8 @@
#define GRC_MISC_CFG_BOARD_ID_5702FE 0x00004000 #define GRC_MISC_CFG_BOARD_ID_5702FE 0x00004000
#define GRC_MISC_CFG_BOARD_ID_5703 0x00000000 #define GRC_MISC_CFG_BOARD_ID_5703 0x00000000
#define GRC_MISC_CFG_BOARD_ID_5703S 0x00002000 #define GRC_MISC_CFG_BOARD_ID_5703S 0x00002000
#define GRC_MISC_CFG_BOARD_ID_5704 0x00000000
#define GRC_MISC_CFG_BOARD_ID_5704CIOBE 0x00004000
#define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000 #define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000
#define GRC_LOCAL_CTRL 0x00006808 #define GRC_LOCAL_CTRL 0x00006808
#define GRC_LCLCTRL_INT_ACTIVE 0x00000001 #define GRC_LCLCTRL_INT_ACTIVE 0x00000001
...@@ -1248,14 +1261,19 @@ ...@@ -1248,14 +1261,19 @@
#define NIC_SRAM_DATA_SIG_MAGIC 0x4b657654 /* ascii for 'KevT' */ #define NIC_SRAM_DATA_SIG_MAGIC 0x4b657654 /* ascii for 'KevT' */
#define NIC_SRAM_DATA_CFG 0x00000b58 #define NIC_SRAM_DATA_CFG 0x00000b58
#define NIC_SRAM_DATA_CFG_PHY_TYPE_MASK 0x0000000c #define NIC_SRAM_DATA_CFG_LED_MODE_MASK 0x0000000c
#define NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN 0x00000000
#define NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER 0x00000004
#define NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER 0x00000008
#define NIC_SRAM_DATA_CFG_LED_MODE_MASK 0x00000030
#define NIC_SRAM_DATA_CFG_LED_MODE_UNKNOWN 0x00000000 #define NIC_SRAM_DATA_CFG_LED_MODE_UNKNOWN 0x00000000
#define NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD 0x00000010 #define NIC_SRAM_DATA_CFG_LED_TRIPLE_SPD 0x00000004
#define NIC_SRAM_DATA_CFG_LED_LINK_SPD 0x00000020 #define NIC_SRAM_DATA_CFG_LED_OPEN_DRAIN 0x00000004
#define NIC_SRAM_DATA_CFG_LED_LINK_SPD 0x00000008
#define NIC_SRAM_DATA_CFG_LED_OUTPUT 0x00000008
#define NIC_SRAM_DATA_CFG_PHY_TYPE_MASK 0x00000030
#define NIC_SRAM_DATA_CFG_PHY_TYPE_UNKNOWN 0x00000000
#define NIC_SRAM_DATA_CFG_PHY_TYPE_COPPER 0x00000010
#define NIC_SRAM_DATA_CFG_PHY_TYPE_FIBER 0x00000020
#define NIC_SRAM_DATA_CFG_WOL_ENABLE 0x00000040
#define NIC_SRAM_DATA_CFG_ASF_ENABLE 0x00000080
#define NIC_SRAM_DATA_CFG_EEPROM_WP 0x00000100
#define NIC_SRAM_DATA_PHY_ID 0x00000b74 #define NIC_SRAM_DATA_PHY_ID 0x00000b74
#define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000 #define NIC_SRAM_DATA_PHY_ID1_MASK 0xffff0000
...@@ -1292,7 +1310,8 @@ ...@@ -1292,7 +1310,8 @@
#define NIC_SRAM_RX_BUFFER_DESC 0x00006000 /* 256 entries */ #define NIC_SRAM_RX_BUFFER_DESC 0x00006000 /* 256 entries */
#define NIC_SRAM_RX_JUMBO_BUFFER_DESC 0x00007000 /* 256 entries */ #define NIC_SRAM_RX_JUMBO_BUFFER_DESC 0x00007000 /* 256 entries */
#define NIC_SRAM_MBUF_POOL_BASE 0x00008000 #define NIC_SRAM_MBUF_POOL_BASE 0x00008000
#define NIC_SRAM_MBUF_POOL_SIZE 0x00018000 #define NIC_SRAM_MBUF_POOL_SIZE96 0x00018000
#define NIC_SRAM_MBUF_POOL_SIZE64 0x00018000
/* Currently this is fixed. */ /* Currently this is fixed. */
#define PHY_ADDR 0x01 #define PHY_ADDR 0x01
...@@ -1410,6 +1429,7 @@ struct tg3_tx_buffer_desc { ...@@ -1410,6 +1429,7 @@ struct tg3_tx_buffer_desc {
u32 vlan_tag; u32 vlan_tag;
#define TXD_VLAN_TAG_SHIFT 0 #define TXD_VLAN_TAG_SHIFT 0
#define TXD_MSS_SHIFT 16
}; };
#define TXD_ADDR 0x00UL /* 64-bit */ #define TXD_ADDR 0x00UL /* 64-bit */
...@@ -1660,6 +1680,12 @@ struct ring_info { ...@@ -1660,6 +1680,12 @@ struct ring_info {
DECLARE_PCI_UNMAP_ADDR(mapping) DECLARE_PCI_UNMAP_ADDR(mapping)
}; };
struct tx_ring_info {
struct sk_buff *skb;
DECLARE_PCI_UNMAP_ADDR(mapping)
u32 prev_vlan_tag;
};
struct tg3_config_info { struct tg3_config_info {
u32 flags; u32 flags;
}; };
...@@ -1737,11 +1763,13 @@ struct tg3 { ...@@ -1737,11 +1763,13 @@ struct tg3 {
#define TG3_FLAG_RX_CHECKSUMS 0x00000004 #define TG3_FLAG_RX_CHECKSUMS 0x00000004
#define TG3_FLAG_USE_LINKCHG_REG 0x00000008 #define TG3_FLAG_USE_LINKCHG_REG 0x00000008
#define TG3_FLAG_USE_MI_INTERRUPT 0x00000010 #define TG3_FLAG_USE_MI_INTERRUPT 0x00000010
#define TG3_FLAG_ENABLE_ASF 0x00000020
#define TG3_FLAG_POLL_SERDES 0x00000080 #define TG3_FLAG_POLL_SERDES 0x00000080
#define TG3_FLAG_PHY_RESET_ON_INIT 0x00000100 #define TG3_FLAG_MBOX_WRITE_REORDER 0x00000100
#define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200 #define TG3_FLAG_PCIX_TARGET_HWBUG 0x00000200
#define TG3_FLAG_WOL_SPEED_100MB 0x00000400 #define TG3_FLAG_WOL_SPEED_100MB 0x00000400
#define TG3_FLAG_WOL_ENABLE 0x00001000 #define TG3_FLAG_WOL_ENABLE 0x00000800
#define TG3_FLAG_EEPROM_WRITE_PROT 0x00001000
#define TG3_FLAG_NVRAM 0x00002000 #define TG3_FLAG_NVRAM 0x00002000
#define TG3_FLAG_NVRAM_BUFFERED 0x00004000 #define TG3_FLAG_NVRAM_BUFFERED 0x00004000
#define TG3_FLAG_RX_PAUSE 0x00008000 #define TG3_FLAG_RX_PAUSE 0x00008000
...@@ -1759,14 +1787,20 @@ struct tg3 { ...@@ -1759,14 +1787,20 @@ struct tg3 {
#define TG3_FLAG_PAUSE_TX 0x08000000 #define TG3_FLAG_PAUSE_TX 0x08000000
#define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000 #define TG3_FLAG_BROKEN_CHECKSUMS 0x10000000
#define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000 #define TG3_FLAG_GOT_SERDES_FLOWCTL 0x20000000
#define TG3_FLAG_SPLIT_MODE 0x40000000
#define TG3_FLAG_INIT_COMPLETE 0x80000000 #define TG3_FLAG_INIT_COMPLETE 0x80000000
u32 msg_enable; u32 msg_enable;
u32 split_mode_max_reqs;
#define SPLIT_MODE_5704_MAX_REQ 3
struct timer_list timer; struct timer_list timer;
u16 timer_counter; u16 timer_counter;
u16 timer_multiplier; u16 timer_multiplier;
u32 timer_offset; u32 timer_offset;
u16 asf_counter;
u16 asf_multiplier;
struct tg3_link_config link_config; struct tg3_link_config link_config;
struct tg3_bufmgr_config bufmgr_config; struct tg3_bufmgr_config bufmgr_config;
...@@ -1807,6 +1841,7 @@ struct tg3 { ...@@ -1807,6 +1841,7 @@ struct tg3 {
#define PHY_ID_BCM5411 0x60008070 #define PHY_ID_BCM5411 0x60008070
#define PHY_ID_BCM5701 0x60008110 #define PHY_ID_BCM5701 0x60008110
#define PHY_ID_BCM5703 0x60008160 #define PHY_ID_BCM5703 0x60008160
#define PHY_ID_BCM5704 0x60008190
#define PHY_ID_BCM8002 0x60010140 #define PHY_ID_BCM8002 0x60010140
#define PHY_ID_SERDES 0xfeedbee0 #define PHY_ID_SERDES 0xfeedbee0
#define PHY_ID_INVALID 0xffffffff #define PHY_ID_INVALID 0xffffffff
...@@ -1826,7 +1861,7 @@ struct tg3 { ...@@ -1826,7 +1861,7 @@ struct tg3 {
#define KNOWN_PHY_ID(X) \ #define KNOWN_PHY_ID(X) \
((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \ ((X) == PHY_ID_BCM5400 || (X) == PHY_ID_BCM5401 || \
(X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \
(X) == PHY_ID_BCM5703 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \
(X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES) (X) == PHY_ID_BCM8002 || (X) == PHY_ID_SERDES)
unsigned long regs; unsigned long regs;
...@@ -1853,7 +1888,7 @@ struct tg3 { ...@@ -1853,7 +1888,7 @@ struct tg3 {
/* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */ /* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */
struct tg3_tx_buffer_desc *tx_ring; struct tg3_tx_buffer_desc *tx_ring;
struct ring_info *tx_buffers; struct tx_ring_info *tx_buffers;
dma_addr_t tx_desc_mapping; dma_addr_t tx_desc_mapping;
struct tg3_hw_status *hw_status; struct tg3_hw_status *hw_status;
......
...@@ -5053,6 +5053,7 @@ ...@@ -5053,6 +5053,7 @@
14e4 000b BCM5703 1000BaseTX 14e4 000b BCM5703 1000BaseTX
14e4 8009 BCM5703 1000BaseTX 14e4 8009 BCM5703 1000BaseTX
14e4 800a BCM5703 1000BaseTX 14e4 800a BCM5703 1000BaseTX
1648 NetXtreme BCM5704 Gigabit Ethernet
164d NetXtreme BCM5702FE Gigabit Ethernet 164d NetXtreme BCM5702FE Gigabit Ethernet
16a6 NetXtreme BCM5702X Gigabit Ethernet 16a6 NetXtreme BCM5702X Gigabit Ethernet
16a7 NetXtreme BCM5703X Gigabit Ethernet 16a7 NetXtreme BCM5703X Gigabit Ethernet
......
...@@ -78,17 +78,6 @@ enum llc_sockopts { ...@@ -78,17 +78,6 @@ enum llc_sockopts {
#define LLC_SAP_DYN_STOP 0xDE #define LLC_SAP_DYN_STOP 0xDE
#define LLC_SAP_DYN_TRIES 4 #define LLC_SAP_DYN_TRIES 4
struct sock;
struct llc_ui_opt {
u16 link; /* network layer link number */
struct llc_sap *sap; /* pointer to parent SAP */
struct sock *core_sk;
struct net_device *dev; /* device to send to remote */
struct sockaddr_llc addr; /* address sock is bound to */
};
#define llc_ui_sk(__sk) ((struct llc_ui_opt *)(__sk)->protinfo)
#define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0])) #define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0]))
#ifdef CONFIG_LLC_UI #ifdef CONFIG_LLC_UI
......
...@@ -1561,6 +1561,7 @@ ...@@ -1561,6 +1561,7 @@
#define PCI_DEVICE_ID_TIGON3_5701 0x1645 #define PCI_DEVICE_ID_TIGON3_5701 0x1645
#define PCI_DEVICE_ID_TIGON3_5702 0x1646 #define PCI_DEVICE_ID_TIGON3_5702 0x1646
#define PCI_DEVICE_ID_TIGON3_5703 0x1647 #define PCI_DEVICE_ID_TIGON3_5703 0x1647
#define PCI_DEVICE_ID_TIGON3_5704 0x1648
#define PCI_DEVICE_ID_TIGON3_5702FE 0x164d #define PCI_DEVICE_ID_TIGON3_5702FE 0x164d
#define PCI_DEVICE_ID_TIGON3_5702X 0x16a6 #define PCI_DEVICE_ID_TIGON3_5702X 0x16a6
#define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define LLC_CONN_H #define LLC_CONN_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, 2002 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.
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
*/ */
#include <linux/timer.h> #include <linux/timer.h>
#include <net/llc_if.h> #include <net/llc_if.h>
#include <linux/llc.h>
#undef DEBUG_LLC_CONN_ALLOC
struct llc_timer { struct llc_timer {
struct timer_list timer; struct timer_list timer;
...@@ -25,7 +24,7 @@ struct llc_timer { ...@@ -25,7 +24,7 @@ struct llc_timer {
struct llc_opt { struct llc_opt {
struct list_head node; /* entry in sap->sk_list.list */ struct list_head node; /* entry in sap->sk_list.list */
struct sock *sk; /* sock that has this llc_opt */ struct sock *sk; /* sock that has this llc_opt */
void *handler; /* for upper layers usage */ struct sockaddr_llc addr; /* address sock is bound to */
u8 state; /* state of connection */ u8 state; /* state of connection */
struct llc_sap *sap; /* pointer to parent SAP */ struct llc_sap *sap; /* pointer to parent SAP */
struct llc_addr laddr; /* lsap/mac pair */ struct llc_addr laddr; /* lsap/mac pair */
...@@ -80,63 +79,14 @@ struct llc_opt { ...@@ -80,63 +79,14 @@ struct llc_opt {
struct llc_conn_state_ev; struct llc_conn_state_ev;
extern struct sock *__llc_sock_alloc(void); extern struct sock *llc_sk_alloc(int family, int priority);
extern void __llc_sock_free(struct sock *sk, u8 free); extern void llc_sk_free(struct sock *sk);
#ifdef DEBUG_LLC_CONN_ALLOC
#define dump_stack() printk(KERN_INFO "call trace: %p, %p, %p\n", \
__builtin_return_address(0), \
__builtin_return_address(1), \
__builtin_return_address(2));
#define llc_sock_alloc() ({ \
struct sock *__sk = __llc_sock_alloc(); \
if (__sk) { \
llc_sk(__sk)->f_alloc = __FUNCTION__; \
llc_sk(__sk)->l_alloc = __LINE__; \
} \
__sk;})
#define __llc_sock_assert(__sk) \
if (llc_sk(__sk)->f_free) { \
printk(KERN_ERR \
"%p conn (alloc'd @ %s(%d)) " \
"already freed @ %s(%d) " \
"being used again @ %s(%d)\n", \
llc_sk(__sk), \
llc_sk(__sk)->f_alloc, llc_sk(__sk)->l_alloc, \
llc_sk(__sk)->f_free, llc_sk(__sk)->l_free, \
__FUNCTION__, __LINE__); \
dump_stack();
#define llc_sock_free(__sk) \
{ \
__llc_sock_assert(__sk) \
} else { \
__llc_sock_free(__sk, 0); \
llc_sk(__sk)->f_free = __FUNCTION__; \
llc_sk(__sk)->l_free = __LINE__; \
} \
}
#define llc_sock_assert(__sk) \
{ \
__llc_sock_assert(__sk); \
return; } \
}
#define llc_sock_assert_ret(__sk, __ret) \
{ \
__llc_sock_assert(__sk); \
return __ret; } \
}
#else /* DEBUG_LLC_CONN_ALLOC */
#define llc_sock_alloc() __llc_sock_alloc()
#define llc_sock_free(__sk) __llc_sock_free(__sk, 1)
#define llc_sock_assert(__sk)
#define llc_sock_assert_ret(__sk)
#endif /* DEBUG_LLC_CONN_ALLOC */
extern void llc_sock_reset(struct sock *sk); extern void llc_sk_reset(struct sock *sk);
extern int llc_sock_init(struct sock *sk); extern int llc_sk_init(struct sock *sk);
/* Access to a connection */ /* Access to a connection */
extern int llc_conn_send_ev(struct sock *sk, struct sk_buff *skb); extern int llc_conn_state_process(struct sock *sk, struct sk_buff *skb);
extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb); extern void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb);
extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb); extern void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb);
extern void llc_conn_free_ev(struct sk_buff *skb); extern void llc_conn_free_ev(struct sk_buff *skb);
...@@ -146,7 +96,10 @@ extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, ...@@ -146,7 +96,10 @@ extern void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr,
u8 first_f_bit); u8 first_f_bit);
extern int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, extern int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr,
u16 *how_many_unacked); u16 *how_many_unacked);
extern struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, extern struct sock *llc_lookup_established(struct llc_sap *sap,
struct llc_addr *daddr,
struct llc_addr *laddr);
extern struct sock *llc_lookup_listener(struct llc_sap *sap,
struct llc_addr *laddr); struct llc_addr *laddr);
extern u8 llc_data_accept_state(u8 state); extern u8 llc_data_accept_state(u8 state);
extern void llc_build_offset_table(void); extern void llc_build_offset_table(void);
......
...@@ -14,13 +14,15 @@ ...@@ -14,13 +14,15 @@
/* Defines LLC interface to network layer */ /* Defines LLC interface to network layer */
/* Available primitives */ /* Available primitives */
#include <linux/if.h> #include <linux/if.h>
#include <linux/if_arp.h>
#include <linux/llc.h>
#define LLC_DATAUNIT_PRIM 0 #define LLC_DATAUNIT_PRIM 0
#define LLC_CONN_PRIM 1 #define LLC_CONN_PRIM 1
#define LLC_DATA_PRIM 2 #define LLC_DATA_PRIM 2
#define LLC_DISC_PRIM 3 #define LLC_DISC_PRIM 3
#define LLC_RESET_PRIM 4 #define LLC_RESET_PRIM 4
#define LLC_FLOWCONTROL_PRIM 5 #define LLC_FLOWCONTROL_PRIM 5 /* Not supported at this time */
#define LLC_DISABLE_PRIM 6 #define LLC_DISABLE_PRIM 6
#define LLC_XID_PRIM 7 #define LLC_XID_PRIM 7
#define LLC_TEST_PRIM 8 #define LLC_TEST_PRIM 8
...@@ -65,46 +67,12 @@ struct llc_addr { ...@@ -65,46 +67,12 @@ struct llc_addr {
u8 mac[IFHWADDRLEN]; u8 mac[IFHWADDRLEN];
}; };
/* Primitive-specific data */
struct llc_prim_conn {
struct llc_addr saddr; /* used by request only */
struct llc_addr daddr; /* used by request only */
u8 status; /* reason for failure */
u8 pri; /* service_class */
struct net_device *dev;
struct sock *sk; /* returned from REQUEST */
void *handler; /* upper layer use,
stored in llc_opt->handler */
u16 link;
struct sk_buff *skb; /* received SABME */
};
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;
u8 reason; /* used only by indicate */ u8 reason; /* used only by indicate */
}; };
struct llc_prim_flow_ctrl {
struct sock *sk;
u16 link;
u32 amount;
};
struct llc_prim_data {
struct sock *sk;
u16 link;
u8 pri;
struct sk_buff *skb; /* pointer to frame */
u8 status; /* reason */
};
/* Sending data in conection-less mode */ /* Sending data in conection-less mode */
struct llc_prim_unit_data { struct llc_prim_unit_data {
struct llc_addr saddr; struct llc_addr saddr;
...@@ -129,11 +97,7 @@ struct llc_prim_test { ...@@ -129,11 +97,7 @@ struct llc_prim_test {
}; };
union llc_u_prim_data { union llc_u_prim_data {
struct llc_prim_conn conn;
struct llc_prim_disc disc;
struct llc_prim_reset res; struct llc_prim_reset res;
struct llc_prim_flow_ctrl fc;
struct llc_prim_data data; /* data */
struct llc_prim_unit_data udata; /* unit data */ struct llc_prim_unit_data udata; /* unit data */
struct llc_prim_xid xid; struct llc_prim_xid xid;
struct llc_prim_test test; struct llc_prim_test test;
...@@ -152,4 +116,30 @@ typedef int (*llc_prim_call_t)(struct llc_prim_if_block *prim_if); ...@@ -152,4 +116,30 @@ typedef int (*llc_prim_call_t)(struct llc_prim_if_block *prim_if);
extern struct llc_sap *llc_sap_open(llc_prim_call_t network_indicate, extern struct llc_sap *llc_sap_open(llc_prim_call_t network_indicate,
llc_prim_call_t network_confirm, u8 lsap); llc_prim_call_t network_confirm, u8 lsap);
extern void llc_sap_close(struct llc_sap *sap); extern void llc_sap_close(struct llc_sap *sap);
extern int llc_establish_connection(struct sock *sk, u8 *lmac,
u8 *dmac, u8 dsap);
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);
extern void llc_build_and_send_xid_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr);
extern void llc_build_and_send_test_pkt(struct llc_sap *sap,
struct sk_buff *skb,
struct sockaddr_llc *addr);
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 */ #endif /* LLC_IF_H */
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#define LLC_MAC_H #define LLC_MAC_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, 2002 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.
...@@ -13,13 +13,12 @@ ...@@ -13,13 +13,12 @@
*/ */
/* Defines MAC-layer interface to LLC layer */ /* Defines MAC-layer interface to LLC layer */
extern int mac_send_pdu(struct sk_buff *skb); extern int mac_send_pdu(struct sk_buff *skb);
extern int mac_indicate(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);
extern struct net_device *mac_dev_peer(struct net_device *current_dev, extern struct net_device *mac_dev_peer(struct net_device *current_dev,
int type, u8 *mac); int type, u8 *mac);
extern int llc_pdu_router(struct llc_sap *sap, struct sock *sk,
struct sk_buff *skb, u8 type);
extern u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da); extern u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da);
extern int llc_conn_rcv(struct sock *sk, struct sk_buff *skb);
static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type) static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type)
{ {
...@@ -31,4 +30,36 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb) ...@@ -31,4 +30,36 @@ static __inline__ char llc_backlog_type(struct sk_buff *skb)
return skb->cb[sizeof(skb->cb) - 1]; return skb->cb[sizeof(skb->cb) - 1];
} }
extern u8 llc_mac_null_var[IFHWADDRLEN];
/**
* llc_mac_null - determines if a address is a null mac address
* @mac: Mac address to test if null.
*
* Determines if a given address is a null mac address. Returns 0 if the
* address is not a null mac, 1 if the address is a null mac.
*/
static __inline__ int llc_mac_null(u8 *mac)
{
return !memcmp(mac, llc_mac_null_var, IFHWADDRLEN);
}
static __inline__ int llc_addrany(struct llc_addr *addr)
{
return llc_mac_null(addr->mac) && !addr->lsap;
}
/**
* llc_mac_match - determines if two mac addresses are the same
* @mac1: First mac address to compare.
* @mac2: Second mac address to compare.
*
* Determines if two given mac address are the same. Returns 0 if there
* is not a complete match up to len, 1 if a complete match up to len is
* found.
*/
static __inline__ int llc_mac_match(u8 *mac1, u8 *mac2)
{
return !memcmp(mac1, mac2, IFHWADDRLEN);
}
#endif /* LLC_MAC_H */ #endif /* LLC_MAC_H */
...@@ -61,7 +61,7 @@ extern void llc_sap_save(struct llc_sap *sap); ...@@ -61,7 +61,7 @@ extern void llc_sap_save(struct llc_sap *sap);
extern void llc_free_sap(struct llc_sap *sap); extern void llc_free_sap(struct llc_sap *sap);
extern struct llc_sap *llc_sap_find(u8 lsap); extern struct llc_sap *llc_sap_find(u8 lsap);
extern struct llc_station *llc_station_get(void); extern struct llc_station *llc_station_get(void);
extern void llc_station_send_ev(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);
......
...@@ -237,35 +237,35 @@ struct llc_frmr_info { ...@@ -237,35 +237,35 @@ struct llc_frmr_info {
extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type); extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type);
extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value); extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value);
extern int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit); extern void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit);
extern int llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit); extern void llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit);
extern int llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa); extern void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa);
extern int llc_pdu_decode_da(struct sk_buff *skb, u8 *ds); extern void llc_pdu_decode_da(struct sk_buff *skb, u8 *ds);
extern int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap); extern void llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap);
extern int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap); extern void llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap);
extern int llc_decode_pdu_type(struct sk_buff *skb, u8 *destination); extern void llc_decode_pdu_type(struct sk_buff *skb, u8 *destination);
extern void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap, extern void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap,
u8 dsap, u8 cr); u8 dsap, u8 cr);
extern int llc_pdu_init_as_ui_cmd(struct sk_buff *skb); extern void llc_pdu_init_as_ui_cmd(struct sk_buff *skb);
extern int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported, extern void llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported,
u8 rx_window); u8 rx_window);
extern int llc_pdu_init_as_test_cmd(struct sk_buff *skb); extern void llc_pdu_init_as_test_cmd(struct sk_buff *skb);
extern int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit); extern void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit);
extern int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr); extern void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr);
extern int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); extern void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
extern int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); extern void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
extern int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr); extern void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr);
extern int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit); extern void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit);
extern int llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit); extern void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit);
extern int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported, extern void llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported,
u8 rx_window); u8 rx_window);
extern int llc_pdu_init_as_test_rsp(struct sk_buff *skb, extern void llc_pdu_init_as_test_rsp(struct sk_buff *skb,
struct sk_buff *ev_skb); struct sk_buff *ev_skb);
extern int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, extern void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb,
struct llc_pdu_sn *prev_pdu, struct llc_pdu_sn *prev_pdu,
u8 f_bit, u8 vs, u8 vr, u8 vzyxw); u8 f_bit, u8 vs, u8 vr, u8 vzyxw);
extern int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); extern void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
extern int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); extern void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
extern int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); extern void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
extern int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit); extern void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit);
#endif /* LLC_PDU_H */ #endif /* LLC_PDU_H */
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
* @p_bit - only lowest-order bit used * @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used * @f_bit - only lowest-order bit used
* @req - provided by LLC layer * @req - provided by LLC layer
* @resp - provided by LLC layer
* @ind - provided by network layer * @ind - provided by network layer
* @conf - provided by network layer * @conf - provided by network layer
* @laddr - SAP value in this 'lsap' * @laddr - SAP value in this 'lsap'
...@@ -32,7 +31,6 @@ struct llc_sap { ...@@ -32,7 +31,6 @@ struct llc_sap {
u8 p_bit; u8 p_bit;
u8 f_bit; u8 f_bit;
llc_prim_call_t req; llc_prim_call_t req;
llc_prim_call_t resp;
llc_prim_call_t ind; llc_prim_call_t ind;
llc_prim_call_t conf; llc_prim_call_t conf;
struct llc_prim_if_block llc_ind_prim, llc_cfm_prim; struct llc_prim_if_block llc_ind_prim, llc_cfm_prim;
...@@ -49,7 +47,7 @@ struct llc_sap_state_ev; ...@@ -49,7 +47,7 @@ struct llc_sap_state_ev;
extern void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk); 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); extern void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk);
extern void llc_sap_send_ev(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_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb); extern void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb);
#endif /* LLC_SAP_H */ #endif /* LLC_SAP_H */
...@@ -626,7 +626,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, ...@@ -626,7 +626,7 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
ret = unregister_vlan_dev(dev, ret = unregister_vlan_dev(dev,
VLAN_DEV_INFO(vlandev)->vlan_id); VLAN_DEV_INFO(vlandev)->vlan_id);
unregister_netdev(vlandev); unregister_netdevice(vlandev);
/* Group was destroyed? */ /* Group was destroyed? */
if (ret == 1) if (ret == 1)
......
...@@ -694,11 +694,15 @@ int dev_open(struct net_device *dev) ...@@ -694,11 +694,15 @@ int dev_open(struct net_device *dev)
* Call device private open method * Call device private open method
*/ */
if (try_inc_mod_count(dev->owner)) { if (try_inc_mod_count(dev->owner)) {
set_bit(__LINK_STATE_START, &dev->state);
if (dev->open) { if (dev->open) {
ret = dev->open(dev); ret = dev->open(dev);
if (ret && dev->owner) if (ret) {
clear_bit(__LINK_STATE_START, &dev->state);
if (dev->owner)
__MOD_DEC_USE_COUNT(dev->owner); __MOD_DEC_USE_COUNT(dev->owner);
} }
}
} else { } else {
ret = -ENODEV; ret = -ENODEV;
} }
...@@ -713,8 +717,6 @@ int dev_open(struct net_device *dev) ...@@ -713,8 +717,6 @@ int dev_open(struct net_device *dev)
*/ */
dev->flags |= IFF_UP; dev->flags |= IFF_UP;
set_bit(__LINK_STATE_START, &dev->state);
/* /*
* Initialize multicasting status * Initialize multicasting status
*/ */
......
...@@ -266,7 +266,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) ...@@ -266,7 +266,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb)
for (l = opt->optlen; l > 0; ) { for (l = opt->optlen; l > 0; ) {
switch (*optptr) { switch (*optptr) {
case IPOPT_END: case IPOPT_END:
for (optptr++, l--; l>0; l--) { for (optptr++, l--; l>0; optptr++, l--) {
if (*optptr != IPOPT_END) { if (*optptr != IPOPT_END) {
*optptr = IPOPT_END; *optptr = IPOPT_END;
opt->is_changed = 1; opt->is_changed = 1;
......
...@@ -3289,17 +3289,24 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, ...@@ -3289,17 +3289,24 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
if ((s32)(tp->rcv_tsval - tp->ts_recent) < 0) if ((s32)(tp->rcv_tsval - tp->ts_recent) < 0)
goto slow_path; goto slow_path;
/* Predicted packet is in window by definition. /* DO NOT update ts_recent here, if checksum fails
* seq == rcv_nxt and rcv_wup <= rcv_nxt. * and timestamp was corrupted part, it will result
* Hence, check seq<=rcv_wup reduces to: * in a hung connection since we will drop all
* future packets due to the PAWS test.
*/ */
if (tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
} }
if (len <= tcp_header_len) { if (len <= tcp_header_len) {
/* Bulk data transfer: sender */ /* Bulk data transfer: sender */
if (len == tcp_header_len) { if (len == tcp_header_len) {
/* Predicted packet is in window by definition.
* seq == rcv_nxt and rcv_wup <= rcv_nxt.
* Hence, check seq<=rcv_wup reduces to:
*/
if (tcp_header_len ==
(sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
/* We know that such packets are checksummed /* We know that such packets are checksummed
* on entry. * on entry.
*/ */
...@@ -3325,12 +3332,30 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, ...@@ -3325,12 +3332,30 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
NET_INC_STATS_BH(TCPHPHitsToUser); NET_INC_STATS_BH(TCPHPHitsToUser);
eaten = 1; eaten = 1;
/* Predicted packet is in window by definition.
* seq == rcv_nxt and rcv_wup <= rcv_nxt.
* Hence, check seq<=rcv_wup reduces to:
*/
if (tcp_header_len ==
(sizeof(struct tcphdr) +
TCPOLEN_TSTAMP_ALIGNED) &&
tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
} }
} }
if (!eaten) { if (!eaten) {
if (tcp_checksum_complete_user(sk, skb)) if (tcp_checksum_complete_user(sk, skb))
goto csum_error; goto csum_error;
/* Predicted packet is in window by definition.
* seq == rcv_nxt and rcv_wup <= rcv_nxt.
* Hence, check seq<=rcv_wup reduces to:
*/
if (tcp_header_len ==
(sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED) &&
tp->rcv_nxt == tp->rcv_wup)
tcp_store_ts_recent(tp);
if ((int)skb->truesize > sk->forward_alloc) if ((int)skb->truesize > sk->forward_alloc)
goto step5; goto step5;
......
...@@ -134,7 +134,7 @@ int llc_station_ac_report_status(struct llc_station *station, ...@@ -134,7 +134,7 @@ int llc_station_ac_report_status(struct llc_station *station,
static void llc_station_ack_tmr_callback(unsigned long timeout_data) static void llc_station_ack_tmr_callback(unsigned long timeout_data)
{ {
struct llc_station *station = (struct llc_station *)timeout_data; struct llc_station *station = (struct llc_station *)timeout_data;
struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
station->ack_tmr_running = 0; station->ack_tmr_running = 0;
if (skb) { if (skb) {
...@@ -142,6 +142,6 @@ static void llc_station_ack_tmr_callback(unsigned long timeout_data) ...@@ -142,6 +142,6 @@ static void llc_station_ack_tmr_callback(unsigned long timeout_data)
ev->type = LLC_STATION_EV_TYPE_ACK_TMR; ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
ev->data.tmr.timer_specific = NULL; ev->data.tmr.timer_specific = NULL;
llc_station_send_ev(station, skb); llc_station_state_process(station, skb);
} }
} }
...@@ -65,24 +65,14 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) ...@@ -65,24 +65,14 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
sap = llc_sap_find(dsap); sap = llc_sap_find(dsap);
if (sap) { if (sap) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
struct llc_prim_if_block *prim = &sap->llc_ind_prim;
union llc_u_prim_data *prim_data = prim->data;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
prim_data->conn.daddr.lsap = dsap;
llc_pdu_decode_sa(skb, llc->daddr.mac); llc_pdu_decode_sa(skb, llc->daddr.mac);
llc_pdu_decode_da(skb, llc->laddr.mac); llc_pdu_decode_da(skb, llc->laddr.mac);
llc->dev = skb->dev; llc->dev = skb->dev;
prim_data->conn.pri = 0; /* FIXME: find better way to notify upper layer */
prim_data->conn.sk = sk; ev->flag = LLC_CONN_PRIM + 1;
prim_data->conn.dev = skb->dev; ev->ind_prim = (void *)1;
memcpy(&prim_data->conn.daddr, &llc->laddr, sizeof(llc->laddr));
memcpy(&prim_data->conn.saddr, &llc->daddr, sizeof(llc->daddr));
prim->data = prim_data;
prim->prim = LLC_CONN_PRIM;
prim->sap = llc->sap;
ev->flag = 1;
ev->ind_prim = prim;
rc = 0; rc = 0;
} }
return rc; return rc;
...@@ -91,42 +81,22 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb) ...@@ -91,42 +81,22 @@ int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_conn_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->conn.sk = sk; ev->flag = LLC_CONN_PRIM + 1;
prim_data->conn.pri = 0; ev->cfm_prim = (void *)1;
prim_data->conn.status = ev->status;
prim_data->conn.link = llc->link;
prim_data->conn.dev = skb->dev;
prim->data = prim_data;
prim->prim = LLC_CONN_PRIM;
prim->sap = sap;
ev->flag = 1;
ev->cfm_prim = prim;
return 0; return 0;
} }
static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *skb) static int llc_conn_ac_data_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->data.sk = sk; /*
prim_data->data.pri = 0; * FIXME: find better way to tell upper layer that the packet was
prim_data->data.link = llc->link; * confirmed by the other endpoint
prim_data->data.status = LLC_STATUS_RECEIVED; */
prim_data->data.skb = NULL; ev->flag = LLC_DATA_PRIM + 1;
prim->data = prim_data; ev->cfm_prim = (void *)1;
prim->prim = LLC_DATA_PRIM;
prim->sap = sap;
ev->flag = 1;
ev->cfm_prim = prim;
return 0; return 0;
} }
...@@ -164,19 +134,15 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) ...@@ -164,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;
} }
...@@ -184,19 +150,11 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb) ...@@ -184,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;
} }
...@@ -1342,13 +1300,16 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb) ...@@ -1342,13 +1300,16 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb); struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
if (!LLC_PDU_IS_RSP(pdu)) {
u8 f_bit; u8 f_bit;
if (!LLC_PDU_IS_RSP(pdu) && llc_pdu_decode_pf_bit(skb, &f_bit);
!llc_pdu_decode_pf_bit(skb, &f_bit) && f_bit) { if (f_bit) {
llc_sk(sk)->p_flag = 0; llc_sk(sk)->p_flag = 0;
llc_conn_ac_stop_p_timer(sk, skb); llc_conn_ac_stop_p_timer(sk, skb);
} }
}
return 0; return 0;
} }
...@@ -1459,61 +1420,73 @@ int llc_conn_ac_set_f_flag_p(struct sock *sk, struct sk_buff *skb) ...@@ -1459,61 +1420,73 @@ int llc_conn_ac_set_f_flag_p(struct sock *sk, struct sk_buff *skb)
void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data) void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
{ {
struct sock *sk = (struct sock *)timeout_data; struct sock *sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->pf_cycle_timer.running = 0; llc_sk(sk)->pf_cycle_timer.running = 0;
if (skb) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_P_TMR; ev->type = LLC_CONN_EV_TYPE_P_TMR;
ev->data.tmr.timer_specific = NULL; ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb); llc_process_tmr_ev(sk, skb);
} }
bh_unlock_sock(sk);
} }
static void llc_conn_busy_tmr_cb(unsigned long timeout_data) static void llc_conn_busy_tmr_cb(unsigned long timeout_data)
{ {
struct sock *sk = (struct sock *)timeout_data; struct sock *sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->busy_state_timer.running = 0; llc_sk(sk)->busy_state_timer.running = 0;
if (skb) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_BUSY_TMR; ev->type = LLC_CONN_EV_TYPE_BUSY_TMR;
ev->data.tmr.timer_specific = NULL; ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb); llc_process_tmr_ev(sk, skb);
} }
bh_unlock_sock(sk);
} }
void llc_conn_ack_tmr_cb(unsigned long timeout_data) void llc_conn_ack_tmr_cb(unsigned long timeout_data)
{ {
struct sock* sk = (struct sock *)timeout_data; struct sock* sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->ack_timer.running = 0; llc_sk(sk)->ack_timer.running = 0;
if (skb) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_ACK_TMR; ev->type = LLC_CONN_EV_TYPE_ACK_TMR;
ev->data.tmr.timer_specific = NULL; ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb); llc_process_tmr_ev(sk, skb);
} }
bh_unlock_sock(sk);
} }
static void llc_conn_rej_tmr_cb(unsigned long timeout_data) static void llc_conn_rej_tmr_cb(unsigned long timeout_data)
{ {
struct sock *sk = (struct sock *)timeout_data; struct sock *sk = (struct sock *)timeout_data;
struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC); struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
bh_lock_sock(sk);
llc_sk(sk)->rej_sent_timer.running = 0; llc_sk(sk)->rej_sent_timer.running = 0;
if (skb) { if (skb) {
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
skb->sk = sk;
ev->type = LLC_CONN_EV_TYPE_REJ_TMR; ev->type = LLC_CONN_EV_TYPE_REJ_TMR;
ev->data.tmr.timer_specific = NULL; ev->data.tmr.timer_specific = NULL;
llc_process_tmr_ev(sk, skb); llc_process_tmr_ev(sk, skb);
} }
bh_unlock_sock(sk);
} }
int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb) int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb)
...@@ -1541,14 +1514,11 @@ int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb) ...@@ -1541,14 +1514,11 @@ int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb)
* llc_conn_disc - removes connection from SAP list and frees it * llc_conn_disc - removes connection from SAP list and frees it
* @sk: closed connection * @sk: closed connection
* @skb: occurred event * @skb: occurred event
*
* Returns 2, to indicate the state machine that the connection was freed.
*/ */
int llc_conn_disc(struct sock *sk, struct sk_buff *skb) int llc_conn_disc(struct sock *sk, struct sk_buff *skb)
{ {
llc_sap_unassign_sock(llc_sk(sk)->sap, sk); /* FIXME: this thing seems to want to die */
llc_sock_free(sk); return 0;
return 2;
} }
/** /**
...@@ -1560,7 +1530,7 @@ int llc_conn_disc(struct sock *sk, struct sk_buff *skb) ...@@ -1560,7 +1530,7 @@ int llc_conn_disc(struct sock *sk, struct sk_buff *skb)
*/ */
int llc_conn_reset(struct sock *sk, struct sk_buff *skb) int llc_conn_reset(struct sock *sk, struct sk_buff *skb)
{ {
llc_sock_reset(sk); llc_sk_reset(sk);
return 0; return 0;
} }
...@@ -1589,24 +1559,21 @@ u8 llc_circular_between(u8 a, u8 b, u8 c) ...@@ -1589,24 +1559,21 @@ u8 llc_circular_between(u8 a, u8 b, u8 c)
* This function is called from timer callback functions. When connection * This function is called from timer callback functions. When connection
* is busy (during sending a data frame) timer expiration event must be * is busy (during sending a data frame) timer expiration event must be
* queued. Otherwise this event can be sent to connection state machine. * queued. Otherwise this event can be sent to connection state machine.
* Queued events will process by process_rxframes_events function after * Queued events will process by llc_backlog_rcv function after sending
* sending data frame. Returns 0 for success, 1 otherwise. * data frame.
*/ */
static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb) static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)
{ {
bh_lock_sock(sk);
if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) { if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) {
printk(KERN_WARNING "%s: timer called on closed connection\n", printk(KERN_WARNING "%s: timer called on closed connection\n",
__FUNCTION__); __FUNCTION__);
llc_conn_free_ev(skb); llc_conn_free_ev(skb);
goto out; } else {
}
if (!sk->lock.users) if (!sk->lock.users)
llc_conn_send_ev(sk, skb); llc_conn_state_process(sk, skb);
else { else {
llc_set_backlog_type(skb, LLC_EVENT); llc_set_backlog_type(skb, LLC_EVENT);
sk_add_backlog(sk, skb); sk_add_backlog(sk, skb);
} }
out: }
bh_unlock_sock(sk);
} }
...@@ -241,9 +241,8 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk, ...@@ -241,9 +241,8 @@ int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
u16 rc = !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && u16 rc = !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
if (!rc) if (!rc)
dprintk(KERN_WARNING "rx_i_cmd_p_bit_set_x_inval_ns matched," dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
"state = %d, ns = %d, vr = %d\n", __FUNCTION__, llc_sk(sk)->state, ns, vr);
llc_sk(sk)->state, ns, vr);
return rc; return rc;
} }
...@@ -317,9 +316,8 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk, ...@@ -317,9 +316,8 @@ int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
u16 rc = !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr && u16 rc = !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) && ns != vr &&
llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1; llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
if (!rc) if (!rc)
dprintk(KERN_WARNING "conn_ev_rx_i_rsp_fbit_set_x_inval_ns " dprintk("%s: matched, state=%d, ns=%d, vr=%d\n",
"matched : state = %d, ns = %d, vr = %d\n", __FUNCTION__, llc_sk(sk)->state, ns, vr);
llc_sk(sk)->state, ns, vr);
return rc; return rc;
} }
...@@ -584,9 +582,8 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk, ...@@ -584,9 +582,8 @@ int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
if (!LLC_PDU_IS_CMD(pdu) && if (!LLC_PDU_IS_CMD(pdu) &&
(!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) && (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) &&
nr != vs && llc_util_nr_inside_tx_window(sk, nr)) { nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
dprintk(KERN_ERR "conn_ev_rx_zzz_cmd_inv_nr matched, state = " dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
"%d, vs = %d, nr = %d\n", __FUNCTION__, llc_sk(sk)->state, vs, nr);
llc_sk(sk)->state, vs, nr);
rc = 0; rc = 0;
} }
return rc; return rc;
...@@ -604,9 +601,8 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk, ...@@ -604,9 +601,8 @@ int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
(!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) && (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) &&
nr != vs && llc_util_nr_inside_tx_window(sk, nr)) { nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
rc = 0; rc = 0;
dprintk(KERN_ERR "conn_ev_rx_zzz_fbit_set_x_inval_nr matched, " dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
"state = %d, vs = %d, nr = %d\n", __FUNCTION__, llc_sk(sk)->state, vs, nr);
llc_sk(sk)->state, vs, nr);
} }
return rc; return rc;
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <net/llc_sap.h> #include <net/llc_sap.h>
#include <net/llc_conn.h> #include <net/llc_conn.h>
#include <net/sock.h> #include <net/sock.h>
#include <linux/tcp.h>
#include <net/llc_main.h> #include <net/llc_main.h>
#include <net/llc_c_ev.h> #include <net/llc_c_ev.h>
#include <net/llc_c_ac.h> #include <net/llc_c_ac.h>
...@@ -38,65 +39,149 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, ...@@ -38,65 +39,149 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
/* Offset table on connection states transition diagram */ /* Offset table on connection states transition diagram */
static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV]; static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
static void llc_save_primitive(struct sock *sk, struct sk_buff* skb,
u8 ua, u8 test, u8 xid)
{
struct llc_opt *llc = llc_sk(sk);
struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
/* save primitive for use by the user. */
addr->sllc_family = sk->family;
addr->sllc_arphrd = skb->dev->type;
addr->sllc_test = test;
addr->sllc_xid = xid;
addr->sllc_ua = ua;
addr->sllc_dsap = llc->sap->laddr.lsap;
memcpy(addr->sllc_dmac, llc->laddr.mac, IFHWADDRLEN);
addr->sllc_ssap = llc->daddr.lsap;
memcpy(addr->sllc_smac, llc->daddr.mac, IFHWADDRLEN);
}
/** /**
* llc_conn_send_event - sends event to connection state machine * llc_conn_state_process - sends event to connection state machine
* @sk: connection * @sk: connection
* @skb: occurred event * @skb: occurred event
* *
* Sends an event to connection state machine. after processing event * Sends an event to connection state machine. After processing event
* (executing it's actions and changing state), upper layer will be * (executing it's actions and changing state), upper layer will be
* indicated or confirmed, if needed. Returns 0 for success, 1 for * indicated or confirmed, if needed. Returns 0 for success, 1 for
* failure. The socket lock has to be held before calling this function. * failure. The socket lock has to be held before calling this function.
*/ */
int llc_conn_send_ev(struct sock *sk, struct sk_buff *skb) int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
{ {
/* sending event to state machine */ /* sending event to state machine */
int rc = llc_conn_service(sk, skb); int rc = llc_conn_service(sk, skb);
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_conn_state_ev *ev = llc_conn_ev(skb); struct llc_conn_state_ev *ev = llc_conn_ev(skb);
u8 flag = ev->flag; u8 flag = ev->flag;
u8 status = ev->status;
struct llc_prim_if_block *ind_prim = ev->ind_prim; struct llc_prim_if_block *ind_prim = ev->ind_prim;
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 last prim crap
*/
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);
#ifdef THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY else if (ind_prim && cfm_prim)
/* check if the connection was freed by the state machine by skb_get(skb);
* means of llc_conn_disc */
if (rc == 2) {
printk(KERN_INFO "%s: rc == 2\n", __FUNCTION__);
rc = -ECONNABORTED;
goto out;
}
#endif /* THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY */
if (!flag) /* indicate or confirm not required */ if (!flag) /* indicate or confirm not required */
goto out; goto out;
rc = 0; rc = 0;
if (ind_prim) /* indication required */ if (ind_prim) { /* indication required */
/*
* FIXME: this will be saner as soon I get rid of the double
* sock crap
*/
switch (flag) {
case LLC_DATA_PRIM + 1:
llc_save_primitive(sk, skb, 0, 0, 0);
if (sock_queue_rcv_skb(sk, skb)) {
/*
* FIXME: have to sync the LLC state
* machine wrt mem usage with
* sk->{r,w}mem_alloc, will do
* this soon 8)
*/
printk(KERN_ERR
"%s: sock_queue_rcv_skb failed!\n",
__FUNCTION__);
kfree_skb(skb);
}
break;
case LLC_CONN_PRIM + 1: {
struct sock *parent = skb->sk;
skb->sk = sk;
skb_queue_tail(&parent->receive_queue, skb);
sk->state_change(parent);
}
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;
}
}
kfree_skb(skb);
sock_put(sk);
break;
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 confirm has preconditions */ /* FIXME: see FIXMEs above */
if (cfm_prim->prim != LLC_DATA_PRIM) { switch (flag) {
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)
goto out_kfree_skb;
if (status) {
sk->socket->state = SS_UNCONNECTED;
sk->state = TCP_CLOSE;
} else {
sk->socket->state = SS_CONNECTED;
sk->state = TCP_ESTABLISHED;
}
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;
}
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)) { out_kfree_skb:
/* In this state, we can send I pdu */ kfree_skb(skb);
/* FIXME: check if we don't need to see if sk->lock.users != 0
* is needed here
*/
rc = llc->sap->conf(cfm_prim);
if (rc) /* confirmation didn't accept by upper layer */
llc->failed_data_req = 1;
} else
llc->failed_data_req = 1;
out: out:
return rc; return rc;
} }
void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
{ {
llc_sock_assert(sk);
/* queue PDU to send to MAC layer */ /* queue PDU to send to MAC layer */
skb_queue_tail(&sk->write_queue, skb); skb_queue_tail(&sk->write_queue, skb);
llc_conn_send_pdus(sk); llc_conn_send_pdus(sk);
...@@ -109,26 +194,15 @@ void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb) ...@@ -109,26 +194,15 @@ void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
* *
* Sends received data pdu to upper layer (by using indicate function). * Sends received data pdu to upper layer (by using indicate function).
* Prepares service parameters (prim and prim_data). calling indication * Prepares service parameters (prim and prim_data). calling indication
* function will be done in llc_conn_send_ev. * function will be done in llc_conn_state_process.
*/ */
void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb) void llc_conn_rtn_pdu(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; /* FIXME: indicate that we should send this to the upper layer */
struct llc_prim_if_block *prim = &sap->llc_ind_prim; ev->flag = LLC_DATA_PRIM + 1;
union llc_u_prim_data *prim_data = prim->data; ev->ind_prim = (void *)1;
prim_data->data.sk = sk;
prim_data->data.pri = 0;
prim_data->data.skb = skb;
prim_data->data.link = llc->link;
prim->data = prim_data;
prim->prim = LLC_DATA_PRIM;
prim->sap = sap;
ev->flag = 1;
/* saving prepd prim in event for future use in llc_conn_send_ev */
ev->ind_prim = prim;
} }
/** /**
...@@ -369,11 +443,10 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk, ...@@ -369,11 +443,10 @@ static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
* llc_exec_conn_trans_actions - executes related actions * llc_exec_conn_trans_actions - executes related actions
* @sk: connection * @sk: connection
* @trans: transition that it's actions must be performed * @trans: transition that it's actions must be performed
* @skb: happened event * @skb: event
* *
* Executes actions that is related to happened event. Returns 0 for * Executes actions that is related to happened event. Returns 0 for
* success, 1 to indicate failure of at least one action or 2 if the * success, 1 to indicate failure of at least one action.
* connection was freed (llc_conn_disc was called)
*/ */
static int llc_exec_conn_trans_actions(struct sock *sk, static int llc_exec_conn_trans_actions(struct sock *sk,
struct llc_conn_state_trans *trans, struct llc_conn_state_trans *trans,
...@@ -396,7 +469,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk, ...@@ -396,7 +469,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
} }
/** /**
* llc_find_sock - Finds connection in sap for the remote/local sap/mac * llc_lookup_established - Finds connection for the remote/local sap/mac
* @sap: SAP * @sap: SAP
* @daddr: address of remote LLC (MAC + SAP) * @daddr: address of remote LLC (MAC + SAP)
* @laddr: address of local LLC (MAC + SAP) * @laddr: address of local LLC (MAC + SAP)
...@@ -405,7 +478,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk, ...@@ -405,7 +478,7 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
* mac, remote sap, local mac, and local sap. Returns pointer for * mac, remote sap, local mac, and local sap. Returns pointer for
* connection found, %NULL otherwise. * connection found, %NULL otherwise.
*/ */
struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
struct llc_addr *laddr) struct llc_addr *laddr)
{ {
struct sock *rc = NULL; struct sock *rc = NULL;
...@@ -419,8 +492,8 @@ struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, ...@@ -419,8 +492,8 @@ struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr,
if (llc->laddr.lsap == laddr->lsap && if (llc->laddr.lsap == laddr->lsap &&
llc->daddr.lsap == daddr->lsap && llc->daddr.lsap == daddr->lsap &&
!memcmp(llc->laddr.mac, laddr->mac, ETH_ALEN) && llc_mac_match(llc->laddr.mac, laddr->mac) &&
!memcmp(llc->daddr.mac, daddr->mac, ETH_ALEN)) { llc_mac_match(llc->daddr.mac, daddr->mac)) {
rc = llc->sk; rc = llc->sk;
break; break;
} }
...@@ -432,6 +505,39 @@ struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, ...@@ -432,6 +505,39 @@ struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr,
return rc; return rc;
} }
/**
* llc_lookup_listener - Finds listener for local MAC + SAP
* @sap: SAP
* @laddr: address of local LLC (MAC + SAP)
*
* Search connection list of the SAP and finds connection listening on
* local mac, and local sap. Returns pointer for parent socket found,
* %NULL otherwise.
*/
struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr)
{
struct sock *rc = NULL;
struct list_head *entry;
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;
}
if (rc)
sock_hold(rc);
out:
spin_unlock_bh(&sap->sk_list.lock);
return rc;
}
/** /**
* llc_data_accept_state - designates if in this state data can be sent. * llc_data_accept_state - designates if in this state data can be sent.
* @state: state of connection. * @state: state of connection.
...@@ -440,10 +546,8 @@ struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr, ...@@ -440,10 +546,8 @@ struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr,
*/ */
u8 llc_data_accept_state(u8 state) u8 llc_data_accept_state(u8 state)
{ {
if (state != LLC_CONN_STATE_NORMAL && state != LLC_CONN_STATE_BUSY && return state != LLC_CONN_STATE_NORMAL && state != LLC_CONN_STATE_BUSY &&
state != LLC_CONN_STATE_REJ) state != LLC_CONN_STATE_REJ;
return 1; /* data_conn_refuse */
return 0;
} }
/** /**
......
This diff is collapsed.
...@@ -27,14 +27,17 @@ ...@@ -27,14 +27,17 @@
#include <net/llc_s_ev.h> #include <net/llc_s_ev.h>
#include <linux/trdevice.h> #include <linux/trdevice.h>
#if 1 #if 0
#define dprintk(args...) printk(KERN_DEBUG args) #define dprintk(args...) printk(KERN_DEBUG args)
#else #else
#define dprintk(args...) #define dprintk(args...)
#endif #endif
/* function prototypes */ u8 llc_mac_null_var[IFHWADDRLEN];
static void fix_up_incoming_skb(struct sk_buff *skb); static void fix_up_incoming_skb(struct sk_buff *skb);
static void llc_station_rcv(struct sk_buff *skb);
static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb);
/** /**
* mac_send_pdu - Sends PDU to specific device. * mac_send_pdu - Sends PDU to specific device.
...@@ -52,7 +55,7 @@ int mac_send_pdu(struct sk_buff *skb) ...@@ -52,7 +55,7 @@ int mac_send_pdu(struct sk_buff *skb)
int pri = GFP_ATOMIC, rc = -1; int pri = GFP_ATOMIC, rc = -1;
if (!skb->dev) { if (!skb->dev) {
dprintk(KERN_ERR "%s: skb->dev == NULL!", __FUNCTION__); dprintk("%s: skb->dev == NULL!", __FUNCTION__);
goto out; goto out;
} }
if (skb->sk) if (skb->sk)
...@@ -67,29 +70,30 @@ int mac_send_pdu(struct sk_buff *skb) ...@@ -67,29 +70,30 @@ int mac_send_pdu(struct sk_buff *skb)
} }
/** /**
* mac_indicate - 802.2 entry point from net lower layers * llc_rcv - 802.2 entry point from net lower layers
* @skb: received pdu * @skb: received pdu
* @dev: device that receive pdu * @dev: device that receive pdu
* @pt: packet type * @pt: packet type
* *
* When the system receives a 802.2 frame this function is called. It * When the system receives a 802.2 frame this function is called. It
* checks SAP and connection of received pdu and passes frame to * checks SAP and connection of received pdu and passes frame to
* llc_pdu_router for sending to proper state machine. If frame is * llc_{station,sap,conn}_rcv for sending to proper state machine. If
* related to a busy connection (a connection is sending data now), * the frame is related to a busy connection (a connection is sending
* function queues this frame in connection's backlog. * data now), it queues this frame in the connection's backlog.
*/ */
int mac_indicate(struct sk_buff *skb, struct net_device *dev, int llc_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct llc_sap *sap; struct llc_sap *sap;
struct llc_pdu_sn *pdu; struct llc_pdu_sn *pdu;
u8 dest; u8 dest;
/* When the interface is in promisc. mode, drop all the crap that it /*
* When the interface is in promisc. mode, drop all the crap that it
* receives, do not try to analyse it. * receives, do not try to analyse it.
*/ */
if (skb->pkt_type == PACKET_OTHERHOST) { if (skb->pkt_type == PACKET_OTHERHOST) {
dprintk(KERN_INFO "%s: PACKET_OTHERHOST\n", __FUNCTION__); dprintk("%s: PACKET_OTHERHOST\n", __FUNCTION__);
goto drop; goto drop;
} }
skb = skb_share_check(skb, GFP_ATOMIC); skb = skb_share_check(skb, GFP_ATOMIC);
...@@ -98,17 +102,19 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -98,17 +102,19 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
fix_up_incoming_skb(skb); fix_up_incoming_skb(skb);
pdu = llc_pdu_sn_hdr(skb); pdu = llc_pdu_sn_hdr(skb);
if (!pdu->dsap) { /* NULL DSAP, refer to station */ if (!pdu->dsap) { /* NULL DSAP, refer to station */
if (llc_pdu_router(NULL, NULL, skb, 0)) dprintk("%s: calling llc_station_rcv!\n", __FUNCTION__);
goto drop; llc_station_rcv(skb);
goto out; goto out;
} }
sap = llc_sap_find(pdu->dsap); sap = llc_sap_find(pdu->dsap);
if (!sap) /* unknown SAP */ if (!sap) {/* unknown SAP */
dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__, pdu->dsap);
goto drop; goto drop;
}
llc_decode_pdu_type(skb, &dest); llc_decode_pdu_type(skb, &dest);
if (dest == LLC_DEST_SAP) { /* type 1 services */ if (dest == LLC_DEST_SAP) { /* type 1 services */
if (llc_pdu_router(sap, NULL, skb, LLC_TYPE_1)) dprintk("%s: calling llc_sap_rcv!\n", __FUNCTION__);
goto drop; llc_sap_rcv(sap, skb);
} else if (dest == LLC_DEST_CONN) { } else if (dest == LLC_DEST_CONN) {
struct llc_addr saddr, daddr; struct llc_addr saddr, daddr;
struct sock *sk; struct sock *sk;
...@@ -119,34 +125,42 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -119,34 +125,42 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
llc_pdu_decode_da(skb, daddr.mac); llc_pdu_decode_da(skb, daddr.mac);
llc_pdu_decode_dsap(skb, &daddr.lsap); llc_pdu_decode_dsap(skb, &daddr.lsap);
sk = llc_find_sock(sap, &saddr, &daddr); sk = llc_lookup_established(sap, &saddr, &daddr);
if (!sk) { /* didn't find an active connection; allocate a if (!sk) {
* connection to use; associate it with this SAP /*
* Didn't find an active connection; verify if there
* is a listening socket for this llc addr
*/ */
sk = llc_sock_alloc(); struct llc_opt *llc;
if (!sk) struct sock *parent;
parent = llc_lookup_listener(sap, &daddr);
if (!parent) {
dprintk("llc_lookup_listener failed!\n");
goto drop; goto drop;
memcpy(&llc_sk(sk)->daddr, &saddr, sizeof(saddr)); }
sk = llc_sk_alloc(parent->family, GFP_ATOMIC);
if (!sk) {
sock_put(parent);
goto drop;
}
llc = llc_sk(sk);
memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));
memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));
llc_sap_assign_sock(sap, sk); llc_sap_assign_sock(sap, sk);
sock_hold(sk); sock_hold(sk);
} sock_put(parent);
skb->sk = parent;
} else
skb->sk = sk;
bh_lock_sock(sk); bh_lock_sock(sk);
if (!sk->lock.users) { if (!sk->lock.users) {
/* FIXME: Check this on SMP as it is now calling /* rc = */ llc_conn_rcv(sk, skb);
* llc_pdu_router _with_ the lock held. rc = 0;
* Old comment:
* With the current code one can't call
* llc_pdu_router with the socket lock held, cause
* it'll route the pdu to the upper layers and it can
* reenter llc and in llc_req_prim will try to grab
* the same lock, maybe we should use spin_trylock_bh
* in the llc_req_prim (llc_data_req_handler, etc) and
* add the request to the backlog, well see...
*/
rc = llc_pdu_router(llc_sk(sk)->sap, sk, skb,
LLC_TYPE_2);
} else { } else {
dprintk(KERN_INFO "%s: add to backlog\n", __FUNCTION__); dprintk("%s: adding to backlog...\n", __FUNCTION__);
llc_set_backlog_type(skb, LLC_PACKET); llc_set_backlog_type(skb, LLC_PACKET);
sk_add_backlog(sk, skb); sk_add_backlog(sk, skb);
rc = 0; rc = 0;
...@@ -191,53 +205,56 @@ static void fix_up_incoming_skb(struct sk_buff *skb) ...@@ -191,53 +205,56 @@ static void fix_up_incoming_skb(struct sk_buff *skb)
} }
} }
/** /*
* llc_pdu_router - routes received pdus to the upper layers * llc_station_rcv - send received pdu to the station state machine
* @sap: current sap component structure. * @skb: received frame.
* @sk: current connection structure.
* @frame: received frame.
* @type: type of received frame, that is LLC_TYPE_1 or LLC_TYPE_2
* *
* Queues received PDUs from LLC_MAC PDU receive queue until queue is * Sends data unit to station state machine.
* empty; examines LLC header to determine the destination of PDU, if DSAP
* is NULL then data unit destined for station else frame destined for SAP
* or connection; finds a matching open SAP, if one, forwards the packet
* to it; if no matching SAP, drops the packet. Returns 0 or the return of
* llc_conn_send_ev (that may well result in the connection being
* destroyed)
*/ */
int llc_pdu_router(struct llc_sap *sap, struct sock* sk, static void llc_station_rcv(struct sk_buff *skb)
struct sk_buff *skb, u8 type)
{ {
struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
int rc = 0;
if (!pdu->dsap) {
struct llc_station *station = llc_station_get(); struct llc_station *station = llc_station_get();
struct llc_station_state_ev *ev = llc_station_ev(skb); struct llc_station_state_ev *ev = llc_station_ev(skb);
ev->type = LLC_STATION_EV_TYPE_PDU; ev->type = LLC_STATION_EV_TYPE_PDU;
ev->data.pdu.reason = 0; ev->data.pdu.reason = 0;
llc_station_send_ev(station, skb); llc_station_state_process(station, skb);
} else if (type == LLC_TYPE_1) { }
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->type = LLC_SAP_EV_TYPE_PDU;
ev->data.pdu.reason = 0; /**
llc_sap_send_ev(sap, skb); * llc_conn_rcv - sends received pdus to the connection state machine
} else if (type == LLC_TYPE_2) { * @sk: current connection structure.
* @skb: received frame.
*
* Sends received pdus to the connection state machine.
*/
int llc_conn_rcv(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_opt *llc = llc_sk(sk);
if (!llc->dev) if (!llc->dev)
llc->dev = skb->dev; llc->dev = skb->dev;
ev->type = LLC_CONN_EV_TYPE_PDU; ev->type = LLC_CONN_EV_TYPE_PDU;
ev->data.pdu.reason = 0; ev->data.pdu.reason = 0;
rc = llc_conn_send_ev(sk, skb); return llc_conn_state_process(sk, skb);
} else }
rc = -EINVAL;
return rc; /**
* llc_sap_rcv - sends received pdus to the sap state machine
* @sap: current sap component structure.
* @skb: received frame.
*
* Sends received pdus to the sap state machine.
*/
static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
ev->type = LLC_SAP_EV_TYPE_PDU;
ev->data.pdu.reason = 0;
llc_sap_state_process(sap, skb);
} }
/** /**
......
...@@ -52,6 +52,11 @@ static int llc_rtn_all_conns(struct llc_sap *sap); ...@@ -52,6 +52,11 @@ static int llc_rtn_all_conns(struct llc_sap *sap);
static struct llc_station llc_main_station; /* only one of its kind */ static struct llc_station llc_main_station; /* only one of its kind */
#undef LLC_REFCNT_DEBUG
#ifdef LLC_REFCNT_DEBUG
static atomic_t llc_sock_nr;
#endif
/** /**
* llc_sap_alloc - allocates and initializes sap. * llc_sap_alloc - allocates and initializes sap.
* *
...@@ -136,7 +141,7 @@ struct llc_sap *llc_sap_find(u8 sap_value) ...@@ -136,7 +141,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
* *
* This function processes frames that has received and timers that has * This function processes frames that has received and timers that has
* expired during sending an I pdu (refer to data_req_handler). frames * expired during sending an I pdu (refer to data_req_handler). frames
* queue by mac_indicate function (llc_mac.c) and timers queue by timer * queue by llc_rcv function (llc_mac.c) and timers queue by timer
* callback functions(llc_c_ac.c). * callback functions(llc_c_ac.c).
*/ */
static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
...@@ -146,13 +151,13 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -146,13 +151,13 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
if (llc_backlog_type(skb) == LLC_PACKET) { if (llc_backlog_type(skb) == LLC_PACKET) {
if (llc->state > 1) /* not closed */ if (llc->state > 1) /* not closed */
rc = llc_pdu_router(llc->sap, sk, skb, LLC_TYPE_2); rc = llc_conn_rcv(sk, skb);
else else
kfree_skb(skb); kfree_skb(skb);
} else if (llc_backlog_type(skb) == LLC_EVENT) { } else if (llc_backlog_type(skb) == LLC_EVENT) {
/* timer expiration event */ /* timer expiration event */
if (llc->state > 1) /* not closed */ if (llc->state > 1) /* not closed */
rc = llc_conn_send_ev(sk, skb); rc = llc_conn_state_process(sk, skb);
else else
llc_conn_free_ev(skb); llc_conn_free_ev(skb);
kfree_skb(skb); kfree_skb(skb);
...@@ -165,10 +170,12 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb) ...@@ -165,10 +170,12 @@ static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
} }
/** /**
* llc_sock_init - Initialize a socket with default llc values. * llc_sk_init - Initializes a socket with default llc values.
* @sk: socket to intiailize. * @sk: socket to intiailize.
*
* Initializes a socket with default llc values.
*/ */
int llc_sock_init(struct sock* sk) int llc_sk_init(struct sock* sk)
{ {
struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC); struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC);
int rc = -ENOMEM; int rc = -ENOMEM;
...@@ -198,61 +205,83 @@ int llc_sock_init(struct sock* sk) ...@@ -198,61 +205,83 @@ int llc_sock_init(struct sock* sk)
} }
/** /**
* __llc_sock_alloc - Allocates LLC sock * llc_sk_alloc - Allocates LLC sock
* @family: upper layer protocol family
* @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
* *
* Allocates a LLC sock and initializes it. Returns the new LLC sock * Allocates a LLC sock and initializes it. Returns the new LLC sock
* or %NULL if there's no memory available for one * or %NULL if there's no memory available for one
*/ */
struct sock *__llc_sock_alloc(void) struct sock *llc_sk_alloc(int family, int priority)
{ {
struct sock *sk = sk_alloc(PF_LLC, GFP_ATOMIC, 1, NULL); struct sock *sk = sk_alloc(family, priority, 1, NULL);
MOD_INC_USE_COUNT;
if (!sk) if (!sk)
goto out; goto decmod;
if (llc_sock_init(sk)) if (llc_sk_init(sk))
goto outsk; goto outsk;
sock_init_data(NULL, sk); sock_init_data(NULL, sk);
#ifdef LLC_REFCNT_DEBUG
atomic_inc(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
__FUNCTION__, atomic_read(&llc_sock_nr));
#endif
out: out:
return sk; return sk;
outsk: outsk:
sk_free(sk); sk_free(sk);
sk = NULL; sk = NULL;
decmod:
MOD_DEC_USE_COUNT;
goto out; goto out;
} }
/** /**
* __llc_sock_free - Frees a LLC socket * llc_sk_free - Frees a LLC socket
* @sk - socket to free * @sk - socket to free
* *
* Frees a LLC socket * Frees a LLC socket
*/ */
void __llc_sock_free(struct sock *sk, u8 free) void llc_sk_free(struct sock *sk)
{ {
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
llc->state = LLC_CONN_OUT_OF_SVC; llc->state = LLC_CONN_OUT_OF_SVC;
/* stop all (possibly) running timers */ /* Stop all (possibly) running timers */
llc_conn_ac_stop_all_timers(sk, NULL); llc_conn_ac_stop_all_timers(sk, NULL);
/* handle return of frames on lists */ #ifdef DEBUG_LLC_CONN_ALLOC
#if 0
printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__, printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
skb_queue_len(&llc->pdu_unack_q), skb_queue_len(&llc->pdu_unack_q),
skb_queue_len(&sk->write_queue)); skb_queue_len(&sk->write_queue));
#endif #endif
skb_queue_purge(&sk->receive_queue);
skb_queue_purge(&sk->write_queue); skb_queue_purge(&sk->write_queue);
skb_queue_purge(&llc->pdu_unack_q); skb_queue_purge(&llc->pdu_unack_q);
if (free) #ifdef LLC_REFCNT_DEBUG
if (atomic_read(&sk->refcnt) != 1) {
printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
sk, __FUNCTION__, atomic_read(&sk->refcnt));
printk(KERN_DEBUG "%d LLC sockets are still alive\n",
atomic_read(&llc_sock_nr));
} else {
atomic_dec(&llc_sock_nr);
printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
__FUNCTION__, atomic_read(&llc_sock_nr));
}
#endif
sock_put(sk); sock_put(sk);
MOD_DEC_USE_COUNT;
} }
/** /**
* llc_sock_reset - resets a connection * llc_sk_reset - resets a connection
* @sk: LLC socket to reset * @sk: LLC socket to reset
* *
* Resets a connection to the out of service state. Stops its timers * Resets a connection to the out of service state. Stops its timers
* and frees any frames in the queues of the connection. * and frees any frames in the queues of the connection.
*/ */
void llc_sock_reset(struct sock *sk) void llc_sk_reset(struct sock *sk)
{ {
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
...@@ -286,8 +315,6 @@ void llc_sock_reset(struct sock *sk) ...@@ -286,8 +315,6 @@ void llc_sock_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);
...@@ -296,12 +323,8 @@ static int llc_rtn_all_conns(struct llc_sap *sap) ...@@ -296,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:
...@@ -320,14 +343,14 @@ struct llc_station *llc_station_get(void) ...@@ -320,14 +343,14 @@ struct llc_station *llc_station_get(void)
} }
/** /**
* llc_station_send_ev: queue event and try to process queue. * llc_station_state_process: queue event and try to process queue.
* @station: Address of the station * @station: Address of the station
* @skb: Address of the event * @skb: Address of the event
* *
* Queues an event (on the station event queue) for handling by the * Queues an event (on the station event queue) for handling by the
* station state machine and attempts to process any queued-up events. * station state machine and attempts to process any queued-up events.
*/ */
void llc_station_send_ev(struct llc_station *station, struct sk_buff *skb) void llc_station_state_process(struct llc_station *station, struct sk_buff *skb)
{ {
spin_lock_bh(&station->ev_q.lock); spin_lock_bh(&station->ev_q.lock);
skb_queue_tail(&station->ev_q.list, skb); skb_queue_tail(&station->ev_q.list, skb);
...@@ -557,13 +580,13 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -557,13 +580,13 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
static struct packet_type llc_packet_type = { static struct packet_type llc_packet_type = {
.type = __constant_htons(ETH_P_802_2), .type = __constant_htons(ETH_P_802_2),
.func = mac_indicate, .func = llc_rcv,
.data = (void *)1, .data = (void *)1,
}; };
static struct packet_type llc_tr_packet_type = { static struct packet_type llc_tr_packet_type = {
.type = __constant_htons(ETH_P_TR_802_2), .type = __constant_htons(ETH_P_TR_802_2),
.func = mac_indicate, .func = llc_rcv,
.data = (void *)1, .data = (void *)1,
}; };
...@@ -585,7 +608,7 @@ static int __init llc_init(void) ...@@ -585,7 +608,7 @@ static int __init llc_init(void)
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);
skb = alloc_skb(1, GFP_ATOMIC); skb = alloc_skb(0, GFP_ATOMIC);
if (!skb) if (!skb)
goto err; goto err;
llc_build_offset_table(); llc_build_offset_table();
......
This diff is collapsed.
...@@ -57,13 +57,10 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb) ...@@ -57,13 +57,10 @@ int llc_sap_action_send_ui(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap,
prim_data->daddr.lsap, LLC_PDU_CMD); prim_data->daddr.lsap, LLC_PDU_CMD);
rc = llc_pdu_init_as_ui_cmd(skb); llc_pdu_init_as_ui_cmd(skb);
if (rc)
goto out;
rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, skb); llc_sap_send_pdu(sap, skb);
out:
return rc; return rc;
} }
...@@ -85,13 +82,10 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb) ...@@ -85,13 +82,10 @@ int llc_sap_action_send_xid_c(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap,
prim_data->daddr.lsap, LLC_PDU_CMD); prim_data->daddr.lsap, LLC_PDU_CMD);
rc = llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
if (rc)
goto out;
rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, skb); llc_sap_send_pdu(sap, skb);
out:
return rc; return rc;
} }
...@@ -118,9 +112,7 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -118,9 +112,7 @@ int llc_sap_action_send_xid_r(struct llc_sap *sap, struct sk_buff *skb)
nskb->dev = skb->dev; nskb->dev = skb->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP); LLC_PDU_RSP);
rc = llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0); llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
if (rc)
goto out;
rc = lan_hdrs_init(nskb, mac_sa, mac_da); rc = lan_hdrs_init(nskb, mac_sa, mac_da);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, nskb); llc_sap_send_pdu(sap, nskb);
...@@ -146,13 +138,10 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb) ...@@ -146,13 +138,10 @@ int llc_sap_action_send_test_c(struct llc_sap *sap, struct sk_buff *skb)
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap,
prim_data->daddr.lsap, LLC_PDU_CMD); prim_data->daddr.lsap, LLC_PDU_CMD);
rc = llc_pdu_init_as_test_cmd(skb); llc_pdu_init_as_test_cmd(skb);
if (rc)
goto out;
rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac); rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, skb); llc_sap_send_pdu(sap, skb);
out:
return rc; return rc;
} }
...@@ -171,9 +160,7 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb) ...@@ -171,9 +160,7 @@ int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
nskb->dev = skb->dev; nskb->dev = skb->dev;
llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap, llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
LLC_PDU_RSP); LLC_PDU_RSP);
rc = llc_pdu_init_as_test_rsp(nskb, skb); llc_pdu_init_as_test_rsp(nskb, skb);
if (rc)
goto out;
rc = lan_hdrs_init(nskb, mac_sa, mac_da); rc = lan_hdrs_init(nskb, mac_sa, mac_da);
if (!rc) if (!rc)
llc_sap_send_pdu(sap, nskb); llc_sap_send_pdu(sap, nskb);
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include <net/llc_pdu.h> #include <net/llc_pdu.h>
#include <linux/if_tr.h> #include <linux/if_tr.h>
static void llc_sap_free_ev(struct llc_sap *sap, struct sk_buff *skb);
static int llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb); static int llc_sap_next_state(struct llc_sap *sap, struct sk_buff *skb);
static int llc_exec_sap_trans_actions(struct llc_sap *sap, static int llc_exec_sap_trans_actions(struct llc_sap *sap,
struct llc_sap_state_trans *trans, struct llc_sap_state_trans *trans,
...@@ -52,8 +51,7 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) ...@@ -52,8 +51,7 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
* @sap: SAP * @sap: SAP
* @sk: pointer to connection * @sk: pointer to connection
* *
* This function removes a connection from connection_list of a SAP. * This function removes a connection from sk_list.list of a SAP.
* List locking is performed by caller (rtn_all_conns).
*/ */
void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk) void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk)
{ {
...@@ -64,23 +62,25 @@ void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk) ...@@ -64,23 +62,25 @@ void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk)
} }
/** /**
* llc_sap_send_ev - sends event to SAP state machine * llc_sap_state_process - sends event to SAP state machine
* @sap: pointer to SAP * @sap: pointer to SAP
* @skb: pointer to occurred event * @skb: pointer to occurred event
* *
* After executing actions of the event, upper layer will be indicated * After executing actions of the event, upper layer will be indicated
* if needed(on receiving an UI frame). * if needed(on receiving an UI frame).
*/ */
void llc_sap_send_ev(struct llc_sap *sap, struct sk_buff *skb) void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
{ {
struct llc_sap_state_ev *ev = llc_sap_ev(skb); struct llc_sap_state_ev *ev = llc_sap_ev(skb);
llc_sap_next_state(sap, skb); llc_sap_next_state(sap, skb);
if (ev->ind_cfm_flag == LLC_IND) { if (ev->ind_cfm_flag == LLC_IND)
skb_get(skb);
sap->ind(ev->prim); sap->ind(ev->prim);
} else if (ev->type == LLC_SAP_EV_TYPE_PDU)
llc_sap_free_ev(sap, skb); kfree_skb(skb);
else
printk(KERN_INFO ":%s !kfree_skb & it is %s in a list\n",
__FUNCTION__, skb->list ? "" : "NOT");
} }
/** /**
...@@ -142,19 +142,6 @@ void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb) ...@@ -142,19 +142,6 @@ void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb)
kfree_skb(skb); kfree_skb(skb);
} }
/**
* llc_sap_free_ev - frees an sap event
* @sap: pointer to SAP
* @skb: released event
*/
static void llc_sap_free_ev(struct llc_sap *sap, struct sk_buff *skb)
{
struct llc_sap_state_ev *ev = llc_sap_ev(skb);
if (ev->type == LLC_SAP_EV_TYPE_PDU)
kfree_skb(skb);
}
/** /**
* llc_sap_next_state - finds transition, execs actions & change SAP state * llc_sap_next_state - finds transition, execs actions & change SAP state
* @sap: pointer to SAP * @sap: pointer to SAP
...@@ -206,7 +193,7 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap, ...@@ -206,7 +193,7 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
/* search thru events for this state until list exhausted or until /* search thru events for this state until list exhausted or until
* its obvious the event is not valid for the current state * its obvious the event is not valid for the current state
*/ */
for (next_trans = curr_state->transitions; next_trans [i]->ev; i++) for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
if (!next_trans[i]->ev(sap, skb)) { if (!next_trans[i]->ev(sap, skb)) {
/* got event match; return it */ /* got event match; return it */
rc = next_trans[i]; rc = next_trans[i];
......
This diff is collapsed.
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