summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@conectiva.com.br>2002-05-30 18:36:32 -0300
committerArnaldo Carvalho de Melo <acme@conectiva.com.br>2002-05-30 18:36:32 -0300
commit34beb106cde7da233d4df35dd3d6cf4fee937caa (patch)
tree2f6047513722259104cccc8fcb3aded043af4ce3 /net
parentd0f0cde199764cb083b3617c3739f45b1a73052d (diff)
net/llc/*.c
Forward port of LLC from 2.4 to 2.5. This is the forward port of the LLC stack released by Procom Inc. for Linux 2.0.30, I have heavily modified it to make it similar to other Linux network stacks, using of struct sk_buff to represent in-transit packets and doing massive code cleanups. Jay Schullist contributed support for BSD Sockets, as the original code had only a simple in kernel API for use by upper layer protocols, such as the NetBEUI stack also provided by Procom for 2.0.30. This code is basically what I had previously submitted to Alan Cox for his 2.4-ac series and that is even shipped in source form, in the Red Hat 7.3 kernel package, plus cleanups wrt standard syntax for labeled elements and further use of this C construct to make the code more resilient to editing mistakes, using the compiler to further check the source code. TODO: Make it completely SMP safe, as the reports of successful usage up to now and the testing is done on UP. Completely remove the old LLC code in the kernel, that is still there for things like Appletalk, IPX, etc to use, also check that all these protocols work correctly with this new LLC stack. This code is already being used in the linux-sna project and Jay Schullist has been developing support for things like DLSw and other protocols that works on top of 802.2. I'll be releasing patches with the NetBEUI stack and updated samba-2.0.6 patches for use with NetBEUI and this LLC stack in the future. But the NetBEUI code is available already in my kernel.org ftp area at: ftp://ftp.kernel.org/pub/linux/kernel/people/acme. Please report problems to me or the linux-sna mailing list, instructions on how to subscribe are available at http://www.linux-sna.org website.
Diffstat (limited to 'net')
-rw-r--r--net/802/p8022.c130
-rw-r--r--net/Config.in9
-rw-r--r--net/Makefile6
-rw-r--r--net/core/Makefile6
-rw-r--r--net/core/ext8022.c76
-rw-r--r--net/llc/Makefile38
-rw-r--r--net/llc/llc_actn.c150
-rw-r--r--net/llc/llc_c_ac.c1648
-rw-r--r--net/llc/llc_c_ev.c873
-rw-r--r--net/llc/llc_c_st.c4946
-rw-r--r--net/llc/llc_conn.c531
-rw-r--r--net/llc/llc_evnt.c112
-rw-r--r--net/llc/llc_if.c530
-rw-r--r--net/llc/llc_mac.c317
-rw-r--r--net/llc/llc_main.c641
-rw-r--r--net/llc/llc_pdu.c654
-rw-r--r--net/llc/llc_s_ac.c227
-rw-r--r--net/llc/llc_s_ev.c101
-rw-r--r--net/llc/llc_s_st.c183
-rw-r--r--net/llc/llc_sap.c262
-rw-r--r--net/llc/llc_sock.c1780
-rw-r--r--net/llc/llc_stat.c218
-rw-r--r--net/netsyms.c2
23 files changed, 13358 insertions, 82 deletions
diff --git a/net/802/p8022.c b/net/802/p8022.c
index 41a755e88842..559d8fa66308 100644
--- a/net/802/p8022.c
+++ b/net/802/p8022.c
@@ -11,11 +11,10 @@
* matches. The control byte is ignored and handling of such items
* is up to the routine passed the frame.
*
- * Unlike the 802.3 datalink we have a list of 802.2 entries as there
- * are multiple protocols to demux. The list is currently short (3 or
- * 4 entries at most). The current demux assumes this.
+ * Unlike the 802.3 datalink we have a list of 802.2 entries as
+ * there are multiple protocols to demux. The list is currently
+ * short (3 or 4 entries at most). The current demux assumes this.
*/
-
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
@@ -25,8 +24,13 @@
#include <linux/init.h>
#include <net/p8022.h>
-static struct datalink_proto *p8022_list = NULL;
+extern void llc_register_sap(unsigned char sap,
+ int (*rcvfunc)(struct sk_buff *,
+ struct net_device *,
+ struct packet_type *));
+extern void llc_unregister_sap(unsigned char sap);
+static struct datalink_proto *p8022_list;
/*
* We don't handle the loopback SAP stuff, the extended
* 802.2 command set, multicast SAP identifiers and non UI
@@ -34,91 +38,68 @@ static struct datalink_proto *p8022_list = NULL;
* IP and Appletalk phase 2. See the llc_* routines for
* support libraries if your protocol needs these.
*/
-
static struct datalink_proto *find_8022_client(unsigned char type)
{
- struct datalink_proto *proto;
-
- for (proto = p8022_list;
- ((proto != NULL) && (*(proto->type) != type));
- proto = proto->next)
- ;
+ struct datalink_proto *proto = p8022_list;
+ while (proto && *(proto->type) != type)
+ proto = proto->next;
return proto;
}
-int p8022_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+int p8022_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
{
- struct datalink_proto *proto;
+ struct datalink_proto *proto;
+ int rc = 0;
proto = find_8022_client(*(skb->h.raw));
- if (proto != NULL)
- {
- skb->h.raw += 3;
- skb->nh.raw += 3;
- skb_pull(skb,3);
- return proto->rcvfunc(skb, dev, pt);
+ if (!proto) {
+ skb->sk = NULL;
+ kfree_skb(skb);
+ goto out;
}
-
- skb->sk = NULL;
- kfree_skb(skb);
- return 0;
+ skb->h.raw += 3;
+ skb->nh.raw += 3;
+ skb_pull(skb, 3);
+ rc = proto->rcvfunc(skb, dev, pt);
+out: return rc;
}
static void p8022_datalink_header(struct datalink_proto *dl,
- struct sk_buff *skb, unsigned char *dest_node)
+ struct sk_buff *skb, unsigned char *dest_node)
{
- struct net_device *dev = skb->dev;
- unsigned char *rawp;
+ struct net_device *dev = skb->dev;
+ unsigned char *rawp = skb_push(skb, 3);
- rawp = skb_push(skb,3);
*rawp++ = dl->type[0];
*rawp++ = dl->type[0];
- *rawp = 0x03; /* UI */
+ *rawp = 0x03; /* UI */
dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
}
-static struct packet_type p8022_packet_type =
-{
- 0, /* MUTTER ntohs(ETH_P_8022),*/
- NULL, /* All devices */
- p8022_rcv,
- NULL,
- NULL,
-};
-
-EXPORT_SYMBOL(register_8022_client);
-EXPORT_SYMBOL(unregister_8022_client);
-
-static int __init p8022_init(void)
-{
- p8022_packet_type.type=htons(ETH_P_802_2);
- dev_add_pack(&p8022_packet_type);
- return 0;
-}
-
-module_init(p8022_init);
-
-struct datalink_proto *register_8022_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct net_device *, struct packet_type *))
+struct datalink_proto *register_8022_client(unsigned char type,
+ int (*rcvfunc)(struct sk_buff *,
+ struct net_device *,
+ struct packet_type *))
{
- struct datalink_proto *proto;
-
- if (find_8022_client(type) != NULL)
- return NULL;
-
- proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
- if (proto != NULL) {
- proto->type[0] = type;
- proto->type_len = 1;
- proto->rcvfunc = rcvfunc;
- proto->header_length = 3;
- proto->datalink_header = p8022_datalink_header;
- proto->string_name = "802.2";
- proto->next = p8022_list;
- p8022_list = proto;
+ struct datalink_proto *proto = NULL;
+
+ if (find_8022_client(type))
+ goto out;
+ proto = kmalloc(sizeof(*proto), GFP_ATOMIC);
+ if (proto) {
+ proto->type[0] = type;
+ proto->type_len = 1;
+ proto->rcvfunc = rcvfunc;
+ proto->header_length = 3;
+ proto->datalink_header = p8022_datalink_header;
+ proto->string_name = "802.2";
+ proto->next = p8022_list;
+ p8022_list = proto;
+ llc_register_sap(type, p8022_rcv);
}
-
- return proto;
+out: return proto;
}
void unregister_8022_client(unsigned char type)
@@ -128,17 +109,18 @@ void unregister_8022_client(unsigned char type)
save_flags(flags);
cli();
-
- while ((tmp = *clients) != NULL)
- {
+ while (*clients) {
+ tmp = *clients;
if (tmp->type[0] == type) {
*clients = tmp->next;
kfree(tmp);
+ llc_unregister_sap(type);
break;
- } else {
- clients = &tmp->next;
}
+ clients = &tmp->next;
}
-
restore_flags(flags);
}
+
+EXPORT_SYMBOL(register_8022_client);
+EXPORT_SYMBOL(unregister_8022_client);
diff --git a/net/Config.in b/net/Config.in
index bef48fea4c73..d56b29187ab6 100644
--- a/net/Config.in
+++ b/net/Config.in
@@ -64,11 +64,12 @@ dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
- bool '802.2 LLC (EXPERIMENTAL)' CONFIG_LLC
+ tristate 'ANSI/IEEE 802.2 Data link layer protocol' CONFIG_LLC
+ if [ "$CONFIG_LLC" != "n" ]; then
+ # When NETBEUI is added the following line will be a tristate
+ define_bool CONFIG_LLC_UI y
+ fi
bool 'Frame Diverter (EXPERIMENTAL)' CONFIG_NET_DIVERT
-# if [ "$CONFIG_LLC" = "y" ]; then
-# bool ' Netbeui (EXPERIMENTAL)' CONFIG_NETBEUI
-# fi
if [ "$CONFIG_INET" = "y" ]; then
tristate 'Acorn Econet/AUN protocols (EXPERIMENTAL)' CONFIG_ECONET
if [ "$CONFIG_ECONET" != "n" ]; then
diff --git a/net/Makefile b/net/Makefile
index 480f369b02b5..1efe05a42106 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -7,7 +7,7 @@
O_TARGET := network.o
-mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink sched
+mod-subdirs := ipv4/netfilter ipv6/netfilter ipx irda bluetooth atm netlink llc sched
export-objs := netsyms.o
subdir-y := core ethernet
@@ -44,8 +44,8 @@ subdir-$(CONFIG_SUNRPC) += sunrpc
subdir-$(CONFIG_ATM) += atm
subdir-$(CONFIG_DECNET) += decnet
subdir-$(CONFIG_ECONET) += econet
-subdir-$(CONFIG_VLAN_8021Q) += 8021q
-
+subdir-$(CONFIG_VLAN_8021Q) += 8021q
+subdir-$(CONFIG_LLC) += llc
obj-y := socket.o $(join $(subdir-y), $(patsubst %,/%.o,$(notdir $(subdir-y))))
ifeq ($(CONFIG_NET),y)
diff --git a/net/core/Makefile b/net/core/Makefile
index 5dacce00c212..a87f6eb0a921 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -9,7 +9,7 @@
O_TARGET := core.o
-export-objs := netfilter.o profile.o
+export-objs := ext8022.o netfilter.o profile.o
obj-y := sock.o skbuff.o iovec.o datagram.o scm.o
@@ -23,6 +23,10 @@ obj-$(CONFIG_FILTER) += filter.o
obj-$(CONFIG_NET) += dev.o dev_mcast.o dst.o neighbour.o rtnetlink.o utils.o
+ifneq ($(CONFIG_LLC),n)
+obj-y += ext8022.o
+endif
+
obj-$(CONFIG_NETFILTER) += netfilter.o
obj-$(CONFIG_NET_DIVERT) += dv.o
obj-$(CONFIG_NET_PROFILE) += profile.o
diff --git a/net/core/ext8022.c b/net/core/ext8022.c
new file mode 100644
index 000000000000..e6415d51accb
--- /dev/null
+++ b/net/core/ext8022.c
@@ -0,0 +1,76 @@
+/*
+ * (ext8022.c)
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/brlock.h>
+
+typedef int (*func_type)(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt);
+static int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *);
+
+static func_type llc_sap_table[128];
+static int llc_users;
+
+static struct packet_type llc_packet_type = {
+ type: __constant_htons(ETH_P_802_2),
+ func: llc_rcv,
+};
+static struct packet_type llc_tr_packet_type = {
+ type: __constant_htons(ETH_P_TR_802_2),
+ func: llc_rcv,
+};
+
+static int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+ unsigned char n = (*(skb->h.raw)) >> 1;
+
+ br_read_lock(BR_LLC_LOCK);
+ if (llc_sap_table[n])
+ llc_sap_table[n](skb, dev, pt);
+ else
+ kfree_skb(skb);
+ br_read_unlock(BR_LLC_LOCK);
+ return 0;
+}
+
+void llc_register_sap(unsigned char sap, func_type rcvfunc)
+{
+ sap >>= 1;
+ br_write_lock_bh(BR_LLC_LOCK);
+ llc_sap_table[sap] = rcvfunc;
+ if (!llc_users) {
+ dev_add_pack(&llc_packet_type);
+ dev_add_pack(&llc_tr_packet_type);
+ }
+ llc_users++;
+ br_write_unlock_bh(BR_LLC_LOCK);
+}
+
+void llc_unregister_sap(unsigned char sap)
+{
+ sap >>= 1;
+ br_write_lock_bh(BR_LLC_LOCK);
+ llc_sap_table[sap] = NULL;
+ if (!--llc_users) {
+ dev_remove_pack(&llc_packet_type);
+ dev_remove_pack(&llc_tr_packet_type);
+ }
+ br_write_unlock_bh(BR_LLC_LOCK);
+}
+
+EXPORT_SYMBOL(llc_register_sap);
+EXPORT_SYMBOL(llc_unregister_sap);
diff --git a/net/llc/Makefile b/net/llc/Makefile
new file mode 100644
index 000000000000..bb536f48da03
--- /dev/null
+++ b/net/llc/Makefile
@@ -0,0 +1,38 @@
+###########################################################################
+# Makefile for the Linux 802.2 LLC (fully-functional) layer.
+#
+# Note 1! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+#
+# Copyright (c) 1997 by Procom Technology,Inc.
+# 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+#
+# This program can be redistributed or modified under the terms of the
+# GNU General Public License as published by the Free Software Foundation.
+# This program is distributed without any warranty or implied warranty
+# of merchantability or fitness for a particular purpose.
+#
+# See the GNU General Public License for more details.
+###########################################################################
+
+O_TARGET := llc.o
+
+obj-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_mac.o llc_sap.o llc_s_st.o \
+ llc_main.o llc_s_ac.o llc_conn.o llc_c_st.o llc_stat.o llc_actn.o \
+ llc_s_ev.o llc_evnt.o llc_pdu.o
+
+ifeq ($(CONFIG_LLC_UI),y)
+ obj-y += llc_sock.o
+endif
+
+# Objects that export symbols.
+export-objs := llc_if.o
+
+ifeq ($(CONFIG_LLC),m)
+ obj-m += $(O_TARGET)
+endif
+
+include $(TOPDIR)/Rules.make
diff --git a/net/llc/llc_actn.c b/net/llc/llc_actn.c
new file mode 100644
index 000000000000..fdc487239236
--- /dev/null
+++ b/net/llc/llc_actn.c
@@ -0,0 +1,150 @@
+/*
+ * llc_actn.c - Implementation of actions of station component of LLC
+ *
+ * Description :
+ * Functions in this module are implementation of station component actions.
+ * Details of actions can be found in IEEE-802.2 standard document.
+ * All functions have one station and one event as input argument. All of
+ * them return 0 On success and 1 otherwise.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <net/llc_if.h>
+#include <net/llc_main.h>
+#include <net/llc_evnt.h>
+#include <net/llc_pdu.h>
+#include <net/llc_mac.h>
+
+static void llc_station_ack_tmr_callback(unsigned long timeout_data);
+
+int llc_station_ac_start_ack_timer(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ del_timer(&station->ack_timer);
+ station->ack_timer.expires = jiffies + LLC_ACK_TIME * HZ;
+ station->ack_timer.data = (unsigned long)station;
+ station->ack_timer.function = llc_station_ack_tmr_callback;
+ add_timer(&station->ack_timer);
+ station->ack_tmr_running = 1;
+ return 0;
+}
+
+int llc_station_ac_set_retry_cnt_0(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ station->retry_count = 0;
+ return 0;
+}
+
+int llc_station_ac_inc_retry_cnt_by_1(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ station->retry_count++;
+ return 0;
+}
+
+int llc_station_ac_set_xid_r_cnt_0(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ station->xid_r_count = 0;
+ return 0;
+}
+
+int llc_station_ac_inc_xid_r_cnt_by_1(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ station->xid_r_count++;
+ return 0;
+}
+
+int llc_station_ac_send_null_dsap_xid_c(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (!skb)
+ goto out;
+ rc = 0;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
+ llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 127);
+ lan_hdrs_init(skb, station->mac_sa, station->mac_sa);
+ llc_station_send_pdu(station, skb);
+out:
+ return rc;
+}
+
+int llc_station_ac_send_xid_r(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ u8 mac_da[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff *ev_skb;
+ struct sk_buff* skb = llc_alloc_frame();
+
+ if (!skb)
+ goto out;
+ rc = 0;
+ ev_skb = ev->data.pdu.skb;
+ skb->dev = ev_skb->dev;
+ llc_pdu_decode_sa(ev_skb, mac_da);
+ llc_pdu_decode_ssap(ev_skb, &dsap);
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
+ llc_pdu_init_as_xid_rsp(skb, LLC_XID_NULL_CLASS_2, 127);
+ lan_hdrs_init(skb, station->mac_sa, mac_da);
+ llc_station_send_pdu(station, skb);
+out:
+ return rc;
+}
+
+int llc_station_ac_send_test_r(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ u8 mac_da[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff *ev_skb;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (!skb)
+ goto out;
+ rc = 0;
+ ev_skb = ev->data.pdu.skb;
+ skb->dev = ev_skb->dev;
+ llc_pdu_decode_sa(ev_skb, mac_da);
+ llc_pdu_decode_ssap(ev_skb, &dsap);
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
+ llc_pdu_init_as_test_rsp(skb, ev_skb);
+ lan_hdrs_init(skb, station->mac_sa, mac_da);
+ llc_station_send_pdu(station, skb);
+out:
+ return rc;
+}
+
+int llc_station_ac_report_status(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ return 0;
+}
+
+static void llc_station_ack_tmr_callback(unsigned long timeout_data)
+{
+ struct llc_station *station = (struct llc_station *)timeout_data;
+ struct llc_station_state_ev *ev;
+
+ station->ack_tmr_running = 0;
+ ev = llc_station_alloc_ev(station);
+ if (ev) {
+ ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
+ ev->data.tmr.timer_specific = NULL;
+ llc_station_send_ev(station, ev);
+ }
+}
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
new file mode 100644
index 000000000000..47aebf133bda
--- /dev/null
+++ b/net/llc/llc_c_ac.c
@@ -0,0 +1,1648 @@
+/*
+ * llc_c_ac.c - actions performed during connection state transition.
+ *
+ * Description:
+ * Functions in this module are implementation of connection component actions
+ * Details of actions can be found in IEEE-802.2 standard document.
+ * All functions have one connection and one event as input argument. All of
+ * them return 0 On success and 1 otherwise.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <net/llc_conn.h>
+#include <net/llc_sap.h>
+#include <net/sock.h>
+#include <net/llc_main.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_c_st.h>
+#include <net/llc_pdu.h>
+#include <net/llc_mac.h>
+
+static void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data);
+static void llc_conn_ack_tmr_cb(unsigned long timeout_data);
+static void llc_conn_rej_tmr_cb(unsigned long timeout_data);
+static void llc_conn_busy_tmr_cb(unsigned long timeout_data);
+static int llc_conn_ac_inc_vs_by_1(struct sock *sk,
+ struct llc_conn_state_ev *ev);
+static void llc_process_tmr_ev(struct sock *sk, struct llc_conn_state_ev *ev);
+static int llc_conn_ac_data_confirm(struct sock *sk,
+ struct llc_conn_state_ev *ev);
+
+#define INCORRECT 0
+
+int llc_conn_ac_clear_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (llc->remote_busy_flag) {
+ u8 nr;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ llc->remote_busy_flag = 0;
+ del_timer(&llc->busy_state_timer.timer);
+ llc->busy_state_timer.running = 0;
+ nr = LLC_I_GET_NR(rx_pdu);
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
+ }
+ return 0;
+}
+
+int llc_conn_ac_conn_ind(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = ev->data.pdu.skb;
+ union llc_u_prim_data *prim_data = llc_ind_prim.data;
+ struct llc_prim_if_block *prim = &llc_ind_prim;
+ struct llc_sap *sap;
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc_pdu_decode_dsap(skb, &prim_data->conn.daddr.lsap);
+ sap = llc_sap_find(prim_data->conn.daddr.lsap);
+ if (sap) {
+ llc_pdu_decode_sa(skb, llc->daddr.mac);
+ llc_pdu_decode_da(skb, llc->laddr.mac);
+ llc->dev = skb->dev;
+ prim_data->conn.pri = 0;
+ prim_data->conn.sk = sk;
+ prim_data->conn.dev = skb->dev;
+ 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;
+ }
+ return rc;
+}
+
+int llc_conn_ac_conn_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ union llc_u_prim_data *prim_data = llc_cfm_prim.data;
+ struct sk_buff *skb = ev->data.pdu.skb;
+ /* FIXME: wtf, this is global, so the whole thing is really
+ * non reentrant...
+ */
+ struct llc_prim_if_block *prim = &llc_cfm_prim;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ prim_data->conn.sk = sk;
+ prim_data->conn.pri = 0;
+ prim_data->conn.status = ev->status;
+ prim_data->conn.link = llc->link;
+ if (skb)
+ prim_data->conn.dev = skb->dev;
+ else
+ printk(KERN_ERR __FUNCTION__ "ev->data.pdu.skb == NULL\n");
+ prim->data = prim_data;
+ prim->prim = LLC_CONN_PRIM;
+ prim->sap = sap;
+ ev->flag = 1;
+ ev->cfm_prim = prim;
+ return 0;
+}
+
+static int llc_conn_ac_data_confirm(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ struct llc_prim_if_block *prim = &llc_cfm_prim;
+ union llc_u_prim_data *prim_data = llc_cfm_prim.data;
+
+ prim_data->data.sk = sk;
+ prim_data->data.pri = 0;
+ prim_data->data.link = llc_sk(sk)->link;
+ prim_data->data.status = LLC_STATUS_RECEIVED;
+ prim_data->data.skb = NULL;
+ prim->data = prim_data;
+ prim->prim = LLC_DATA_PRIM;
+ prim->sap = llc_sk(sk)->sap;
+ ev->flag = 1;
+ ev->cfm_prim = prim;
+ return 0;
+}
+
+int llc_conn_ac_data_ind(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_conn_rtn_pdu(sk, ev->data.pdu.skb, ev);
+ return 0;
+}
+
+int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ u8 reason = 0;
+ int rc = 1;
+ union llc_u_prim_data *prim_data = llc_ind_prim.data;
+ struct llc_prim_if_block *prim = &llc_ind_prim;
+
+ if (ev->type == LLC_CONN_EV_TYPE_PDU) {
+ llc_pdu_un_t *rx_pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_RSP(rx_pdu) &&
+ !LLC_PDU_TYPE_IS_U(rx_pdu) &&
+ LLC_U_PDU_RSP(rx_pdu) == LLC_2_PDU_RSP_DM) {
+ reason = LLC_DISC_REASON_RX_DM_RSP_PDU;
+ rc = 0;
+ } else if (!LLC_PDU_IS_CMD(rx_pdu) &&
+ !LLC_PDU_TYPE_IS_U(rx_pdu) &&
+ LLC_U_PDU_CMD(rx_pdu) == LLC_2_PDU_CMD_DISC) {
+ reason = LLC_DISC_REASON_RX_DISC_CMD_PDU;
+ rc = 0;
+ }
+ } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR) {
+ reason = LLC_DISC_REASON_ACK_TMR_EXP;
+ rc = 0;
+ } else {
+ reason = 0;
+ rc = 1;
+ }
+ if (!rc) {
+ prim_data->disc.sk = sk;
+ prim_data->disc.reason = reason;
+ prim_data->disc.link = llc_sk(sk)->link;
+ prim->data = prim_data;
+ prim->prim = LLC_DISC_PRIM;
+ prim->sap = llc_sk(sk)->sap;
+ ev->flag = 1;
+ ev->ind_prim = prim;
+ }
+ return rc;
+}
+
+int llc_conn_ac_disc_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ union llc_u_prim_data *prim_data = llc_cfm_prim.data;
+ struct llc_prim_if_block *prim = &llc_cfm_prim;
+
+ prim_data->disc.sk = sk;
+ prim_data->disc.reason = ev->status;
+ prim_data->disc.link = llc_sk(sk)->link;
+ prim->data = prim_data;
+ prim->prim = LLC_DISC_PRIM;
+ prim->sap = llc_sk(sk)->sap;
+ ev->flag = 1;
+ ev->cfm_prim = prim;
+ return 0;
+}
+
+int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ u8 reason = 0;
+ int rc = 1;
+ llc_pdu_un_t *rx_pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+ union llc_u_prim_data *prim_data = llc_ind_prim.data;
+ struct llc_prim_if_block *prim = &llc_ind_prim;
+ struct llc_opt *llc = llc_sk(sk);
+
+ switch (ev->type) {
+ case LLC_CONN_EV_TYPE_PDU:
+ if (!LLC_PDU_IS_RSP(rx_pdu) &&
+ !LLC_PDU_TYPE_IS_U(rx_pdu) &&
+ LLC_U_PDU_RSP(rx_pdu) == LLC_2_PDU_RSP_FRMR) {
+ reason = LLC_RESET_REASON_LOCAL;
+ rc = 0;
+ } else if (!LLC_PDU_IS_CMD(rx_pdu) &&
+ !LLC_PDU_TYPE_IS_U(rx_pdu) &&
+ LLC_U_PDU_CMD(rx_pdu) ==
+ LLC_2_PDU_CMD_SABME) {
+ reason = LLC_RESET_REASON_REMOTE;
+ rc = 0;
+ } else {
+ reason = 0;
+ rc = 1;
+ }
+ break;
+ case LLC_CONN_EV_TYPE_ACK_TMR:
+ case LLC_CONN_EV_TYPE_P_TMR:
+ case LLC_CONN_EV_TYPE_REJ_TMR:
+ case LLC_CONN_EV_TYPE_BUSY_TMR:
+ if (llc->retry_count > llc->n2) {
+ reason = LLC_RESET_REASON_LOCAL;
+ rc = 0;
+ } else
+ rc = 1;
+ break;
+ }
+ if (!rc) {
+ prim_data->res.sk = sk;
+ prim_data->res.reason = reason;
+ prim_data->res.link = llc->link;
+ prim->data = prim_data;
+ prim->prim = LLC_RESET_PRIM;
+ prim->sap = llc->sap;
+ ev->flag = 1;
+ ev->ind_prim = prim;
+ }
+ return rc;
+}
+
+int llc_conn_ac_rst_confirm(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ union llc_u_prim_data *prim_data = llc_cfm_prim.data;
+ struct llc_prim_if_block *prim = &llc_cfm_prim;
+
+ prim_data->res.sk = sk;
+ prim_data->res.link = llc_sk(sk)->link;
+ prim->data = prim_data;
+ prim->prim = LLC_RESET_PRIM;
+ prim->sap = llc_sk(sk)->sap;
+ ev->flag = 1;
+ ev->cfm_prim = prim;
+ return 0;
+}
+
+int llc_conn_ac_report_status(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return 0;
+}
+
+int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_RSP(rx_pdu) &&
+ !LLC_PDU_TYPE_IS_I(rx_pdu) &&
+ !LLC_I_PF_IS_1(rx_pdu) && llc_sk(sk)->ack_pf)
+ llc_conn_ac_clear_remote_busy(sk, ev);
+ return 0;
+}
+
+int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ if (llc_sk(sk)->data_flag == 2) {
+ del_timer(&llc_sk(sk)->rej_sent_timer.timer);
+ llc_sk(sk)->rej_sent_timer.running = 0;
+ }
+ return 0;
+}
+
+int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ u8 p_bit = 1;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_disc_cmd(skb, p_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ llc_conn_ac_set_p_flag_1(sk, ev);
+ return rc;
+}
+
+int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ struct sk_buff *rx_skb = ev->data.pdu.skb;
+ u8 f_bit;
+
+ skb->dev = llc->dev;
+ llc_pdu_decode_pf_bit(rx_skb, &f_bit);
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_dm_rsp(skb, f_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_dm_rsp(skb, f_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_dm_rsp_f_set_f_flag(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = llc->f_flag;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_dm_rsp(skb, f_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 f_bit;
+ int rc = 1;
+ struct sk_buff *skb, *ev_skb = ev->data.pdu.skb;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev_skb->nh.raw;
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc->rx_pdu_hdr = (u32)*((u32 *)rx_pdu);
+ if (!LLC_PDU_IS_CMD(rx_pdu))
+ llc_pdu_decode_pf_bit(ev_skb, &f_bit);
+ else
+ f_bit = 0;
+ skb = llc_alloc_frame();
+ if (skb) {
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS,
+ llc->vR, INCORRECT);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ u8 f_bit = 0;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)&llc->rx_pdu_hdr;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS,
+ llc->vR, INCORRECT);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 f_bit;
+ int rc = 1;
+ struct sk_buff *skb;
+
+ llc_pdu_decode_pf_bit(ev->data.pdu.skb, &f_bit);
+ skb = llc_alloc_frame();
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS,
+ llc->vR, INCORRECT);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 p_bit = 1;
+ struct sk_buff *skb = ev->data.prim.data->data->data.skb;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, ev);
+ return 0;
+}
+
+int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 p_bit = 0;
+ struct sk_buff *skb = ev->data.prim.data->data->data.skb;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, ev);
+ return 0;
+}
+
+int llc_conn_ac_resend_i_cmd_p_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ u8 nr = LLC_I_GET_NR(rx_pdu);
+
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, 1);
+ return 0;
+}
+
+int llc_conn_ac_resend_i_cmd_p_set_1_or_send_rr(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ u8 nr = LLC_I_GET_NR(rx_pdu);
+ int rc = llc_conn_ac_send_rr_cmd_p_set_1(sk, ev);
+
+ if (!rc)
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
+ return rc;
+}
+
+int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 p_bit = 0;
+ struct sk_buff *skb = ev->data.prim.data->data->data.skb;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, ev);
+ return 0;
+}
+
+int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 nr = LLC_I_GET_NR(rx_pdu);
+
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
+ return 0;
+}
+
+int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 nr;
+ u8 f_bit = 0;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ if (rc) {
+ nr = LLC_I_GET_NR(rx_pdu);
+ rc = 0;
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, f_bit);
+ }
+ return rc;
+}
+
+int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 nr = LLC_I_GET_NR(rx_pdu);
+
+ llc_conn_resend_i_pdu_as_rsp(sk, nr, 1);
+ return 0;
+}
+
+int llc_conn_ac_send_rej_cmd_p_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 p_bit = 1;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rej_cmd(skb, p_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ u8 f_bit = 1;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rej_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 0;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rej_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 p_bit = 1;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rnr_cmd(skb, p_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rnr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ u8 f_bit = 0;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rnr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_set_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (!llc->remote_busy_flag) {
+ llc->remote_busy_flag = 1;
+ llc->busy_state_timer.timer.expires = jiffies +
+ llc->busy_state_timer.expire * HZ;
+ llc->busy_state_timer.timer.data = (unsigned long)sk;
+ llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
+ add_timer(&llc->busy_state_timer.timer);
+ llc->busy_state_timer.running = 1;
+ }
+ return 0;
+}
+
+int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 0;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rnr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ u8 p_bit = 1;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rr_cmd(skb, p_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_ack_cmd_p_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ u8 p_bit = 1;
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rr_cmd(skb, p_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 0;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 0;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+ struct llc_opt *llc = llc_sk(sk);
+ u8 p_bit = 1;
+
+ if (skb) {
+ struct llc_sap *sap = llc->sap;
+ u8 *dmac = llc->daddr.mac;
+
+ if (llc->dev->flags & IFF_LOOPBACK)
+ dmac = llc->dev->dev_addr;
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_sabme_cmd(skb, p_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, dmac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ llc->p_flag = p_bit;
+ return rc;
+}
+
+int llc_conn_ac_send_ua_rsp_f_set_f_flag(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = llc->f_flag;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_ua_rsp(skb, f_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 f_bit;
+ int rc = 1;
+ struct sk_buff *rx_skb = ev->data.pdu.skb;
+ struct sk_buff *skb;
+
+ llc_pdu_decode_pf_bit(rx_skb, &f_bit);
+ skb = llc_alloc_frame();
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_ua_rsp(skb, f_bit);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_set_s_flag_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->s_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_s_flag_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->s_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_start_p_timer(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc->p_flag = 1;
+ del_timer(&llc->pf_cycle_timer.timer);
+ llc->pf_cycle_timer.timer.expires = jiffies +
+ llc->pf_cycle_timer.expire * HZ;
+ llc->pf_cycle_timer.timer.data = (unsigned long)sk;
+ llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
+ add_timer(&llc->pf_cycle_timer.timer);
+ llc->pf_cycle_timer.running = 1;
+ return 0;
+}
+
+/**
+ * llc_conn_ac_send_ack_if_needed - check if ack is needed
+ * @sk: current connection structure
+ * @ev: current event
+ *
+ * Checks number of received PDUs which have not been acknowledged, yet,
+ * If number of them reaches to "npta"(Number of PDUs To Acknowledge) then
+ * sends an RR response as acknowledgement for them. Returns 0 for
+ * success, 1 otherwise.
+ */
+int llc_conn_ac_send_ack_if_needed(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u8 pf_bit;
+ struct sk_buff *skb = ev->data.pdu.skb;
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc_pdu_decode_pf_bit(skb, &pf_bit);
+ llc->ack_pf |= pf_bit & 1;
+ if (!llc->ack_must_be_send) {
+ llc->first_pdu_Ns = llc->vR;
+ llc->ack_must_be_send = 1;
+ llc->ack_pf = pf_bit & 1;
+ }
+ if (((llc->vR - llc->first_pdu_Ns + 129) % 128) >= llc->npta) {
+ llc_conn_ac_send_rr_rsp_f_set_ackpf(sk, ev);
+ llc->ack_must_be_send = 0;
+ llc->ack_pf = 0;
+ llc_conn_ac_inc_npta_value(sk, ev);
+ }
+ return 0;
+}
+
+/**
+ * llc_conn_ac_rst_sendack_flag - resets ack_must_be_send flag
+ * @sk: current connection structure
+ * @ev: current event
+ *
+ * This action resets ack_must_be_send flag of given connection, this flag
+ * indicates if there is any PDU which has not been acknowledged yet.
+ * Returns 0 for success, 1 otherwise.
+ */
+int llc_conn_ac_rst_sendack_flag(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->ack_must_be_send = llc_sk(sk)->ack_pf = 0;
+ return 0;
+}
+
+/**
+ * llc_conn_ac_send_i_rsp_f_set_ackpf - acknowledge received PDUs
+ * @sk: current connection structure
+ * @ev: current event
+ *
+ * Sends an I response PDU with f-bit set to ack_pf flag as acknowledge to
+ * all received PDUs which have not been acknowledged, yet. ack_pf flag is
+ * set to one if one PDU with p-bit set to one is received. Returns 0 for
+ * success, 1 otherwise.
+ */
+int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ struct sk_buff *skb = ev->data.prim.data->data->data.skb;
+ struct llc_opt *llc = llc_sk(sk);
+ u8 p_bit = llc->ack_pf;
+ struct llc_sap *sap = llc->sap;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_i_cmd(skb, p_bit, llc->vS, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, ev);
+ return 0;
+}
+
+/**
+ * llc_conn_ac_send_i_as_ack - sends an I-format PDU to acknowledge rx PDUs
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * This action sends an I-format PDU as acknowledge to received PDUs which
+ * have not been acknowledged, yet, if there is any. By using of this
+ * action number of acknowledgements decreases, this technic is called
+ * piggy backing. Returns 0 for success, 1 otherwise.
+ */
+int llc_conn_ac_send_i_as_ack(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (llc->ack_must_be_send) {
+ llc_conn_ac_send_i_rsp_f_set_ackpf(sk, ev);
+ llc->ack_must_be_send = 0 ;
+ llc->ack_pf = 0;
+ } else
+ llc_conn_ac_send_i_cmd_p_set_0(sk, ev);
+ return 0;
+}
+
+/**
+ * llc_conn_ac_send_rr_rsp_f_set_ackpf - ack all rx PDUs not yet acked
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * This action sends an RR response with f-bit set to ack_pf flag as
+ * acknowledge to all received PDUs which have not been acknowledged, yet,
+ * if there is any. ack_pf flag indicates if a PDU has been received with
+ * p-bit set to one. Returns 0 for success, 1 otherwise.
+ */
+int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct sk_buff *skb = llc_alloc_frame();
+
+ if (skb) {
+ struct llc_opt *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = llc->ack_pf;
+
+ skb->dev = llc->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(skb, f_bit, llc->vR);
+ lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ rc = 0;
+ llc_conn_send_pdu(sk, skb);
+ }
+ return rc;
+}
+
+/**
+ * llc_conn_ac_inc_npta_value - tries to make value of npta greater
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * After "inc_cntr" times calling of this action, "npta" increase by one.
+ * this action tries to make vale of "npta" greater as possible; number of
+ * acknowledgements decreases by increasing of "npta". Returns 0 for
+ * success, 1 otherwise.
+ */
+int llc_conn_ac_inc_npta_value(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (!llc->inc_cntr) {
+ llc->dec_step = 0;
+ llc->dec_cntr = llc->inc_cntr = 2;
+ ++llc->npta;
+ if (llc->npta > 127)
+ llc->npta = 127 ;
+ } else
+ --llc->inc_cntr;
+ return 0;
+}
+
+/**
+ * llc_conn_ac_adjust_npta_by_rr - decreases "npta" by one
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * After receiving "dec_cntr" times RR command, this action decreases
+ * "npta" by one. Returns 0 for success, 1 otherwise.
+ */
+int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (!llc->connect_step && !llc->remote_busy_flag) {
+ if (!llc->dec_step) {
+ if (!llc->dec_cntr) {
+ llc->inc_cntr = llc->dec_cntr = 2;
+ if (llc->npta > 0)
+ llc->npta = llc->npta - 1;
+ } else
+ llc->dec_cntr -=1;
+ }
+ } else
+ llc->connect_step = 0 ;
+ return 0;
+}
+
+/**
+ * llc_conn_ac_adjust_npta_by_rnr - decreases "npta" by one
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * After receiving "dec_cntr" times RNR command, this action decreases
+ * "npta" by one. Returns 0 for success, 1 otherwise.
+ */
+int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (llc->remote_busy_flag)
+ if (!llc->dec_step) {
+ if (!llc->dec_cntr) {
+ llc->inc_cntr = llc->dec_cntr = 2;
+ if (llc->npta > 0)
+ --llc->npta;
+ } else
+ --llc->dec_cntr;
+ }
+ return 0;
+}
+
+/**
+ * llc_conn_ac_dec_tx_win_size - decreases tx window size
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * After receiving of a REJ command or response, transmit window size is
+ * decreased by number of PDUs which are outstanding yet. Returns 0 for
+ * success, 1 otherwise.
+ */
+int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+ u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q);
+
+ llc->k -= unacked_pdu;
+ if (llc->k < 2)
+ llc->k = 2;
+ return 0;
+}
+
+/**
+ * llc_conn_ac_inc_tx_win_size - tx window size is inc by 1
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * After receiving an RR response with f-bit set to one, transmit window
+ * size is increased by one. Returns 0 for success, 1 otherwise.
+ */
+int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc->k += 1;
+ if (llc->k > 128)
+ llc->k = 128 ;
+ return 0;
+}
+
+int llc_conn_ac_stop_all_timers(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ del_timer(&llc->pf_cycle_timer.timer);
+ llc->pf_cycle_timer.running = 0;
+ del_timer(&llc->ack_timer.timer);
+ llc->ack_timer.running = 0;
+ del_timer(&llc->rej_sent_timer.timer);
+ llc->rej_sent_timer.running = 0;
+ del_timer(&llc->busy_state_timer.timer);
+ llc->busy_state_timer.running = 0;
+ llc->ack_must_be_send = 0;
+ llc->ack_pf = 0;
+ return 0;
+}
+
+int llc_conn_ac_stop_other_timers(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ del_timer(&llc->rej_sent_timer.timer);
+ llc->rej_sent_timer.running = 0;
+ del_timer(&llc->pf_cycle_timer.timer);
+ llc->pf_cycle_timer.running = 0;
+ del_timer(&llc->busy_state_timer.timer);
+ llc->busy_state_timer.running = 0;
+ llc->ack_must_be_send = 0;
+ llc->ack_pf = 0;
+ return 0;
+}
+
+int llc_conn_ac_start_ack_timer(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ del_timer(&llc->ack_timer.timer);
+ llc->ack_timer.timer.expires = jiffies + llc->ack_timer.expire * HZ;
+ llc->ack_timer.timer.data = (unsigned long)sk;
+ llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
+ add_timer(&llc->ack_timer.timer);
+ llc->ack_timer.running = 1;
+ return 0;
+}
+
+int llc_conn_ac_start_rej_timer(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ del_timer(&llc->rej_sent_timer.timer);
+ llc->rej_sent_timer.timer.expires = jiffies +
+ llc->rej_sent_timer.expire * HZ;
+ llc->rej_sent_timer.timer.data = (unsigned long)sk;
+ llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
+ add_timer(&llc->rej_sent_timer.timer);
+ llc->rej_sent_timer.running = 1;
+ return 0;
+}
+
+int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (!llc->ack_timer.running) {
+ llc->ack_timer.timer.expires = jiffies +
+ llc->ack_timer.expire * HZ;
+ llc->ack_timer.timer.data = (unsigned long)sk;
+ llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
+ add_timer(&llc->ack_timer.timer);
+ llc->ack_timer.running = 1;
+ }
+ return 0;
+}
+
+int llc_conn_ac_stop_ack_timer(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ del_timer(&llc_sk(sk)->ack_timer.timer);
+ llc_sk(sk)->ack_timer.running = 0;
+ return 0;
+}
+
+int llc_conn_ac_stop_p_timer(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ del_timer(&llc->pf_cycle_timer.timer);
+ llc->pf_cycle_timer.running = 0;
+ llc->p_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_stop_rej_timer(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ del_timer(&llc_sk(sk)->rej_sent_timer.timer);
+ llc_sk(sk)->rej_sent_timer.running = 0;
+ return 0;
+}
+
+int llc_conn_ac_upd_nr_received(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ int acked;
+ u16 unacked = 0;
+ u8 fbit;
+ struct sk_buff *skb = ev->data.pdu.skb;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc->last_nr = PDU_SUPV_GET_Nr(rx_pdu);
+ acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked);
+ /* On loopback we don't queue I frames in unack_pdu_q queue. */
+ if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) {
+ llc->retry_count = 0;
+ del_timer(&llc->ack_timer.timer);
+ llc->ack_timer.running = 0;
+ if (llc->failed_data_req) {
+ /* already, we did not accept data from upper layer
+ * (tx_window full or unacceptable state). Now, we
+ * can send data and must inform to upper layer.
+ */
+ llc->failed_data_req = 0;
+ llc_conn_ac_data_confirm(sk, ev);
+ }
+ if (unacked) {
+ llc->ack_timer.timer.expires = jiffies +
+ llc->ack_timer.expire * HZ;
+ llc->ack_timer.timer.data = (unsigned long)sk;
+ llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
+ add_timer(&llc->ack_timer.timer);
+ llc->ack_timer.running = 1;
+ }
+ } else if (llc->failed_data_req) {
+ llc_pdu_decode_pf_bit(skb, &fbit);
+ if (fbit == 1) {
+ llc->failed_data_req = 0;
+ llc_conn_ac_data_confirm(sk, ev);
+ }
+ }
+ return 0;
+}
+
+int llc_conn_ac_upd_p_flag(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct sk_buff *skb = ev->data.pdu.skb;
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ u8 f_bit;
+
+ if (!LLC_PDU_IS_RSP(rx_pdu) &&
+ !llc_pdu_decode_pf_bit(skb, &f_bit) && f_bit) {
+ llc_sk(sk)->p_flag = 0;
+ llc_conn_ac_stop_p_timer(sk, ev);
+ }
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_2(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->data_flag = 2;
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->data_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->data_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_1_if_data_flag_eq_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ if (!llc_sk(sk)->data_flag)
+ llc_sk(sk)->data_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_set_p_flag_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->p_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_p_flag_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->p_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->remote_busy_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->cause_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->cause_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->retry_count = 0;
+ return 0;
+}
+
+int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->retry_count++;
+ return 0;
+}
+
+int llc_conn_ac_set_vr_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->vR = 0;
+ return 0;
+}
+
+int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->vR = PDU_GET_NEXT_Vr(llc_sk(sk)->vR);
+ return 0;
+}
+
+int llc_conn_ac_set_vs_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->vS = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_vs_nr(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->vS = llc_sk(sk)->last_nr;
+ return 0;
+}
+
+int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128;
+ return 0;
+}
+
+int llc_conn_ac_set_f_flag_p(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_pdu_decode_pf_bit(ev->data.pdu.skb, &llc_sk(sk)->f_flag);
+ return 0;
+}
+
+void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
+{
+ struct sock *sk = (struct sock *)timeout_data;
+ struct llc_conn_state_ev *ev;
+
+ llc_sk(sk)->pf_cycle_timer.running = 0;
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_P_TMR;
+ ev->data.tmr.timer_specific = NULL;
+ llc_process_tmr_ev(sk, ev);
+ }
+}
+
+static void llc_conn_busy_tmr_cb(unsigned long timeout_data)
+{
+ struct sock *sk = (struct sock *)timeout_data;
+ struct llc_conn_state_ev *ev;
+
+ llc_sk(sk)->busy_state_timer.running = 0;
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_BUSY_TMR;
+ ev->data.tmr.timer_specific = NULL;
+ llc_process_tmr_ev(sk, ev);
+ }
+}
+
+void llc_conn_ack_tmr_cb(unsigned long timeout_data)
+{
+ struct sock* sk = (struct sock *)timeout_data;
+ struct llc_conn_state_ev *ev;
+
+ llc_sk(sk)->ack_timer.running = 0;
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_ACK_TMR;
+ ev->data.tmr.timer_specific = NULL;
+ llc_process_tmr_ev(sk, ev);
+ }
+}
+
+static void llc_conn_rej_tmr_cb(unsigned long timeout_data)
+{
+ struct sock *sk = (struct sock *)timeout_data;
+ struct llc_conn_state_ev *ev;
+
+ llc_sk(sk)->rej_sent_timer.running = 0;
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_REJ_TMR;
+ ev->data.tmr.timer_specific = NULL;
+ llc_process_tmr_ev(sk, ev);
+ }
+}
+
+int llc_conn_ac_rst_vs(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sk(sk)->X = llc_sk(sk)->vS;
+ llc_conn_ac_set_vs_nr(sk, ev);
+ return 0;
+}
+
+int llc_conn_ac_upd_vs(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 nr = PDU_SUPV_GET_Nr(rx_pdu);
+
+ if (llc_circular_between(llc_sk(sk)->vS, nr, llc_sk(sk)->X))
+ llc_conn_ac_set_vs_nr(sk, ev);
+ return 0;
+}
+
+/*
+ * Non-standard actions; these not contained in IEEE specification; for
+ * our own usage
+ */
+/**
+ * llc_conn_disc - removes connection from SAP list and frees it
+ * @sk: closed connection
+ * @ev: occurred event
+ *
+ * Returns 2, to indicate the state machine that the connection was freed.
+ */
+int llc_conn_disc(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sap_unassign_sock(llc_sk(sk)->sap, sk);
+ llc_sock_free(sk);
+ return 2;
+}
+
+/**
+ * llc_conn_reset - resets connection
+ * @sk : reseting connection.
+ * @ev: occurred event.
+ *
+ * Stop all timers, empty all queues and reset all flags.
+ */
+int llc_conn_reset(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ llc_sock_reset(sk);
+ return 0;
+}
+
+/**
+ * llc_circular_between - designates that b is between a and c or not
+ * @a: lower bound
+ * @b: element to see if is between a and b
+ * @c: upper bound
+ *
+ * This function designates that b is between a and c or not (for example,
+ * 0 is between 127 and 1). Returns 1 if b is between a and c, 0
+ * otherwise.
+ */
+u8 llc_circular_between(u8 a, u8 b, u8 c)
+{
+ b = b - a;
+ c = c - a;
+ return b <= c;
+}
+
+/**
+ * llc_process_tmr_ev - timer backend
+ * @sk: active connection
+ * @ev: occurred event
+ *
+ * This function is called from timer callback functions. When connection
+ * is busy (during sending a data frame) timer expiration event must be
+ * queued. Otherwise this event can be sent to connection state machine.
+ * Queued events will process by process_rxframes_events function after
+ * sending data frame. Returns 0 for success, 1 otherwise.
+ */
+static void llc_process_tmr_ev(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ bh_lock_sock(sk);
+ if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) {
+ printk(KERN_WARNING "timer called on closed connection\n");
+ llc_conn_free_ev(ev);
+ goto out;
+ }
+ if (!sk->lock.users)
+ llc_conn_send_ev(sk, ev);
+ else {
+ struct sk_buff *skb = alloc_skb(1, GFP_ATOMIC);
+
+ if (skb) {
+ skb->cb[0] = LLC_EVENT;
+ skb->data = (void *)ev;
+ sk_add_backlog(sk, skb);
+ } else
+ llc_conn_free_ev(ev);
+ }
+out:
+ bh_unlock_sock(sk);
+}
diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c
new file mode 100644
index 000000000000..7020bf5b8b02
--- /dev/null
+++ b/net/llc/llc_c_ev.c
@@ -0,0 +1,873 @@
+/*
+ * llc_c_ev.c - Connection component state transition event qualifiers
+ *
+ * A 'state' consists of a number of possible event matching functions,
+ * the actions associated with each being executed when that event is
+ * matched; a 'state machine' accepts events in a serial fashion from an
+ * event queue. Each event is passed to each successive event matching
+ * function until a match is made (the event matching function returns
+ * success, or '0') or the list of event matching functions is exhausted.
+ * If a match is made, the actions associated with the event are executed
+ * and the state is changed to that event's transition state. Before some
+ * events are recognized, even after a match has been made, a certain
+ * number of 'event qualifier' functions must also be executed. If these
+ * all execute successfully, then the event is finally executed.
+ *
+ * These event functions must return 0 for success, to show a matched
+ * event, of 1 if the event does not match. Event qualifier functions
+ * must return a 0 for success or a non-zero for failure. Each function
+ * is simply responsible for verifying one single thing and returning
+ * either a success or failure.
+ *
+ * All of followed event functions are described in 802.2 LLC Protocol
+ * standard document except two functions that we added that will explain
+ * in their comments, at below.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <net/llc_conn.h>
+#include <net/llc_sap.h>
+#include <net/sock.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_pdu.h>
+
+#if 0
+#define dprintk(args...) printk(KERN_DEBUG args)
+#else
+#define dprintk(args...)
+#endif
+
+extern u16 llc_circular_between(u8 a, u8 b, u8 c);
+
+/**
+ * llc_util_ns_inside_rx_window - check if sequence number is in rx window
+ * @ns: sequence number of received pdu.
+ * @vr: sequence number which receiver expects to receive.
+ * @rw: receive window size of receiver.
+ *
+ * Checks if sequence number of received PDU is in range of receive
+ * window. Returns 0 for success, 1 otherwise
+ */
+static u16 llc_util_ns_inside_rx_window(u8 ns, u8 vr, u8 rw)
+{
+ return !llc_circular_between(vr, ns,
+ (vr + rw - 1) % LLC_2_SEQ_NBR_MODULO);
+}
+
+/**
+ * llc_util_nr_inside_tx_window - check if sequence number is in tx window
+ * @sk: current connection.
+ * @nr: N(R) of received PDU.
+ *
+ * This routine checks if N(R) of received PDU is in range of transmit
+ * window; on the other hand checks if received PDU acknowledges some
+ * outstanding PDUs that are in transmit window. Returns 0 for success, 1
+ * otherwise.
+ */
+static u16 llc_util_nr_inside_tx_window(struct sock *sk, u8 nr)
+{
+ u8 nr1, nr2;
+ struct sk_buff *skb;
+ llc_pdu_sn_t *pdu;
+ struct llc_opt *llc = llc_sk(sk);
+ int rc = 0;
+
+ if (llc->dev->flags & IFF_LOOPBACK)
+ goto out;
+ rc = 1;
+ if (!skb_queue_len(&llc->pdu_unack_q))
+ goto out;
+ skb = skb_peek(&llc->pdu_unack_q);
+ pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ nr1 = LLC_I_GET_NS(pdu);
+ skb = skb_peek_tail(&llc->pdu_unack_q);
+ pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ nr2 = LLC_I_GET_NS(pdu);
+ rc = !llc_circular_between(nr1, nr, (nr2 + 1) % LLC_2_SEQ_NBR_MODULO);
+out:
+ return rc;
+}
+
+int llc_conn_ev_conn_req(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->data.prim.prim == LLC_CONN_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_conn_resp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->data.prim.prim == LLC_CONN_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_RESP ? 0 : 1;
+}
+
+int llc_conn_ev_data_req(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->data.prim.prim == LLC_DATA_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_disc_req(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->data.prim.prim == LLC_DISC_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_rst_req(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->data.prim.prim == LLC_RESET_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_rst_resp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->data.prim.prim == LLC_RESET_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_RESP ? 0 : 1;
+}
+
+int llc_conn_ev_local_busy_detected(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
+ ev->data.a.ev == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
+}
+
+int llc_conn_ev_local_busy_cleared(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
+ ev->data.a.ev == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
+}
+
+int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return 1;
+}
+
+int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC ? 0 : 1;
+}
+
+int llc_conn_ev_rx_dm_rsp_fbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM ? 0 : 1;
+}
+
+int llc_conn_ev_rx_frmr_rsp_fbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_cmd_pbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_0(pdu) &&
+ LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_cmd_pbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_1(pdu) &&
+ LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_0(pdu) && ns != vr &&
+ !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_1(pdu) && ns != vr &&
+ !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t * pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+ 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;
+ if (!rc)
+ dprintk(KERN_WARNING "rx_i_cmd_p_bit_set_x_inval_ns matched,"
+ "state = %d, ns = %d, vr = %d\n",
+ llc_sk(sk)->state, ns, vr);
+ return rc;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_0(pdu) &&
+ LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_1(pdu) &&
+ LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ LLC_I_GET_NS(pdu) == llc_sk(sk)->vR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_0(pdu) && ns != vr &&
+ !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
+ !LLC_I_PF_IS_1(pdu) && ns != vr &&
+ !llc_util_ns_inside_rx_window(ns, vr, llc_sk(sk)->rw) ? 0 : 1;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+
+ return !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;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vr = llc_sk(sk)->vR;
+ u8 ns = LLC_I_GET_NS(pdu);
+ 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;
+ if (!rc)
+ dprintk(KERN_WARNING "conn_ev_rx_i_rsp_fbit_set_x_inval_ns "
+ "matched : state = %d, ns = %d, vr = %d\n",
+ llc_sk(sk)->state, ns, vr);
+ return rc;
+}
+
+int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_0(pdu) &&
+ LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rej_cmd_pbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_1(pdu) &&
+ LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_REJ ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rej_rsp_fbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_0(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rej_rsp_fbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_1(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rej_rsp_fbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_REJ ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rnr_cmd_pbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_0(pdu) &&
+ LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rnr_cmd_pbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_1(pdu) &&
+ LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RNR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rnr_rsp_fbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_0(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rnr_rsp_fbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_1(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RNR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rr_cmd_pbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_0(pdu) &&
+ LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rr_cmd_pbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_1(pdu) &&
+ LLC_S_PDU_CMD(pdu) == LLC_2_PDU_CMD_RR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rr_rsp_fbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_0(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_rr_rsp_fbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_S(pdu) &&
+ !LLC_S_PF_IS_1(pdu) &&
+ LLC_S_PDU_RSP(pdu) == LLC_2_PDU_RSP_RR ? 0 : 1;
+}
+
+int llc_conn_ev_rx_sabme_cmd_pbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_CMD(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_SABME ? 0 : 1;
+}
+
+int llc_conn_ev_rx_ua_rsp_fbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return !LLC_PDU_IS_RSP(pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_UA ? 0 : 1;
+}
+
+int llc_conn_ev_rx_xxx_cmd_pbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_CMD(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) {
+ if (!LLC_I_PF_IS_1(pdu))
+ rc = 0;
+ } else if (!LLC_PDU_TYPE_IS_U(pdu) && !LLC_U_PF_IS_1(pdu))
+ rc = 0;
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_xxx_cmd_pbit_set_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_CMD(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) {
+ if (!LLC_I_PF_IS_0(pdu))
+ rc = 0;
+ } else if (!LLC_PDU_TYPE_IS_U(pdu))
+ switch (LLC_U_PDU_CMD(pdu)) {
+ case LLC_2_PDU_CMD_SABME:
+ case LLC_2_PDU_CMD_DISC:
+ if (!LLC_U_PF_IS_0(pdu))
+ rc = 0;
+ break;
+ }
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_xxx_cmd_pbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_CMD(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu))
+ rc = 0;
+ else if (!LLC_PDU_TYPE_IS_U(pdu))
+ switch (LLC_U_PDU_CMD(pdu)) {
+ case LLC_2_PDU_CMD_SABME:
+ case LLC_2_PDU_CMD_DISC:
+ rc = 0;
+ break;
+ }
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_xxx_rsp_fbit_set_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_RSP(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) {
+ if (!LLC_I_PF_IS_1(pdu))
+ rc = 0;
+ } else if (!LLC_PDU_TYPE_IS_U(pdu))
+ switch (LLC_U_PDU_RSP(pdu)) {
+ case LLC_2_PDU_RSP_UA:
+ case LLC_2_PDU_RSP_DM:
+ case LLC_2_PDU_RSP_FRMR:
+ if (!LLC_U_PF_IS_1(pdu))
+ rc = 0;
+ break;
+ }
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_xxx_rsp_fbit_set_x(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_IS_RSP(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu))
+ rc = 0;
+ else if (!LLC_PDU_TYPE_IS_U(pdu))
+ switch (LLC_U_PDU_RSP(pdu)) {
+ case LLC_2_PDU_RSP_UA:
+ case LLC_2_PDU_RSP_DM:
+ case LLC_2_PDU_RSP_FRMR:
+ rc = 0;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int llc_conn_ev_rx_xxx_yyy(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu))
+ rc = 0;
+ else if (!LLC_PDU_TYPE_IS_U(pdu))
+ switch (LLC_U_PDU_CMD(pdu)) {
+ case LLC_2_PDU_CMD_SABME:
+ case LLC_2_PDU_CMD_DISC:
+ case LLC_2_PDU_RSP_UA:
+ case LLC_2_PDU_RSP_DM:
+ case LLC_2_PDU_RSP_FRMR:
+ rc = 0;
+ break;
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vs = llc_sk(sk)->vS;
+ u8 nr = LLC_I_GET_NR(pdu);
+
+ if (!LLC_PDU_IS_CMD(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) {
+ if (nr != vs &&
+ llc_util_nr_inside_tx_window(sk, nr)) {
+ dprintk(KERN_ERR "conn_ev_rx_zzz_cmd_inv_nr "
+ "matched, state = %d, vs = %d, "
+ "nr = %d\n", llc_sk(sk)->state, vs, nr);
+ rc = 0;
+ }
+ }
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ u16 rc = 1;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+ u8 vs = llc_sk(sk)->vS;
+ u8 nr = LLC_I_GET_NR(pdu);
+
+ if (!LLC_PDU_IS_RSP(pdu)) {
+ if (!LLC_PDU_TYPE_IS_I(pdu) || !LLC_PDU_TYPE_IS_S(pdu)) {
+ if (nr != vs &&
+ llc_util_nr_inside_tx_window(sk, nr)) {
+ rc = 0;
+ dprintk(KERN_ERR "conn_ev_rx_zzz_fbit_set"
+ "_x_inval_nr matched, state = %d, "
+ "vs = %d, nr = %d\n",
+ llc_sk(sk)->state, vs, nr);
+ }
+ }
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_any_frame(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return 0;
+}
+
+int llc_conn_ev_p_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->type != LLC_CONN_EV_TYPE_P_TMR;
+}
+
+int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->type != LLC_CONN_EV_TYPE_ACK_TMR;
+}
+
+int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->type != LLC_CONN_EV_TYPE_REJ_TMR;
+}
+
+int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR;
+}
+
+int llc_conn_ev_any_tmr_exp(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+
+ return ev->type == LLC_CONN_EV_TYPE_P_TMR ||
+ ev->type == LLC_CONN_EV_TYPE_ACK_TMR ||
+ ev->type == LLC_CONN_EV_TYPE_REJ_TMR ||
+ ev->type == LLC_CONN_EV_TYPE_BUSY_TMR ? 0 : 1;
+}
+
+int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return 1;
+}
+
+int llc_conn_ev_tx_buffer_full(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
+ ev->data.a.ev == LLC_CONN_EV_TX_BUFF_FULL ? 0 : 1;
+}
+
+/* Event qualifier functions
+ *
+ * these functions simply verify the value of a state flag associated with
+ * the connection and return either a 0 for success or a non-zero value
+ * for not-success; verify the event is the type we expect
+ */
+int llc_conn_ev_qlfy_data_flag_eq_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->data_flag != 1;
+}
+
+int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->data_flag;
+}
+
+int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->data_flag != 2;
+}
+
+int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->p_flag != 1;
+}
+
+/**
+ * conn_ev_qlfy_last_frame_eq_1 - checks if frame is last in tx window
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * This function determines when frame which is sent, is last frame of
+ * transmit window, if it is then this function return zero else return
+ * one. This function is used for sending last frame of transmit window
+ * as I-format command with p-bit set to one. Returns 0 if frame is last
+ * frame, 1 otherwise.
+ */
+int llc_conn_ev_qlfy_last_frame_eq_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return !(skb_queue_len(&llc_sk(sk)->pdu_unack_q) + 1 == llc_sk(sk)->k);
+}
+
+/**
+ * conn_ev_qlfy_last_frame_eq_0 - checks if frame isn't last in tx window
+ * @sk: current connection structure.
+ * @ev: current event.
+ *
+ * This function determines when frame which is sent, isn't last frame of
+ * transmit window, if it isn't then this function return zero else return
+ * one. Returns 0 if frame isn't last frame, 1 otherwise.
+ */
+int llc_conn_ev_qlfy_last_frame_eq_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return skb_queue_len(&llc_sk(sk)->pdu_unack_q) + 1 == llc_sk(sk)->k;
+}
+
+int llc_conn_ev_qlfy_p_flag_eq_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->p_flag;
+}
+
+int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ u8 f_bit;
+ struct sk_buff *skb;
+
+ if (ev->type == LLC_CONN_EV_TYPE_PDU)
+ skb = ev->data.pdu.skb;
+ else
+ skb = ev->data.prim.data->data->conn.skb;
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ return llc_sk(sk)->p_flag == f_bit ? 0 : 1;
+}
+
+int llc_conn_ev_qlfy_remote_busy_eq_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->remote_busy_flag;
+}
+
+int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return !llc_sk(sk)->remote_busy_flag;
+}
+
+int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return !(llc_sk(sk)->retry_count < llc_sk(sk)->n2);
+}
+
+int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return !(llc_sk(sk)->retry_count >= llc_sk(sk)->n2);
+}
+
+int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return !llc_sk(sk)->s_flag;
+}
+
+int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->s_flag;
+}
+
+int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return !llc_sk(sk)->cause_flag;
+}
+
+int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return llc_sk(sk)->cause_flag;
+}
+
+int llc_conn_ev_qlfy_init_p_f_cycle(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_conn(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_CONN;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_disc(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_DISC;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_impossible(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_IMPOSSIBLE;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_failed(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_FAILED;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_REMOTE_BUSY;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_received(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_RECEIVED;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_REFUSE;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_CONFLICT;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk,
+ struct llc_conn_state_ev *ev)
+{
+ ev->status = LLC_STATUS_RESET_DONE;
+ return 0;
+}
diff --git a/net/llc/llc_c_st.c b/net/llc/llc_c_st.c
new file mode 100644
index 000000000000..ef52dc23ad13
--- /dev/null
+++ b/net/llc/llc_c_st.c
@@ -0,0 +1,4946 @@
+/*
+ * llc_c_st.c - This module contains state transition of connection component.
+ *
+ * Description of event functions and actions there is in 802.2 LLC standard,
+ * or in "llc_c_ac.c" and "llc_c_ev.c" modules.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001, 2002 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/types.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_c_st.h>
+
+#define NONE NULL
+
+/* COMMON CONNECTION STATE transitions
+ * Common transitions for
+ * LLC_CONN_STATE_NORMAL,
+ * LLC_CONN_STATE_BUSY,
+ * LLC_CONN_STATE_REJ,
+ * LLC_CONN_STATE_AWAIT,
+ * LLC_CONN_STATE_AWAIT_BUSY and
+ * LLC_CONN_STATE_AWAIT_REJ states
+ */
+/* State transitions for LLC_CONN_EV_DISC_REQ event */
+static llc_conn_action_t llc_common_actions_1[] = {
+ [0] = llc_conn_ac_send_disc_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_1 = {
+ .ev = llc_conn_ev_disc_req,
+ .next_state = LLC_CONN_STATE_D_CONN,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RESET_REQ event */
+static llc_conn_action_t llc_common_actions_2[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_2 = {
+ .ev = llc_conn_ev_rst_req,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_common_actions_3[] = {
+ [0] = llc_conn_ac_stop_all_timers,
+ [1] = llc_conn_ac_set_vs_0,
+ [2] = llc_conn_ac_set_vr_0,
+ [3] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [4] = llc_conn_ac_rst_ind,
+ [5] = llc_conn_ac_set_p_flag_0,
+ [6] = llc_conn_ac_set_remote_busy_0,
+ [7] = llc_conn_reset,
+ [8] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_3 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_common_actions_4[] = {
+ [0] = llc_conn_ac_stop_all_timers,
+ [1] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [2] = llc_conn_ac_disc_ind,
+ [3] = llc_conn_disc,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_4 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X event */
+static llc_conn_action_t llc_common_actions_5[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_rst_ind,
+ [5] = llc_conn_ac_set_cause_flag_0,
+ [6] = llc_conn_reset,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_5 = {
+ .ev = llc_conn_ev_rx_frmr_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event */
+static llc_conn_action_t llc_common_actions_6[] = {
+ [0] = llc_conn_ac_disc_ind,
+ [1] = llc_conn_ac_stop_all_timers,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_6 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_RX_ZZZ_CMD_Pbit_SET_X_INVAL_Nr event */
+static llc_conn_action_t llc_common_actions_7a[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_7a = {
+ .ev = llc_conn_ev_rx_zzz_cmd_pbit_set_x_inval_nr,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_7a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_X_INVAL_Ns event */
+static llc_conn_action_t llc_common_actions_7b[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_7b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_x_inval_ns,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_7b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_ZZZ_RSP_Fbit_SET_X_INVAL_Nr event */
+static llc_conn_action_t llc_common_actions_8a[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_8a = {
+ .ev = llc_conn_ev_rx_zzz_rsp_fbit_set_x_inval_nr,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_8a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_INVAL_Ns event */
+static llc_conn_action_t llc_common_actions_8b[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_8b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_x_inval_ns,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_8b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_BAD_PDU event */
+static llc_conn_action_t llc_common_actions_8c[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_8c = {
+ .ev = llc_conn_ev_rx_bad_pdu,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_8c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event */
+static llc_conn_action_t llc_common_actions_9[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_9 = {
+ .ev = llc_conn_ev_rx_ua_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_common_actions_9,
+};
+
+/* State transitions for LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_1 event */
+#if 0
+static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_10[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_common_actions_10[] = {
+ [0] = llc_conn_ac_send_frmr_rsp_f_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_10 = {
+ .ev = llc_conn_ev_rx_xxx_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = llc_common_ev_qfyrs_10,
+ .ev_actions = llc_common_actions_10,
+};
+#endif
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11a[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_common_actions_11a[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_0,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_11a = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_common_ev_qfyrs_11a,
+ .ev_actions = llc_common_actions_11a,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11b[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_common_actions_11b[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_0,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_11b = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_common_ev_qfyrs_11b,
+ .ev_actions = llc_common_actions_11b,
+};
+
+/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11c[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_common_actions_11c[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_0,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_11c = {
+ .ev = llc_conn_ev_rej_tmr_exp,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_common_ev_qfyrs_11c,
+ .ev_actions = llc_common_actions_11c,
+};
+
+/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_common_ev_qfyrs_11d[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_common_actions_11d[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_stop_other_timers,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_0,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_common_state_trans_11d = {
+ .ev = llc_conn_ev_busy_tmr_exp,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_common_ev_qfyrs_11d,
+ .ev_actions = llc_common_actions_11d,
+};
+
+/*
+ * Common dummy state transition; must be last entry for all state
+ * transition groups - it'll be on .bss, so will be zeroed.
+ */
+static struct llc_conn_state_trans llc_common_state_trans_n;
+
+/* LLC_CONN_STATE_ADM transitions */
+/* State transitions for LLC_CONN_EV_CONN_REQ event */
+static llc_conn_action_t llc_adm_actions_1[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_set_retry_cnt_0,
+ [3] = llc_conn_ac_set_s_flag_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_adm_state_trans_1 = {
+ .ev = llc_conn_ev_conn_req,
+ .next_state = LLC_CONN_STATE_SETUP,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_adm_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_adm_actions_2[] = {
+ [0] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [1] = llc_conn_ac_set_vs_0,
+ [2] = llc_conn_ac_set_vr_0,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_p_flag_0,
+ [5] = llc_conn_ac_set_remote_busy_0,
+ [6] = llc_conn_ac_conn_ind,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_adm_state_trans_2 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_adm_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_adm_actions_3[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_p,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_adm_state_trans_3 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_adm_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_adm_actions_4[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_1,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_adm_state_trans_4 = {
+ .ev = llc_conn_ev_rx_xxx_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_adm_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_XXX_YYY event */
+static llc_conn_action_t llc_adm_actions_5[] = {
+ [0] = llc_conn_disc,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_adm_state_trans_5 = {
+ .ev = llc_conn_ev_rx_any_frame,
+ .next_state = LLC_CONN_OUT_OF_SVC,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_adm_actions_5,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_adm_state_transitions[] = {
+ [0] = &llc_adm_state_trans_1, /* Request */
+ [1] = &llc_common_state_trans_n,
+ [2] = &llc_common_state_trans_n, /* local_busy */
+ [3] = &llc_common_state_trans_n, /* init_pf_cycle */
+ [4] = &llc_common_state_trans_n, /* timer */
+ [5] = &llc_adm_state_trans_2, /* Receive frame */
+ [6] = &llc_adm_state_trans_3,
+ [7] = &llc_adm_state_trans_4,
+ [8] = &llc_adm_state_trans_5,
+ [9] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_SETUP transitions */
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_setup_actions_1[] = {
+ [0] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [1] = llc_conn_ac_set_vs_0,
+ [2] = llc_conn_ac_set_vr_0,
+ [3] = llc_conn_ac_set_s_flag_1,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_1 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_SETUP,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_setup_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = llc_conn_ev_qlfy_set_status_conn,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_setup_actions_2[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_ac_set_vs_0,
+ [2] = llc_conn_ac_set_vr_0,
+ [3] = llc_conn_ac_upd_p_flag,
+ [4] = llc_conn_ac_set_remote_busy_0,
+ [5] = llc_conn_ac_conn_confirm,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_2 = {
+ .ev = llc_conn_ev_rx_ua_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_setup_ev_qfyrs_2,
+ .ev_actions = llc_setup_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_3[] = {
+ [0] = llc_conn_ev_qlfy_s_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_conn,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_setup_actions_3[] = {
+ [0] = llc_conn_ac_set_p_flag_0,
+ [1] = llc_conn_ac_set_remote_busy_0,
+ [2] = llc_conn_ac_conn_confirm,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_3 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_setup_ev_qfyrs_3,
+ .ev_actions = llc_setup_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_4[] = {
+ [0] = llc_conn_ev_qlfy_set_status_disc,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_setup_actions_4[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_p,
+ [1] = llc_conn_ac_stop_ack_timer,
+ [2] = llc_conn_ac_conn_confirm,
+ [3] = llc_conn_disc,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_4 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_setup_ev_qfyrs_4,
+ .ev_actions = llc_setup_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_5[] = {
+ [0] = llc_conn_ev_qlfy_set_status_disc,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_setup_actions_5[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_ac_conn_confirm,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_5 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_setup_ev_qfyrs_5,
+ .ev_actions = llc_setup_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_7[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = llc_conn_ev_qlfy_s_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_setup_actions_7[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_7 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_SETUP,
+ .ev_qualifiers = llc_setup_ev_qfyrs_7,
+ .ev_actions = llc_setup_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_setup_ev_qfyrs_8[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = llc_conn_ev_qlfy_s_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_set_status_failed,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_setup_actions_8[] = {
+ [0] = llc_conn_ac_conn_confirm,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_setup_state_trans_8 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_setup_ev_qfyrs_8,
+ .ev_actions = llc_setup_actions_8,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_setup_state_transitions[] = {
+ [0] = &llc_common_state_trans_n, /* Request */
+ [1] = &llc_common_state_trans_n, /* local busy */
+ [2] = &llc_common_state_trans_n, /* init_pf_cycle */
+ [3] = &llc_setup_state_trans_3, /* Timer */
+ [4] = &llc_setup_state_trans_7,
+ [5] = &llc_setup_state_trans_8,
+ [6] = &llc_common_state_trans_n,
+ [7] = &llc_setup_state_trans_1, /* Receive frame */
+ [8] = &llc_setup_state_trans_2,
+ [9] = &llc_setup_state_trans_4,
+ [10] = &llc_setup_state_trans_5,
+ [11] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_NORMAL transitions */
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_1[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_last_frame_eq_0,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_1[] = {
+ [0] = llc_conn_ac_send_i_as_ack,
+ [1] = llc_conn_ac_start_ack_tmr_if_not_running,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_1 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_1,
+ .ev_actions = llc_normal_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_last_frame_eq_1,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_2[] = {
+ [0] = llc_conn_ac_send_i_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_2 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_2,
+ .ev_actions = llc_normal_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_2_1[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_remote_busy,
+ [2] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_normal_actions_2_1[1];
+
+static struct llc_conn_state_trans llc_normal_state_trans_2_1 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_2_1,
+ .ev_actions = llc_normal_actions_2_1,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_3[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_3[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rnr_xxx_x_set_0,
+ [2] = llc_conn_ac_set_data_flag_0,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_3 = {
+ .ev = llc_conn_ev_local_busy_detected,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_normal_ev_qfyrs_3,
+ .ev_actions = llc_normal_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_4[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_4[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rnr_xxx_x_set_0,
+ [2] = llc_conn_ac_set_data_flag_0,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_4 = {
+ .ev = llc_conn_ev_local_busy_detected,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_normal_ev_qfyrs_4,
+ .ev_actions = llc_normal_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_5a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_5a[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_upd_p_flag,
+ [4] = llc_conn_ac_start_rej_timer,
+ [5] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_5a = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_normal_ev_qfyrs_5a,
+ .ev_actions = llc_normal_actions_5a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_5b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_5b[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_upd_p_flag,
+ [4] = llc_conn_ac_start_rej_timer,
+ [5] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_5b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_normal_ev_qfyrs_5b,
+ .ev_actions = llc_normal_actions_5b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_5c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_5c[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_upd_p_flag,
+ [4] = llc_conn_ac_start_rej_timer,
+ [5] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_5c = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_normal_ev_qfyrs_5c,
+ .ev_actions = llc_normal_actions_5c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_6a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_6a[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_start_rej_timer,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_6a = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_normal_ev_qfyrs_6a,
+ .ev_actions = llc_normal_actions_6a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_6b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_6b[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_start_rej_timer,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_6b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_normal_ev_qfyrs_6b,
+ .ev_actions = llc_normal_actions_6b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_normal_actions_7[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rej_rsp_f_set_1,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_start_rej_timer,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_7 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_8a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_8[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [5] = llc_conn_ac_send_ack_if_needed,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_8a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_8a,
+ .ev_actions = llc_normal_actions_8,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_8b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_8b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_8b,
+ .ev_actions = llc_normal_actions_8,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_9a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_9a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_data_ind,
+ [3] = llc_conn_ac_send_ack_if_needed,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_9a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_9a,
+ .ev_actions = llc_normal_actions_9a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_9b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_9b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_data_ind,
+ [3] = llc_conn_ac_send_ack_if_needed,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_9b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_9b,
+ .ev_actions = llc_normal_actions_9b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_normal_actions_10[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_send_ack_rsp_f_set_1,
+ [2] = llc_conn_ac_rst_sendack_flag,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_data_ind,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_10 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_10,
+};
+
+/* State transitions for * LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_normal_actions_11a[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_11a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_11a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_normal_actions_11b[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_11b = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_11b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_11c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_11c[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_inc_tx_win_size,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_11c = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_11c,
+ .ev_actions = llc_normal_actions_11c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_normal_actions_12[] = {
+ [0] = llc_conn_ac_send_ack_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_adjust_npta_by_rr,
+ [3] = llc_conn_ac_rst_sendack_flag,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_12 = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_12,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_normal_actions_13a[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_13a = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_13a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_normal_actions_13b[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_13b = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_13b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_13c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_13c[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_13c = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_13c,
+ .ev_actions = llc_normal_actions_13c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_normal_actions_14[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_adjust_npta_by_rnr,
+ [3] = llc_conn_ac_rst_sendack_flag,
+ [4] = llc_conn_ac_set_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_14 = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_14,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_15a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_15a[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_dec_tx_win_size,
+ [4] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [5] = llc_conn_ac_clear_remote_busy,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_15a = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_15a,
+ .ev_actions = llc_normal_actions_15a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_15b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_15b[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_dec_tx_win_size,
+ [4] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [5] = llc_conn_ac_clear_remote_busy,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_15b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_15b,
+ .ev_actions = llc_normal_actions_15b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_16a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_16a[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_dec_tx_win_size,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_16a = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_16a,
+ .ev_actions = llc_normal_actions_16a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_16b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_16b[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_dec_tx_win_size,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_16b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_16b,
+ .ev_actions = llc_normal_actions_16b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_normal_actions_17[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_dec_tx_win_size,
+ [3] = llc_conn_ac_resend_i_rsp_f_set_1,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_17 = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_normal_actions_17,
+};
+
+/* State transitions for LLC_CONN_EV_INIT_P_F_CYCLE event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_18[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_18[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_18 = {
+ .ev = llc_conn_ev_init_p_f_cycle,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_18,
+ .ev_actions = llc_normal_actions_18,
+};
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_19[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_19[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [2] = llc_conn_ac_rst_vs,
+ [3] = llc_conn_ac_start_p_timer,
+ [4] = llc_conn_ac_inc_retry_cnt_by_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_19 = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = llc_normal_ev_qfyrs_19,
+ .ev_actions = llc_normal_actions_19,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_20a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_20a[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [2] = llc_conn_ac_rst_vs,
+ [3] = llc_conn_ac_start_p_timer,
+ [4] = llc_conn_ac_inc_retry_cnt_by_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_20a = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = llc_normal_ev_qfyrs_20a,
+ .ev_actions = llc_normal_actions_20a,
+};
+
+/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_20b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_20b[] = {
+ [0] = llc_conn_ac_rst_sendack_flag,
+ [1] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [2] = llc_conn_ac_rst_vs,
+ [3] = llc_conn_ac_start_p_timer,
+ [4] = llc_conn_ac_inc_retry_cnt_by_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_20b = {
+ .ev = llc_conn_ev_busy_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = llc_normal_ev_qfyrs_20b,
+ .ev_actions = llc_normal_actions_20b,
+};
+
+/* State transitions for LLC_CONN_EV_TX_BUFF_FULL event */
+static llc_conn_ev_qfyr_t llc_normal_ev_qfyrs_21[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_normal_actions_21[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_normal_state_trans_21 = {
+ .ev = llc_conn_ev_tx_buffer_full,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_normal_ev_qfyrs_21,
+ .ev_actions = llc_normal_actions_21,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_normal_state_transitions[] = {
+ [0] = &llc_normal_state_trans_1, /* Requests */
+ [1] = &llc_normal_state_trans_2,
+ [2] = &llc_normal_state_trans_2_1,
+ [3] = &llc_common_state_trans_1,
+ [4] = &llc_common_state_trans_2,
+ [5] = &llc_common_state_trans_n,
+ [6] = &llc_normal_state_trans_21,
+ [7] = &llc_normal_state_trans_3, /* Local busy */
+ [8] = &llc_normal_state_trans_4,
+ [9] = &llc_common_state_trans_n,
+ [10] = &llc_normal_state_trans_18, /* Init pf cycle */
+ [11] = &llc_common_state_trans_n,
+ [12] = &llc_common_state_trans_11a, /* Timers */
+ [13] = &llc_common_state_trans_11b,
+ [14] = &llc_common_state_trans_11c,
+ [15] = &llc_common_state_trans_11d,
+ [16] = &llc_normal_state_trans_19,
+ [17] = &llc_normal_state_trans_20a,
+ [18] = &llc_normal_state_trans_20b,
+ [19] = &llc_common_state_trans_n,
+ [20] = &llc_normal_state_trans_8b, /* Receive frames */
+ [21] = &llc_normal_state_trans_9b,
+ [22] = &llc_normal_state_trans_10,
+ [23] = &llc_normal_state_trans_11b,
+ [24] = &llc_normal_state_trans_11c,
+ [25] = &llc_normal_state_trans_5a,
+ [26] = &llc_normal_state_trans_5b,
+ [27] = &llc_normal_state_trans_5c,
+ [28] = &llc_normal_state_trans_6a,
+ [29] = &llc_normal_state_trans_6b,
+ [30] = &llc_normal_state_trans_7,
+ [31] = &llc_normal_state_trans_8a,
+ [32] = &llc_normal_state_trans_9a,
+ [33] = &llc_normal_state_trans_11a,
+ [34] = &llc_normal_state_trans_12,
+ [35] = &llc_normal_state_trans_13a,
+ [36] = &llc_normal_state_trans_13b,
+ [37] = &llc_normal_state_trans_13c,
+ [38] = &llc_normal_state_trans_14,
+ [39] = &llc_normal_state_trans_15a,
+ [40] = &llc_normal_state_trans_15b,
+ [41] = &llc_normal_state_trans_16a,
+ [42] = &llc_normal_state_trans_16b,
+ [43] = &llc_normal_state_trans_17,
+ [44] = &llc_common_state_trans_3,
+ [45] = &llc_common_state_trans_4,
+ [46] = &llc_common_state_trans_5,
+ [47] = &llc_common_state_trans_6,
+ [48] = &llc_common_state_trans_7a,
+ [49] = &llc_common_state_trans_7b,
+ [50] = &llc_common_state_trans_8a,
+ [51] = &llc_common_state_trans_8b,
+ [52] = &llc_common_state_trans_8c,
+ [53] = &llc_common_state_trans_9,
+ /* [54] = &llc_common_state_trans_10, */
+ [54] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_BUSY transitions */
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_1[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_1[] = {
+ [0] = llc_conn_ac_send_i_xxx_x_set_0,
+ [1] = llc_conn_ac_start_ack_tmr_if_not_running,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_1 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_1,
+ .ev_actions = llc_busy_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_2[] = {
+ [0] = llc_conn_ac_send_i_xxx_x_set_0,
+ [1] = llc_conn_ac_start_ack_tmr_if_not_running,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_2 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_2,
+ .ev_actions = llc_busy_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_2_1[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_remote_busy,
+ [2] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_busy_actions_2_1[1];
+
+static struct llc_conn_state_trans llc_busy_state_trans_2_1 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_2_1,
+ .ev_actions = llc_busy_actions_2_1,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_3[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_3[] = {
+ [0] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [1] = llc_conn_ac_start_rej_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_3 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_busy_ev_qfyrs_3,
+ .ev_actions = llc_busy_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_4[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_4[] = {
+ [0] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [1] = llc_conn_ac_start_rej_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_4 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_busy_ev_qfyrs_4,
+ .ev_actions = llc_busy_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_5[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_5[] = {
+ [0] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_5 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_busy_ev_qfyrs_5,
+ .ev_actions = llc_busy_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_6[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_6[] = {
+ [0] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_6 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_busy_ev_qfyrs_6,
+ .ev_actions = llc_busy_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_7[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_2,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_7[] = {
+ [0] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_7 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_busy_ev_qfyrs_7,
+ .ev_actions = llc_busy_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_8[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_2,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_8[] = {
+ [0] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_8 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_busy_ev_qfyrs_8,
+ .ev_actions = llc_busy_actions_8,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_9a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_9a[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_p_flag,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_set_data_flag_1_if_data_flag_eq_0,
+ [4] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_9a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_x_unexpd_ns,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_9a,
+ .ev_actions = llc_busy_actions_9a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_9b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_9b[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_p_flag,
+ [2] = llc_conn_ac_upd_nr_received,
+ [3] = llc_conn_ac_set_data_flag_1_if_data_flag_eq_0,
+ [4] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_9b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_9b,
+ .ev_actions = llc_busy_actions_9b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_10a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_10a[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_data_flag_1_if_data_flag_eq_0,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_10a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_10a,
+ .ev_actions = llc_busy_actions_10a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_10b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_10b[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_data_flag_1_if_data_flag_eq_0,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_10b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_10b,
+ .ev_actions = llc_busy_actions_10b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_busy_actions_11[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_data_flag_1_if_data_flag_eq_0,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_11 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_11,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_busy_actions_12[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2,
+ [5] = llc_conn_ac_set_data_flag_0,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_12 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_12,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_13a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_13a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2,
+ [6] = llc_conn_ac_set_data_flag_0,
+ [7] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [8] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_13a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_13a,
+ .ev_actions = llc_busy_actions_13a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_13b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_13b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2,
+ [6] = llc_conn_ac_set_data_flag_0,
+ [7] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [8] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_13b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_13b,
+ .ev_actions = llc_busy_actions_13b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_14a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_14a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2,
+ [5] = llc_conn_ac_set_data_flag_0,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_14a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_14a,
+ .ev_actions = llc_busy_actions_14a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_14b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_14b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2,
+ [5] = llc_conn_ac_set_data_flag_0,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_14b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_14b,
+ .ev_actions = llc_busy_actions_14b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_busy_actions_15a[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_15a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_15a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_busy_actions_15b[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_15b = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_15b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_15c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_15c[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_15c = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_15c,
+ .ev_actions = llc_busy_actions_15c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_busy_actions_16[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_16 = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_16,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_busy_actions_17a[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_17a = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_17a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_busy_actions_17b[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_17b = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_17b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_17c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_17c[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_17c = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_17c,
+ .ev_actions = llc_busy_actions_17c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_busy_actions_18[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_18 = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_18,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_19a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_19a[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_19a = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_19a,
+ .ev_actions = llc_busy_actions_19a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_19b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_19b[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_19b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_19b,
+ .ev_actions = llc_busy_actions_19b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_20a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_20a[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_20a = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_20a,
+ .ev_actions = llc_busy_actions_20a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_20b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_20b[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_20b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_20b,
+ .ev_actions = llc_busy_actions_20b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_busy_actions_21[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_21 = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_busy_actions_21,
+};
+
+/* State transitions for LLC_CONN_EV_INIT_P_F_CYCLE event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_22[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_22[] = {
+ [0] = llc_conn_ac_send_rnr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_22 = {
+ .ev = llc_conn_ev_init_p_f_cycle,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_22,
+ .ev_actions = llc_busy_actions_22,
+};
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_23[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_23[] = {
+ [0] = llc_conn_ac_send_rnr_cmd_p_set_1,
+ [1] = llc_conn_ac_rst_vs,
+ [2] = llc_conn_ac_start_p_timer,
+ [3] = llc_conn_ac_inc_retry_cnt_by_1,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_23 = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_23,
+ .ev_actions = llc_busy_actions_23,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_24a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_24a[] = {
+ [0] = llc_conn_ac_send_rnr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = llc_conn_ac_rst_vs,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_24a = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_24a,
+ .ev_actions = llc_busy_actions_24a,
+};
+
+/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_24b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_24b[] = {
+ [0] = llc_conn_ac_send_rnr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = llc_conn_ac_rst_vs,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_24b = {
+ .ev = llc_conn_ev_busy_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_24b,
+ .ev_actions = llc_busy_actions_24b,
+};
+
+/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_25[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_25[] = {
+ [0] = llc_conn_ac_send_rnr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = llc_conn_ac_rst_vs,
+ [4] = llc_conn_ac_set_data_flag_1,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_25 = {
+ .ev = llc_conn_ev_rej_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_25,
+ .ev_actions = llc_busy_actions_25,
+};
+
+/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_busy_ev_qfyrs_26[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_busy_actions_26[] = {
+ [0] = llc_conn_ac_set_data_flag_1,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_busy_state_trans_26 = {
+ .ev = llc_conn_ev_rej_tmr_exp,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_busy_ev_qfyrs_26,
+ .ev_actions = llc_busy_actions_26,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_busy_state_transitions[] = {
+ [0] = &llc_common_state_trans_1, /* Request */
+ [1] = &llc_common_state_trans_2,
+ [2] = &llc_busy_state_trans_1,
+ [3] = &llc_busy_state_trans_2,
+ [4] = &llc_busy_state_trans_2_1,
+ [5] = &llc_common_state_trans_n,
+ [6] = &llc_busy_state_trans_3, /* Local busy */
+ [7] = &llc_busy_state_trans_4,
+ [8] = &llc_busy_state_trans_5,
+ [9] = &llc_busy_state_trans_6,
+ [10] = &llc_busy_state_trans_7,
+ [11] = &llc_busy_state_trans_8,
+ [12] = &llc_common_state_trans_n,
+ [13] = &llc_busy_state_trans_22, /* Initiate PF cycle */
+ [14] = &llc_common_state_trans_n,
+ [15] = &llc_common_state_trans_11a, /* Timer */
+ [16] = &llc_common_state_trans_11b,
+ [17] = &llc_common_state_trans_11c,
+ [18] = &llc_common_state_trans_11d,
+ [19] = &llc_busy_state_trans_23,
+ [20] = &llc_busy_state_trans_24a,
+ [21] = &llc_busy_state_trans_24b,
+ [22] = &llc_busy_state_trans_25,
+ [23] = &llc_busy_state_trans_26,
+ [24] = &llc_common_state_trans_n,
+ [25] = &llc_busy_state_trans_9a, /* Receive frame */
+ [26] = &llc_busy_state_trans_9b,
+ [27] = &llc_busy_state_trans_10a,
+ [28] = &llc_busy_state_trans_10b,
+ [29] = &llc_busy_state_trans_11,
+ [30] = &llc_busy_state_trans_12,
+ [31] = &llc_busy_state_trans_13a,
+ [32] = &llc_busy_state_trans_13b,
+ [33] = &llc_busy_state_trans_14a,
+ [34] = &llc_busy_state_trans_14b,
+ [35] = &llc_busy_state_trans_15a,
+ [36] = &llc_busy_state_trans_15b,
+ [37] = &llc_busy_state_trans_15c,
+ [38] = &llc_busy_state_trans_16,
+ [39] = &llc_busy_state_trans_17a,
+ [40] = &llc_busy_state_trans_17b,
+ [41] = &llc_busy_state_trans_17c,
+ [42] = &llc_busy_state_trans_18,
+ [43] = &llc_busy_state_trans_19a,
+ [44] = &llc_busy_state_trans_19b,
+ [45] = &llc_busy_state_trans_20a,
+ [46] = &llc_busy_state_trans_20b,
+ [47] = &llc_busy_state_trans_21,
+ [48] = &llc_common_state_trans_3,
+ [49] = &llc_common_state_trans_4,
+ [50] = &llc_common_state_trans_5,
+ [51] = &llc_common_state_trans_6,
+ [52] = &llc_common_state_trans_7a,
+ [53] = &llc_common_state_trans_7b,
+ [54] = &llc_common_state_trans_8a,
+ [55] = &llc_common_state_trans_8b,
+ [56] = &llc_common_state_trans_8c,
+ [57] = &llc_common_state_trans_9,
+ /* [58] = &llc_common_state_trans_10, */
+ [58] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_REJ transitions */
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_1[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_1[] = {
+ [0] = llc_conn_ac_send_i_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_1 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_1,
+ .ev_actions = llc_reject_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_0,
+ [1] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_2[] = {
+ [0] = llc_conn_ac_send_i_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_2 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_2,
+ .ev_actions = llc_reject_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_2_1[] = {
+ [0] = llc_conn_ev_qlfy_remote_busy_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_remote_busy,
+ [2] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_reject_actions_2_1[1];
+
+static struct llc_conn_state_trans llc_reject_state_trans_2_1 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_2_1,
+ .ev_actions = llc_reject_actions_2_1,
+};
+
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_3[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_3[] = {
+ [0] = llc_conn_ac_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_set_data_flag_2,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_3 = {
+ .ev = llc_conn_ev_local_busy_detected,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_reject_ev_qfyrs_3,
+ .ev_actions = llc_reject_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_4[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_4[] = {
+ [0] = llc_conn_ac_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_set_data_flag_2,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_4 = {
+ .ev = llc_conn_ev_local_busy_detected,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = llc_reject_ev_qfyrs_4,
+ .ev_actions = llc_reject_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_reject_actions_5a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_p_flag,
+ [2] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_5a = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_5a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_reject_actions_5b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_p_flag,
+ [2] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_5b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_5b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_5c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_5c[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_p_flag,
+ [2] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_5c = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_5c,
+ .ev_actions = llc_reject_actions_5c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_reject_actions_6[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_6 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_7a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_7a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_send_ack_xxx_x_set_0,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [6] = llc_conn_ac_stop_rej_timer,
+ [7] = NULL,
+
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_7a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_reject_ev_qfyrs_7a,
+ .ev_actions = llc_reject_actions_7a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_7b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_7b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_send_ack_xxx_x_set_0,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_clear_remote_busy_if_f_eq_1,
+ [6] = llc_conn_ac_stop_rej_timer,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_7b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_reject_ev_qfyrs_7b,
+ .ev_actions = llc_reject_actions_7b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_8a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_8a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_ack_xxx_x_set_0,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_stop_rej_timer,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_8a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_reject_ev_qfyrs_8a,
+ .ev_actions = llc_reject_actions_8a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_8b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_8b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_ack_xxx_x_set_0,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_stop_rej_timer,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_8b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_reject_ev_qfyrs_8b,
+ .ev_actions = llc_reject_actions_8b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_reject_actions_9[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_ack_rsp_f_set_1,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_stop_rej_timer,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_9 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_9,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_reject_actions_10a[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_10a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_10a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_reject_actions_10b[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_10b = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_10b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_10c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_10c[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_10c = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_10c,
+ .ev_actions = llc_reject_actions_10c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_reject_actions_11[] = {
+ [0] = llc_conn_ac_send_ack_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_11 = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_11,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_reject_actions_12a[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_12a = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_12a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_reject_actions_12b[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_12b = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_12b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_12c[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_12c[] = {
+ [0] = llc_conn_ac_upd_p_flag,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_12c = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_12c,
+ .ev_actions = llc_reject_actions_12c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_reject_actions_13[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_13 = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_13,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_14a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_14a[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_14a = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_14a,
+ .ev_actions = llc_reject_actions_14a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_X event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_14b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_14b[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_p_flag,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_14b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_14b,
+ .ev_actions = llc_reject_actions_14b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_15a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_15a[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_15a = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_15a,
+ .ev_actions = llc_reject_actions_15a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_15b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_15b[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_15b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_15b,
+ .ev_actions = llc_reject_actions_15b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_reject_actions_16[] = {
+ [0] = llc_conn_ac_set_vs_nr,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_resend_i_rsp_f_set_1,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_16 = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_reject_actions_16,
+};
+
+/* State transitions for LLC_CONN_EV_INIT_P_F_CYCLE event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_17[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_17[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_17 = {
+ .ev = llc_conn_ev_init_p_f_cycle,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_17,
+ .ev_actions = llc_reject_actions_17,
+};
+
+/* State transitions for LLC_CONN_EV_REJ_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_18[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_18[] = {
+ [0] = llc_conn_ac_send_rej_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_start_rej_timer,
+ [3] = llc_conn_ac_inc_retry_cnt_by_1,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_18 = {
+ .ev = llc_conn_ev_rej_tmr_exp,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_18,
+ .ev_actions = llc_reject_actions_18,
+};
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_19[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_19[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_start_rej_timer,
+ [3] = llc_conn_ac_inc_retry_cnt_by_1,
+ [4] = llc_conn_ac_rst_vs,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_19 = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_19,
+ .ev_actions = llc_reject_actions_19,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_20a[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_20a[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_start_rej_timer,
+ [3] = llc_conn_ac_inc_retry_cnt_by_1,
+ [4] = llc_conn_ac_rst_vs,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_20a = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_20a,
+ .ev_actions = llc_reject_actions_20a,
+};
+
+/* State transitions for LLC_CONN_EV_BUSY_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_reject_ev_qfyrs_20b[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_reject_actions_20b[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_start_rej_timer,
+ [3] = llc_conn_ac_inc_retry_cnt_by_1,
+ [4] = llc_conn_ac_rst_vs,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_reject_state_trans_20b = {
+ .ev = llc_conn_ev_busy_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_reject_ev_qfyrs_20b,
+ .ev_actions = llc_reject_actions_20b,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_reject_state_transitions[] = {
+ [0] = &llc_common_state_trans_1, /* Request */
+ [1] = &llc_common_state_trans_2,
+ [2] = &llc_common_state_trans_n,
+ [3] = &llc_reject_state_trans_1,
+ [4] = &llc_reject_state_trans_2,
+ [5] = &llc_reject_state_trans_2_1,
+ [6] = &llc_reject_state_trans_3, /* Local busy */
+ [7] = &llc_reject_state_trans_4,
+ [8] = &llc_common_state_trans_n,
+ [9] = &llc_reject_state_trans_17, /* Initiate PF cycle */
+ [10] = &llc_common_state_trans_n,
+ [11] = &llc_common_state_trans_11a, /* Timer */
+ [12] = &llc_common_state_trans_11b,
+ [13] = &llc_common_state_trans_11c,
+ [14] = &llc_common_state_trans_11d,
+ [15] = &llc_reject_state_trans_18,
+ [16] = &llc_reject_state_trans_19,
+ [17] = &llc_reject_state_trans_20a,
+ [18] = &llc_reject_state_trans_20b,
+ [19] = &llc_common_state_trans_n,
+ [20] = &llc_common_state_trans_3, /* Receive frame */
+ [21] = &llc_common_state_trans_4,
+ [22] = &llc_common_state_trans_5,
+ [23] = &llc_common_state_trans_6,
+ [24] = &llc_common_state_trans_7a,
+ [25] = &llc_common_state_trans_7b,
+ [26] = &llc_common_state_trans_8a,
+ [27] = &llc_common_state_trans_8b,
+ [28] = &llc_common_state_trans_8c,
+ [29] = &llc_common_state_trans_9,
+ /* [30] = &llc_common_state_trans_10, */
+ [30] = &llc_reject_state_trans_5a,
+ [31] = &llc_reject_state_trans_5b,
+ [32] = &llc_reject_state_trans_5c,
+ [33] = &llc_reject_state_trans_6,
+ [34] = &llc_reject_state_trans_7a,
+ [35] = &llc_reject_state_trans_7b,
+ [36] = &llc_reject_state_trans_8a,
+ [37] = &llc_reject_state_trans_8b,
+ [38] = &llc_reject_state_trans_9,
+ [40] = &llc_reject_state_trans_10a,
+ [41] = &llc_reject_state_trans_10b,
+ [42] = &llc_reject_state_trans_10c,
+ [43] = &llc_reject_state_trans_11,
+ [44] = &llc_reject_state_trans_12a,
+ [45] = &llc_reject_state_trans_12b,
+ [46] = &llc_reject_state_trans_12c,
+ [47] = &llc_reject_state_trans_13,
+ [48] = &llc_reject_state_trans_14a,
+ [49] = &llc_reject_state_trans_14b,
+ [50] = &llc_reject_state_trans_15a,
+ [51] = &llc_reject_state_trans_15b,
+ [52] = &llc_reject_state_trans_16,
+ [53] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_AWAIT transitions */
+/* State transitions for LLC_CONN_EV_DATA_REQ event */
+static llc_conn_ev_qfyr_t llc_await_ev_qfyrs_1_0[] = {
+ [0] = llc_conn_ev_qlfy_set_status_refuse,
+ [1] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_await_actions_1_0[1];
+
+static struct llc_conn_state_trans llc_await_state_trans_1_0 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = llc_await_ev_qfyrs_1_0,
+ .ev_actions = llc_await_actions_1_0,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */
+static llc_conn_action_t llc_await_actions_1[] = {
+ [0] = llc_conn_ac_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_set_data_flag_0,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_1 = {
+ .ev = llc_conn_ev_local_busy_detected,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_actions_2[] = {
+ [0] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_stop_p_timer,
+ [4] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [5] = llc_conn_ac_start_rej_timer,
+ [6] = llc_conn_ac_clear_remote_busy,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_2 = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_actions_3a[] = {
+ [0] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_start_rej_timer,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_3a = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_3a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_actions_3b[] = {
+ [0] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_start_rej_timer,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_3b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_3b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_actions_4[] = {
+ [0] = llc_conn_ac_send_rej_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_start_rej_timer,
+ [4] = llc_conn_ac_start_p_timer,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_4 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_5[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr,
+ [6] = llc_conn_ac_clear_remote_busy,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_5 = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_6a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_6a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_6a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_6b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_6b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_6b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_7[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_7 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_8a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_8a = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_8a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_8b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_8b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_8b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_9a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_9a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_9a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_9b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_9b = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_9b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_9c[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_9c = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_9c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_9d[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_9d = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_9d,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_10a[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_10a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_10a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_10b[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_10b = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_10b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_11[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_set_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_11 = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_11,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_12a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_12a = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_12a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_actions_12b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_12b = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_12b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_actions_13[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_set_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_13 = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_actions_13,
+};
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_await_ev_qfyrs_14[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_await_actions_14[] = {
+ [0] = llc_conn_ac_send_rr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_state_trans_14 = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = llc_await_ev_qfyrs_14,
+ .ev_actions = llc_await_actions_14,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_await_state_transitions[] = {
+ [0] = &llc_common_state_trans_1, /* Request */
+ [1] = &llc_common_state_trans_2,
+ [2] = &llc_await_state_trans_1_0,
+ [3] = &llc_common_state_trans_n,
+ [4] = &llc_await_state_trans_1, /* Local busy */
+ [5] = &llc_common_state_trans_n,
+ [6] = &llc_common_state_trans_n, /* Initiate PF Cycle */
+ [7] = &llc_common_state_trans_11a, /* Timer */
+ [8] = &llc_common_state_trans_11b,
+ [9] = &llc_common_state_trans_11c,
+ [10] = &llc_common_state_trans_11d,
+ [11] = &llc_await_state_trans_14,
+ [12] = &llc_common_state_trans_n,
+ [13] = &llc_common_state_trans_3, /* Receive frame */
+ [14] = &llc_common_state_trans_4,
+ [15] = &llc_common_state_trans_5,
+ [16] = &llc_common_state_trans_6,
+ [17] = &llc_common_state_trans_7a,
+ [18] = &llc_common_state_trans_7b,
+ [19] = &llc_common_state_trans_8a,
+ [20] = &llc_common_state_trans_8b,
+ [21] = &llc_common_state_trans_8c,
+ [22] = &llc_common_state_trans_9,
+ /* [23] = &llc_common_state_trans_10, */
+ [23] = &llc_await_state_trans_2,
+ [24] = &llc_await_state_trans_3a,
+ [25] = &llc_await_state_trans_3b,
+ [26] = &llc_await_state_trans_4,
+ [27] = &llc_await_state_trans_5,
+ [28] = &llc_await_state_trans_6a,
+ [29] = &llc_await_state_trans_6b,
+ [30] = &llc_await_state_trans_7,
+ [31] = &llc_await_state_trans_8a,
+ [32] = &llc_await_state_trans_8b,
+ [33] = &llc_await_state_trans_9a,
+ [34] = &llc_await_state_trans_9b,
+ [35] = &llc_await_state_trans_9c,
+ [36] = &llc_await_state_trans_9d,
+ [37] = &llc_await_state_trans_10a,
+ [38] = &llc_await_state_trans_10b,
+ [39] = &llc_await_state_trans_11,
+ [40] = &llc_await_state_trans_12a,
+ [41] = &llc_await_state_trans_12b,
+ [42] = &llc_await_state_trans_13,
+ [43] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_AWAIT_BUSY transitions */
+/* State transitions for LLC_CONN_EV_DATA_CONN_REQ event */
+static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_1_0[] = {
+ [0] = llc_conn_ev_qlfy_set_status_refuse,
+ [1] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_await_busy_actions_1_0[1];
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_1_0 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = llc_await_busy_ev_qfyrs_1_0,
+ .ev_actions = llc_await_busy_actions_1_0,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_1[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_1,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_await_busy_actions_1[] = {
+ [0] = llc_conn_ac_send_rej_xxx_x_set_0,
+ [1] = llc_conn_ac_start_rej_timer,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_1 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_await_busy_ev_qfyrs_1,
+ .ev_actions = llc_await_busy_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_0,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_await_busy_actions_2[] = {
+ [0] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_2 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = llc_await_busy_ev_qfyrs_2,
+ .ev_actions = llc_await_busy_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_CLEARED event */
+static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_3[] = {
+ [0] = llc_conn_ev_qlfy_data_flag_eq_2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_await_busy_actions_3[] = {
+ [0] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_3 = {
+ .ev = llc_conn_ev_local_busy_cleared,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_await_busy_ev_qfyrs_3,
+ .ev_actions = llc_await_busy_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_busy_actions_4[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_stop_p_timer,
+ [4] = llc_conn_ac_set_data_flag_1,
+ [5] = llc_conn_ac_clear_remote_busy,
+ [6] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_4 = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_busy_actions_5a[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_set_data_flag_1,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_5a = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_5a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_busy_actions_5b[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_set_data_flag_1,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_5b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_5b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_busy_actions_6[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_set_data_flag_1,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_6 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_7[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_inc_vr_by_1,
+ [2] = llc_conn_ac_data_ind,
+ [3] = llc_conn_ac_stop_p_timer,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_upd_vs,
+ [6] = llc_conn_ac_set_data_flag_0,
+ [7] = llc_conn_ac_clear_remote_busy,
+ [8] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [9] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_7 = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_8a[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_inc_vr_by_1,
+ [2] = llc_conn_ac_data_ind,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = llc_conn_ac_set_data_flag_0,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_8a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_8a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_8b[] = {
+ [0] = llc_conn_ac_opt_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_inc_vr_by_1,
+ [2] = llc_conn_ac_data_ind,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = llc_conn_ac_set_data_flag_0,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_8b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_8b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_9[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_inc_vr_by_1,
+ [2] = llc_conn_ac_data_ind,
+ [3] = llc_conn_ac_upd_nr_received,
+ [4] = llc_conn_ac_upd_vs,
+ [5] = llc_conn_ac_set_data_flag_0,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_9 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_9,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_10a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_10a = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_10a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_10b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_10b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_10b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_11a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_11a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_11a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_11b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_11b = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_11b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_11c[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_11c = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_11c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_11d[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_11d = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_11d,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_12a[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_12a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_12a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_12b[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_12b = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_12b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_13[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_set_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_13 = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_13,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_14a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_14a = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_14a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_busy_actions_14b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_14b = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_14b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_busy_actions_15[] = {
+ [0] = llc_conn_ac_send_rnr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_set_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_15 = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_busy_actions_15,
+};
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_await_busy_ev_qfyrs_16[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_await_busy_actions_16[] = {
+ [0] = llc_conn_ac_send_rnr_cmd_p_set_1,
+ [1] = llc_conn_ac_start_p_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_busy_state_trans_16 = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = llc_await_busy_ev_qfyrs_16,
+ .ev_actions = llc_await_busy_actions_16,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_await_busy_state_transitions[] = {
+ [0] = &llc_common_state_trans_1, /* Request */
+ [1] = &llc_common_state_trans_2,
+ [2] = &llc_await_busy_state_trans_1_0,
+ [3] = &llc_common_state_trans_n,
+ [4] = &llc_await_busy_state_trans_1, /* Local busy */
+ [5] = &llc_await_busy_state_trans_2,
+ [6] = &llc_await_busy_state_trans_3,
+ [7] = &llc_common_state_trans_n,
+ [8] = &llc_common_state_trans_n, /* Initiate PF cycle */
+ [9] = &llc_common_state_trans_11a, /* Timer */
+ [10] = &llc_common_state_trans_11b,
+ [11] = &llc_common_state_trans_11c,
+ [12] = &llc_common_state_trans_11d,
+ [13] = &llc_await_busy_state_trans_16,
+ [14] = &llc_common_state_trans_n,
+ [15] = &llc_await_busy_state_trans_4, /* Receive frame */
+ [16] = &llc_await_busy_state_trans_5a,
+ [17] = &llc_await_busy_state_trans_5b,
+ [18] = &llc_await_busy_state_trans_6,
+ [19] = &llc_await_busy_state_trans_7,
+ [20] = &llc_await_busy_state_trans_8a,
+ [21] = &llc_await_busy_state_trans_8b,
+ [22] = &llc_await_busy_state_trans_9,
+ [23] = &llc_await_busy_state_trans_10a,
+ [24] = &llc_await_busy_state_trans_10b,
+ [25] = &llc_await_busy_state_trans_11a,
+ [26] = &llc_await_busy_state_trans_11b,
+ [27] = &llc_await_busy_state_trans_11c,
+ [28] = &llc_await_busy_state_trans_11d,
+ [29] = &llc_await_busy_state_trans_12a,
+ [30] = &llc_await_busy_state_trans_12b,
+ [31] = &llc_await_busy_state_trans_13,
+ [32] = &llc_await_busy_state_trans_14a,
+ [33] = &llc_await_busy_state_trans_14b,
+ [34] = &llc_await_busy_state_trans_15,
+ [35] = &llc_common_state_trans_3,
+ [36] = &llc_common_state_trans_4,
+ [37] = &llc_common_state_trans_5,
+ [38] = &llc_common_state_trans_6,
+ [39] = &llc_common_state_trans_7a,
+ [40] = &llc_common_state_trans_7b,
+ [41] = &llc_common_state_trans_8a,
+ [42] = &llc_common_state_trans_8b,
+ [43] = &llc_common_state_trans_8c,
+ [44] = &llc_common_state_trans_9,
+ /* [45] = &llc_common_state_trans_10, */
+ [45] = &llc_common_state_trans_n,
+};
+
+/* ----------------- LLC_CONN_STATE_AWAIT_REJ transitions --------------- */
+/* State transitions for LLC_CONN_EV_DATA_CONN_REQ event */
+static llc_conn_ev_qfyr_t llc_await_reject_ev_qfyrs_1_0[] = {
+ [0] = llc_conn_ev_qlfy_set_status_refuse,
+ [1] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_await_reject_actions_1_0[1];
+
+static struct llc_conn_state_trans llc_await_reject_state_trans_1_0 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_await_reject_ev_qfyrs_1_0,
+ .ev_actions = llc_await_reject_actions_1_0,
+};
+
+/* State transitions for LLC_CONN_EV_LOCAL_BUSY_DETECTED event */
+static llc_conn_action_t llc_await_rejct_actions_1[] = {
+ [0] = llc_conn_ac_send_rnr_xxx_x_set_0,
+ [1] = llc_conn_ac_set_data_flag_2,
+ [2] = NULL
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_1 = {
+ .ev = llc_conn_ev_local_busy_detected,
+ .next_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_rejct_actions_2a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = NULL
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_2a = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_2a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_rejct_actions_2b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = NULL
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_2b = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_2b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_rejct_actions_3[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = NULL
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_3 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_4[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_stop_rej_timer,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_upd_vs,
+ [6] = llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr,
+ [7] = llc_conn_ac_clear_remote_busy,
+ [8] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_4 = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_5a[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [3] = llc_conn_ac_stop_rej_timer,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_upd_vs,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_5a = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_5a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_5b[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rr_xxx_x_set_0,
+ [3] = llc_conn_ac_stop_rej_timer,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_upd_vs,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_5b = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_5b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_6[] = {
+ [0] = llc_conn_ac_inc_vr_by_1,
+ [1] = llc_conn_ac_data_ind,
+ [2] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [3] = llc_conn_ac_stop_rej_timer,
+ [4] = llc_conn_ac_upd_nr_received,
+ [5] = llc_conn_ac_upd_vs,
+ [6] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_6 = {
+ .ev = llc_conn_ev_rx_i_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_7a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_7a = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_7a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_7b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_7b = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_7b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_I_RSP_Fbit_SET_1_UNEXPD_Ns event */
+static llc_conn_action_t llc_await_rejct_actions_7c[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_resend_i_xxx_x_set_0,
+ [4] = llc_conn_ac_clear_remote_busy,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_7c = {
+ .ev = llc_conn_ev_rx_i_rsp_fbit_set_1_unexpd_ns,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_7c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_8a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_8a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_8a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_8b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_8b = {
+ .ev = llc_conn_ev_rx_rr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_8b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_8c[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_8c = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_8c,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_8d[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_clear_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_8d = {
+ .ev = llc_conn_ev_rx_rej_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_8d,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_9a[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_9a = {
+ .ev = llc_conn_ev_rx_rr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_9a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_REJ_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_9b[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_clear_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_9b = {
+ .ev = llc_conn_ev_rx_rej_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_9b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_10[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_stop_p_timer,
+ [3] = llc_conn_ac_set_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_10 = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_1,
+ .next_state = LLC_CONN_STATE_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_10,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_11a[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_11a = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_11a,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_RSP_Fbit_SET_0 event */
+static llc_conn_action_t llc_await_rejct_actions_11b[] = {
+ [0] = llc_conn_ac_upd_nr_received,
+ [1] = llc_conn_ac_upd_vs,
+ [2] = llc_conn_ac_set_remote_busy,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_11b = {
+ .ev = llc_conn_ev_rx_rnr_rsp_fbit_set_0,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_11b,
+};
+
+/* State transitions for LLC_CONN_EV_RX_RNR_CMD_Pbit_SET_1 event */
+static llc_conn_action_t llc_await_rejct_actions_12[] = {
+ [0] = llc_conn_ac_send_rr_rsp_f_set_1,
+ [1] = llc_conn_ac_upd_nr_received,
+ [2] = llc_conn_ac_upd_vs,
+ [3] = llc_conn_ac_set_remote_busy,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_12 = {
+ .ev = llc_conn_ev_rx_rnr_cmd_pbit_set_1,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_await_rejct_actions_12,
+};
+
+/* State transitions for LLC_CONN_EV_P_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_await_rejct_ev_qfyrs_13[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_await_rejct_actions_13[] = {
+ [0] = llc_conn_ac_send_rej_cmd_p_set_1,
+ [1] = llc_conn_ac_stop_p_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_await_rejct_state_trans_13 = {
+ .ev = llc_conn_ev_p_tmr_exp,
+ .next_state = LLC_CONN_STATE_AWAIT_REJ,
+ .ev_qualifiers = llc_await_rejct_ev_qfyrs_13,
+ .ev_actions = llc_await_rejct_actions_13,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_await_rejct_state_transitions[] = {
+ [0] = &llc_await_reject_state_trans_1_0,
+ [1] = &llc_common_state_trans_1, /* requests */
+ [2] = &llc_common_state_trans_2,
+ [3] = &llc_common_state_trans_n,
+ [4] = &llc_await_rejct_state_trans_1, /* local busy */
+ [5] = &llc_common_state_trans_n,
+ [6] = &llc_common_state_trans_n, /* Initiate PF cycle */
+ [7] = &llc_await_rejct_state_trans_13, /* timers */
+ [8] = &llc_common_state_trans_11a,
+ [9] = &llc_common_state_trans_11b,
+ [10] = &llc_common_state_trans_11c,
+ [11] = &llc_common_state_trans_11d,
+ [12] = &llc_common_state_trans_n,
+ [13] = &llc_await_rejct_state_trans_2a, /* receive frames */
+ [14] = &llc_await_rejct_state_trans_2b,
+ [15] = &llc_await_rejct_state_trans_3,
+ [16] = &llc_await_rejct_state_trans_4,
+ [17] = &llc_await_rejct_state_trans_5a,
+ [18] = &llc_await_rejct_state_trans_5b,
+ [19] = &llc_await_rejct_state_trans_6,
+ [20] = &llc_await_rejct_state_trans_7a,
+ [21] = &llc_await_rejct_state_trans_7b,
+ [22] = &llc_await_rejct_state_trans_7c,
+ [23] = &llc_await_rejct_state_trans_8a,
+ [24] = &llc_await_rejct_state_trans_8b,
+ [25] = &llc_await_rejct_state_trans_8c,
+ [26] = &llc_await_rejct_state_trans_8d,
+ [27] = &llc_await_rejct_state_trans_9a,
+ [28] = &llc_await_rejct_state_trans_9b,
+ [29] = &llc_await_rejct_state_trans_10,
+ [30] = &llc_await_rejct_state_trans_11a,
+ [31] = &llc_await_rejct_state_trans_11b,
+ [32] = &llc_await_rejct_state_trans_12,
+ [33] = &llc_common_state_trans_3,
+ [34] = &llc_common_state_trans_4,
+ [35] = &llc_common_state_trans_5,
+ [36] = &llc_common_state_trans_6,
+ [37] = &llc_common_state_trans_7a,
+ [38] = &llc_common_state_trans_7b,
+ [39] = &llc_common_state_trans_8a,
+ [40] = &llc_common_state_trans_8b,
+ [41] = &llc_common_state_trans_8c,
+ [42] = &llc_common_state_trans_9,
+ /* [43] = &llc_common_state_trans_10, */
+ [43] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_D_CONN transitions */
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event,
+ * cause_flag = 1 */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_1[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_conflict,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_1[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_p,
+ [1] = llc_conn_ac_stop_ack_timer,
+ [2] = llc_conn_ac_disc_confirm,
+ [3] = llc_conn_disc,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_1 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_1,
+ .ev_actions = llc_d_conn_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event,
+ * cause_flag = 0
+ */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_1_1[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_set_status_conflict,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_1_1[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_p,
+ [1] = llc_conn_ac_stop_ack_timer,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_1_1 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_1_1,
+ .ev_actions = llc_d_conn_actions_1_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event,
+ * cause_flag = 1
+ */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [2] = llc_conn_ev_qlfy_set_status_disc,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_2[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_ac_disc_confirm,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_2 = {
+ .ev = llc_conn_ev_rx_ua_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_2,
+ .ev_actions = llc_d_conn_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event,
+ * cause_flag = 0
+ */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_2_1[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_set_status_disc,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_2_1[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_2_1 = {
+ .ev = llc_conn_ev_rx_ua_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_2_1,
+ .ev_actions = llc_d_conn_actions_2_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_d_conn_actions_3[] = {
+ [0] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_3 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_D_CONN,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_d_conn_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event,
+ * cause_flag = 1
+ */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_4[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_disc,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_4[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_ac_disc_confirm,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_4 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_4,
+ .ev_actions = llc_d_conn_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event,
+ * cause_flag = 0
+ */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_4_1[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_set_status_disc,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_4_1[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_4_1 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_4_1,
+ .ev_actions = llc_d_conn_actions_4_1,
+};
+
+/*
+ * State transition for
+ * LLC_CONN_EV_DATA_CONN_REQ event
+ */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_5[] = {
+ [0] = llc_conn_ev_qlfy_set_status_refuse,
+ [1] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_d_conn_actions_5[1];
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_5 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_D_CONN,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_5,
+ .ev_actions = llc_d_conn_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_6[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_6[] = {
+ [0] = llc_conn_ac_send_disc_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_6 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_D_CONN,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_6,
+ .ev_actions = llc_d_conn_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event, cause_flag = 1 */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_7[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [2] = llc_conn_ev_qlfy_set_status_failed,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_7[] = {
+ [0] = llc_conn_ac_disc_confirm,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_7 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_7,
+ .ev_actions = llc_d_conn_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event, cause_flag = 0 */
+static llc_conn_ev_qfyr_t llc_d_conn_ev_qfyrs_8[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_set_status_failed,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_d_conn_actions_8[] = {
+ [0] = llc_conn_disc,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_d_conn_state_trans_8 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_d_conn_ev_qfyrs_8,
+ .ev_actions = llc_d_conn_actions_8,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_d_conn_state_transitions[] = {
+ [0] = &llc_d_conn_state_trans_5, /* Request */
+ [1] = &llc_common_state_trans_n,
+ [2] = &llc_common_state_trans_n, /* Local busy */
+ [3] = &llc_common_state_trans_n, /* Initiate PF cycle */
+ [4] = &llc_d_conn_state_trans_6, /* Timer */
+ [5] = &llc_d_conn_state_trans_7,
+ [6] = &llc_d_conn_state_trans_8,
+ [7] = &llc_common_state_trans_n,
+ [8] = &llc_d_conn_state_trans_1, /* Receive frame */
+ [9] = &llc_d_conn_state_trans_1_1,
+ [10] = &llc_d_conn_state_trans_2,
+ [11] = &llc_d_conn_state_trans_2_1,
+ [12] = &llc_d_conn_state_trans_3,
+ [13] = &llc_d_conn_state_trans_4,
+ [14] = &llc_d_conn_state_trans_4_1,
+ [15] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_RESET transitions */
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_rst_actions_1[] = {
+ [0] = llc_conn_ac_set_vs_0,
+ [1] = llc_conn_ac_set_vr_0,
+ [2] = llc_conn_ac_set_s_flag_1,
+ [3] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_1 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_rst_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event,
+ * cause_flag = 1
+ */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_2[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [2] = llc_conn_ev_qlfy_set_status_conn,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_2[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_ac_set_vs_0,
+ [2] = llc_conn_ac_set_vr_0,
+ [3] = llc_conn_ac_upd_p_flag,
+ [4] = llc_conn_ac_rst_confirm,
+ [5] = llc_conn_ac_set_remote_busy_0,
+ [6] = llc_conn_reset,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_2 = {
+ .ev = llc_conn_ev_rx_ua_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_rst_ev_qfyrs_2,
+ .ev_actions = llc_rst_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_RX_UA_RSP_Fbit_SET_X event,
+ * cause_flag = 0
+ */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_2_1[] = {
+ [0] = llc_conn_ev_qlfy_p_flag_eq_f,
+ [1] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_set_status_rst_done,
+ [3] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_2_1[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_ac_set_vs_0,
+ [2] = llc_conn_ac_set_vr_0,
+ [3] = llc_conn_ac_upd_p_flag,
+ [4] = llc_conn_ac_rst_confirm,
+ [5] = llc_conn_ac_set_remote_busy_0,
+ [6] = llc_conn_reset,
+ [7] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_2_1 = {
+ .ev = llc_conn_ev_rx_ua_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_rst_ev_qfyrs_2_1,
+ .ev_actions = llc_rst_actions_2_1,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_3[] = {
+ [0] = llc_conn_ev_qlfy_s_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_rst_done,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_3[] = {
+ [0] = llc_conn_ac_set_p_flag_0,
+ [1] = llc_conn_ac_set_remote_busy_0,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_3 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = llc_rst_ev_qfyrs_3,
+ .ev_actions = llc_rst_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event,
+ * cause_flag = 1
+ */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_4[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_disc,
+ [2] = NULL,
+};
+static llc_conn_action_t llc_rst_actions_4[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_p,
+ [1] = llc_conn_ac_disc_ind,
+ [2] = llc_conn_ac_stop_ack_timer,
+ [3] = llc_conn_disc,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_4 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_rst_ev_qfyrs_4,
+ .ev_actions = llc_rst_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event,
+ * cause_flag = 0
+ */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_4_1[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_set_status_refuse,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_4_1[] = {
+ [0] = llc_conn_ac_send_dm_rsp_f_set_p,
+ [1] = llc_conn_ac_stop_ack_timer,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_4_1 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_rst_ev_qfyrs_4_1,
+ .ev_actions = llc_rst_actions_4_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event,
+ * cause_flag = 1
+ */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_5[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [1] = llc_conn_ev_qlfy_set_status_disc,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_5[] = {
+ [0] = llc_conn_ac_disc_ind,
+ [1] = llc_conn_ac_stop_ack_timer,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_5 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_rst_ev_qfyrs_5,
+ .ev_actions = llc_rst_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event,
+ * cause_flag = 0
+ */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_5_1[] = {
+ [0] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [1] = llc_conn_ev_qlfy_set_status_refuse,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_5_1[] = {
+ [0] = llc_conn_ac_stop_ack_timer,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_5_1 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_rst_ev_qfyrs_5_1,
+ .ev_actions = llc_rst_actions_5_1,
+};
+
+/* State transitions for DATA_CONN_REQ event */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_6[] = {
+ [0] = llc_conn_ev_qlfy_set_status_refuse,
+ [1] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_rst_actions_6[1];
+
+static struct llc_conn_state_trans llc_rst_state_trans_6 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_rst_ev_qfyrs_6,
+ .ev_actions = llc_rst_actions_6,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_7[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = llc_conn_ev_qlfy_s_flag_eq_0,
+ [2] = NULL,
+};
+
+static llc_conn_action_t llc_rst_actions_7[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_7 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_rst_ev_qfyrs_7,
+ .ev_actions = llc_rst_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_8[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = llc_conn_ev_qlfy_s_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_cause_flag_eq_1,
+ [3] = llc_conn_ev_qlfy_set_status_failed,
+ [4] = NULL,
+};
+static llc_conn_action_t llc_rst_actions_8[] = {
+ [0] = llc_conn_ac_disc_ind,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_8 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_rst_ev_qfyrs_8,
+ .ev_actions = llc_rst_actions_8,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_rst_ev_qfyrs_8_1[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = llc_conn_ev_qlfy_s_flag_eq_0,
+ [2] = llc_conn_ev_qlfy_cause_flag_eq_0,
+ [3] = llc_conn_ev_qlfy_set_status_failed,
+ [4] = NULL,
+};
+static llc_conn_action_t llc_rst_actions_8_1[] = {
+ [0] = llc_conn_ac_disc_ind,
+ [1] = llc_conn_disc,
+ [2] = NULL,
+};
+
+static struct llc_conn_state_trans llc_rst_state_trans_8_1 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = llc_rst_ev_qfyrs_8_1,
+ .ev_actions = llc_rst_actions_8_1,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_rst_state_transitions[] = {
+ [0] = &llc_rst_state_trans_6, /* Request */
+ [1] = &llc_common_state_trans_n,
+ [2] = &llc_common_state_trans_n, /* Local busy */
+ [3] = &llc_common_state_trans_n, /* Initiate PF cycle */
+ [4] = &llc_rst_state_trans_3, /* Timer */
+ [5] = &llc_rst_state_trans_7,
+ [6] = &llc_rst_state_trans_8,
+ [7] = &llc_rst_state_trans_8_1,
+ [8] = &llc_common_state_trans_n,
+ [9] = &llc_rst_state_trans_1, /* Receive frame */
+ [10] = &llc_rst_state_trans_2,
+ [11] = &llc_rst_state_trans_2_1,
+ [12] = &llc_rst_state_trans_4,
+ [13] = &llc_rst_state_trans_4_1,
+ [14] = &llc_rst_state_trans_5,
+ [15] = &llc_rst_state_trans_5_1,
+ [16] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_ERROR transitions */
+/* State transitions for LLC_CONN_EV_RX_SABME_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_error_actions_1[] = {
+ [0] = llc_conn_ac_set_vs_0,
+ [1] = llc_conn_ac_set_vr_0,
+ [2] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [3] = llc_conn_ac_rst_ind,
+ [4] = llc_conn_ac_set_p_flag_0,
+ [5] = llc_conn_ac_set_remote_busy_0,
+ [6] = llc_conn_ac_stop_ack_timer,
+ [7] = llc_conn_reset,
+ [8] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_1 = {
+ .ev = llc_conn_ev_rx_sabme_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_NORMAL,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_error_actions_1,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DISC_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_error_actions_2[] = {
+ [0] = llc_conn_ac_send_ua_rsp_f_set_p,
+ [1] = llc_conn_ac_disc_ind,
+ [2] = llc_conn_ac_stop_ack_timer,
+ [3] = llc_conn_disc,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_2 = {
+ .ev = llc_conn_ev_rx_disc_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_error_actions_2,
+};
+
+/* State transitions for LLC_CONN_EV_RX_DM_RSP_Fbit_SET_X event */
+static llc_conn_action_t llc_error_actions_3[] = {
+ [0] = llc_conn_ac_disc_ind,
+ [1] = llc_conn_ac_stop_ack_timer,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_3 = {
+ .ev = llc_conn_ev_rx_dm_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_error_actions_3,
+};
+
+/* State transitions for LLC_CONN_EV_RX_FRMR_RSP_Fbit_SET_X event */
+static llc_conn_action_t llc_error_actions_4[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_set_retry_cnt_0,
+ [3] = llc_conn_ac_set_cause_flag_0,
+ [4] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_4 = {
+ .ev = llc_conn_ev_rx_frmr_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_error_actions_4,
+};
+
+/* State transitions for LLC_CONN_EV_RX_XXX_CMD_Pbit_SET_X event */
+static llc_conn_action_t llc_error_actions_5[] = {
+ [0] = llc_conn_ac_resend_frmr_rsp_f_set_p,
+ [1] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_5 = {
+ .ev = llc_conn_ev_rx_xxx_cmd_pbit_set_x,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_error_actions_5,
+};
+
+/* State transitions for LLC_CONN_EV_RX_XXX_RSP_Fbit_SET_X event */
+static struct llc_conn_state_trans llc_error_state_trans_6 = {
+ .ev = llc_conn_ev_rx_xxx_rsp_fbit_set_x,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = NONE,
+ .ev_actions = NONE,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_error_ev_qfyrs_7[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_lt_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_error_actions_7[] = {
+ [0] = llc_conn_ac_resend_frmr_rsp_f_set_0,
+ [1] = llc_conn_ac_start_ack_timer,
+ [2] = llc_conn_ac_inc_retry_cnt_by_1,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_7 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = llc_error_ev_qfyrs_7,
+ .ev_actions = llc_error_actions_7,
+};
+
+/* State transitions for LLC_CONN_EV_ACK_TMR_EXP event */
+static llc_conn_ev_qfyr_t llc_error_ev_qfyrs_8[] = {
+ [0] = llc_conn_ev_qlfy_retry_cnt_gte_n2,
+ [1] = NULL,
+};
+
+static llc_conn_action_t llc_error_actions_8[] = {
+ [0] = llc_conn_ac_send_sabme_cmd_p_set_x,
+ [1] = llc_conn_ac_set_s_flag_0,
+ [2] = llc_conn_ac_start_ack_timer,
+ [3] = llc_conn_ac_set_retry_cnt_0,
+ [4] = llc_conn_ac_set_cause_flag_0,
+ [5] = NULL,
+};
+
+static struct llc_conn_state_trans llc_error_state_trans_8 = {
+ .ev = llc_conn_ev_ack_tmr_exp,
+ .next_state = LLC_CONN_STATE_RESET,
+ .ev_qualifiers = llc_error_ev_qfyrs_8,
+ .ev_actions = llc_error_actions_8,
+};
+
+/* State transitions for LLC_CONN_EV_DATA_CONN_REQ event */
+static llc_conn_ev_qfyr_t llc_error_ev_qfyrs_9[] = {
+ [0] = llc_conn_ev_qlfy_set_status_refuse,
+ [1] = NULL,
+};
+
+/* just one member, NULL, .bss zeroes it */
+static llc_conn_action_t llc_error_actions_9[1];
+
+static struct llc_conn_state_trans llc_error_state_trans_9 = {
+ .ev = llc_conn_ev_data_req,
+ .next_state = LLC_CONN_STATE_ERROR,
+ .ev_qualifiers = llc_error_ev_qfyrs_9,
+ .ev_actions = llc_error_actions_9,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_error_state_transitions[] = {
+ [0] = &llc_error_state_trans_9, /* Request */
+ [1] = &llc_common_state_trans_n,
+ [2] = &llc_common_state_trans_n, /* Local busy */
+ [3] = &llc_common_state_trans_n, /* Initiate PF cycle */
+ [4] = &llc_error_state_trans_7, /* Timer */
+ [5] = &llc_error_state_trans_8,
+ [6] = &llc_common_state_trans_n,
+ [7] = &llc_error_state_trans_1, /* Receive frame */
+ [8] = &llc_error_state_trans_2,
+ [9] = &llc_error_state_trans_3,
+ [10] = &llc_error_state_trans_4,
+ [11] = &llc_error_state_trans_5,
+ [12] = &llc_error_state_trans_6,
+ [13] = &llc_common_state_trans_n,
+};
+
+/* LLC_CONN_STATE_TEMP transitions */
+/* State transitions for LLC_CONN_EV_DISC_REQ event */
+static llc_conn_action_t llc_temp_actions_1[] = {
+ [0] = llc_conn_ac_stop_all_timers,
+ [1] = llc_conn_ac_send_disc_cmd_p_set_x,
+ [2] = llc_conn_disc,
+ [3] = NULL,
+};
+
+static struct llc_conn_state_trans llc_temp_state_trans_1 = {
+ .ev = llc_conn_ev_disc_req,
+ .next_state = LLC_CONN_STATE_ADM,
+ .ev_qualifiers = NONE,
+ .ev_actions = llc_temp_actions_1,
+};
+
+/*
+ * Array of pointers;
+ * one to each transition
+ */
+static struct llc_conn_state_trans *llc_temp_state_transitions[] = {
+ [0] = &llc_temp_state_trans_1, /* requests */
+ [1] = &llc_common_state_trans_n,
+ [2] = &llc_common_state_trans_n, /* local busy */
+ [3] = &llc_common_state_trans_n, /* init_pf_cycle */
+ [4] = &llc_common_state_trans_n, /* timer */
+ [5] = &llc_common_state_trans_n, /* receive */
+};
+
+/* Connection State Transition Table */
+struct llc_conn_state llc_conn_state_table[] = {
+ {
+ current_state: LLC_CONN_STATE_ADM,
+ transitions: llc_adm_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_SETUP,
+ transitions: llc_setup_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_NORMAL,
+ transitions: llc_normal_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_BUSY,
+ transitions: llc_busy_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_REJ,
+ transitions: llc_reject_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_AWAIT,
+ transitions: llc_await_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_AWAIT_BUSY,
+ transitions: llc_await_busy_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_AWAIT_REJ,
+ transitions: llc_await_rejct_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_D_CONN,
+ transitions: llc_d_conn_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_RESET,
+ transitions: llc_rst_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_ERROR,
+ transitions: llc_error_state_transitions,
+ },
+ {
+ current_state: LLC_CONN_STATE_TEMP,
+ transitions: llc_temp_state_transitions,
+ },
+};
diff --git a/net/llc/llc_conn.c b/net/llc/llc_conn.c
new file mode 100644
index 000000000000..2d96a6a3cbd5
--- /dev/null
+++ b/net/llc/llc_conn.c
@@ -0,0 +1,531 @@
+/*
+ * llc_conn.c - Driver routines for connection component.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_conn.h>
+#include <net/sock.h>
+#include <net/llc_main.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_c_st.h>
+#include <net/llc_mac.h>
+#include <net/llc_pdu.h>
+#include <net/llc_s_ev.h>
+
+static int llc_find_offset(int state, int ev_type);
+static void llc_conn_send_pdus(struct sock *sk);
+static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev);
+static int llc_exec_conn_trans_actions(struct sock *sk,
+ struct llc_conn_state_trans *trans,
+ struct llc_conn_state_ev *ev);
+static struct llc_conn_state_trans *
+ llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev);
+
+/* Offset table on connection states transition diagram */
+static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
+
+/**
+ * llc_conn_alloc_event: allocates an event
+ * @sk: socket that event is associated
+ *
+ * Returns pointer to allocated connection on success, %NULL on failure.
+ */
+struct llc_conn_state_ev *llc_conn_alloc_ev(struct sock *sk)
+{
+ struct llc_conn_state_ev *ev = NULL;
+
+ /* verify connection is valid, active and open */
+ if (llc_sk(sk)->state != LLC_CONN_OUT_OF_SVC) {
+ /* get event structure to build a station event */
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (ev)
+ memset(ev, 0, sizeof(*ev));
+ }
+ return ev;
+}
+
+/**
+ * llc_conn_send_event - sends event to connection state machine
+ * @sk: connection
+ * @ev: occurred event
+ *
+ * Sends an event to connection state machine. after processing event
+ * (executing it's actions and changing state), upper layer will be
+ * indicated or confirmed, if needed. Returns 0 for success, 1 for
+ * failure. The socket lock has to be held before calling this function.
+ */
+int llc_conn_send_ev(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ /* sending event to state machine */
+ int rc = llc_conn_service(sk, ev);
+ struct llc_opt *llc = llc_sk(sk);
+ u8 flag = ev->flag;
+ struct llc_prim_if_block *ind_prim = ev->ind_prim;
+ struct llc_prim_if_block *cfm_prim = ev->cfm_prim;
+
+ llc_conn_free_ev(ev);
+#ifdef THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY
+ /* check if the connection was freed by the state machine by
+ * means of llc_conn_disc */
+ if (rc == 2) {
+ printk(KERN_INFO __FUNCTION__ ": rc == 2\n");
+ rc = -ECONNABORTED;
+ goto out;
+ }
+#endif /* THIS_BREAKS_DISCONNECT_NOTIFICATION_BADLY */
+ if (!flag) /* indicate or confirm not required */
+ goto out;
+ rc = 0;
+ if (ind_prim) /* indication required */
+ llc->sap->ind(ind_prim);
+ if (!cfm_prim) /* confirmation not required */
+ goto out;
+ /* data confirm has preconditions */
+ if (cfm_prim->prim != LLC_DATA_PRIM) {
+ llc->sap->conf(cfm_prim);
+ goto out;
+ }
+ if (!llc_data_accept_state(llc->state)) {
+ /* In this state, we can send I pdu */
+ /* 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:
+ return rc;
+}
+
+void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sock_assert(sk);
+ /* queue PDU to send to MAC layer */
+ skb_queue_tail(&sk->write_queue, skb);
+ llc_conn_send_pdus(sk);
+}
+
+/**
+ * llc_conn_rtn_pdu - sends received data pdu to upper layer
+ * @sk: Active connection
+ * @skb: Received data frame
+ * @ev: Occurred event
+ *
+ * Sends received data pdu to upper layer (by using indicate function).
+ * Prepares service parameters (prim and prim_data). calling indication
+ * function will be done in llc_conn_send_ev.
+ */
+void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb,
+ struct llc_conn_state_ev *ev)
+{
+ struct llc_prim_if_block *prim = &llc_ind_prim;
+ union llc_u_prim_data *prim_data = llc_ind_prim.data;
+
+ prim_data->data.sk = sk;
+ prim_data->data.pri = 0;
+ prim_data->data.skb = skb;
+ prim_data->data.link = llc_sk(sk)->link;
+ prim->data = prim_data;
+ prim->prim = LLC_DATA_PRIM;
+ prim->sap = llc_sk(sk)->sap;
+ ev->flag = 1;
+ /* saving prepd prim in event for future use in llc_conn_send_ev */
+ ev->ind_prim = prim;
+}
+
+/**
+ * llc_conn_resend_i_pdu_as_cmd - resend all all unacknowledged I PDUs
+ * @sk: active connection
+ * @nr: NR
+ * @first_p_bit: p_bit value of first pdu
+ *
+ * Resend all unacknowledged I PDUs, starting with the NR; send first as
+ * command PDU with P bit equal first_p_bit; if more than one send
+ * subsequent as command PDUs with P bit equal zero (0).
+ */
+void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
+{
+ struct sk_buff *skb;
+ llc_pdu_sn_t *pdu;
+ u16 nbr_unack_pdus;
+ u8 howmany_resend = 0;
+
+ llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
+ if (!nbr_unack_pdus)
+ goto out;
+ /* process unack PDUs only if unack queue is not empty; remove
+ * appropriate PDUs, fix them up, and put them on mac_pdu_q.
+ */
+ while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) {
+ pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD);
+ llc_pdu_set_pf_bit(skb, first_p_bit);
+ skb_queue_tail(&sk->write_queue, skb);
+ first_p_bit = 0;
+ llc_sk(sk)->vS = LLC_I_GET_NS(pdu);
+ howmany_resend++;
+ }
+ if (howmany_resend > 0)
+ llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % LLC_2_SEQ_NBR_MODULO;
+ /* any PDUs to re-send are queued up; start sending to MAC */
+ llc_conn_send_pdus(sk);
+out:;
+}
+
+/**
+ * llc_conn_resend_i_pdu_as_rsp - Resend all unacknowledged I PDUs
+ * @sk: active connection.
+ * @nr: NR
+ * @first_f_bit: f_bit value of first pdu.
+ *
+ * Resend all unacknowledged I PDUs, starting with the NR; send first as
+ * response PDU with F bit equal first_f_bit; if more than one send
+ * subsequent as response PDUs with F bit equal zero (0).
+ */
+void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
+{
+ struct sk_buff *skb;
+ llc_pdu_sn_t *pdu;
+ u16 nbr_unack_pdus;
+ u8 howmany_resend = 0;
+
+ llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
+ if (!nbr_unack_pdus)
+ goto out;
+ /* process unack PDUs only if unack queue is not empty; remove
+ * appropriate PDUs, fix them up, and put them on mac_pdu_q
+ */
+ while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) {
+ pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP);
+ llc_pdu_set_pf_bit(skb, first_f_bit);
+ skb_queue_tail(&sk->write_queue, skb);
+ first_f_bit = 0;
+ llc_sk(sk)->vS = LLC_I_GET_NS(pdu);
+ howmany_resend++;
+ }
+ if (howmany_resend > 0)
+ llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % LLC_2_SEQ_NBR_MODULO;
+ /* any PDUs to re-send are queued up; start sending to MAC */
+ llc_conn_send_pdus(sk);
+out:;
+}
+
+/**
+ * llc_conn_remove_acked_pdus - Removes acknowledged pdus from tx queue
+ * @sk: active connection
+ * nr: NR
+ * how_many_unacked: size of pdu_unack_q after removing acked pdus
+ *
+ * Removes acknowledged pdus from transmit queue (pdu_unack_q). Returns
+ * the number of pdus that removed from queue.
+ */
+int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked)
+{
+ int pdu_pos, i;
+ struct sk_buff *skb;
+ llc_pdu_sn_t *pdu;
+ int nbr_acked = 0;
+ int q_len = skb_queue_len(&llc_sk(sk)->pdu_unack_q);
+
+ if (!q_len)
+ goto out;
+ skb = skb_peek(&llc_sk(sk)->pdu_unack_q);
+ pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ /* finding position of last acked pdu in queue */
+ pdu_pos = ((int)LLC_2_SEQ_NBR_MODULO + (int)nr -
+ (int)LLC_I_GET_NS(pdu)) % LLC_2_SEQ_NBR_MODULO;
+
+ for (i = 0; i < pdu_pos && i < q_len; i++) {
+ skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q);
+ if (skb)
+ kfree_skb(skb);
+ nbr_acked++;
+ }
+out:
+ *how_many_unacked = skb_queue_len(&llc_sk(sk)->pdu_unack_q);
+ return nbr_acked;
+}
+
+/**
+ * llc_conn_send_pdus - Sends queued PDUs
+ * @sk: active connection
+ *
+ * Sends queued pdus to MAC layer for transmition.
+ */
+static void llc_conn_send_pdus(struct sock *sk)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&sk->write_queue)) != NULL) {
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ if (!LLC_PDU_TYPE_IS_I(pdu) &&
+ !(skb->dev->flags & IFF_LOOPBACK))
+ skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb);
+ mac_send_pdu(skb);
+ if (LLC_PDU_TYPE_IS_I(pdu) ||
+ (skb->dev && skb->dev->flags & IFF_LOOPBACK))
+ kfree_skb(skb);
+ }
+}
+
+/**
+ * llc_conn_free_ev - free event
+ * @ev: event to free
+ *
+ * Free allocated event.
+ */
+void llc_conn_free_ev(struct llc_conn_state_ev *ev)
+{
+ if (ev->type == LLC_CONN_EV_TYPE_PDU) {
+ /* free the frame that binded to this event */
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
+
+ if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim)
+ kfree_skb(ev->data.pdu.skb);
+ }
+ /* free event structure to free list of the same */
+ kfree(ev);
+}
+
+/**
+ * llc_conn_service - finds transition and changes state of connection
+ * @sk: connection
+ * @ev: happened event
+ *
+ * This function finds transition that matches with happened event, then
+ * executes related actions and finally changes state of connection.
+ * Returns 0 for success, 1 for failure.
+ */
+static int llc_conn_service(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ int rc = 1;
+ struct llc_conn_state_trans *trans;
+
+ if (llc_sk(sk)->state > NBR_CONN_STATES)
+ goto out;
+ rc = 0;
+ trans = llc_qualify_conn_ev(sk, ev);
+ if (trans) {
+ rc = llc_exec_conn_trans_actions(sk, trans, ev);
+ if (!rc && trans->next_state != NO_STATE_CHANGE)
+ llc_sk(sk)->state = trans->next_state;
+ }
+out:
+ return rc;
+}
+
+/**
+ * llc_qualify_conn_ev - finds transition for event
+ * @sk: connection
+ * @ev: happened event
+ *
+ * This function finds transition that matches with happened event.
+ * Returns pointer to found transition on success, %NULL otherwise.
+ */
+static struct llc_conn_state_trans *
+ llc_qualify_conn_ev(struct sock *sk, struct llc_conn_state_ev *ev)
+{
+ struct llc_conn_state_trans **next_trans;
+ llc_conn_ev_qfyr_t *next_qualifier;
+ struct llc_conn_state *curr_state =
+ &llc_conn_state_table[llc_sk(sk)->state - 1];
+
+ /* search thru events for this state until
+ * list exhausted or until no more
+ */
+ for (next_trans = curr_state->transitions +
+ llc_find_offset(llc_sk(sk)->state - 1, ev->type);
+ (*next_trans)->ev; next_trans++) {
+ if (!((*next_trans)->ev)(sk, ev)) {
+ /* got POSSIBLE event match; the event may require
+ * qualification based on the values of a number of
+ * state flags; if all qualifications are met (i.e.,
+ * if all qualifying functions return success, or 0,
+ * then this is THE event we're looking for
+ */
+ for (next_qualifier = (*next_trans)->ev_qualifiers;
+ next_qualifier && *next_qualifier &&
+ !(*next_qualifier)(sk, ev); next_qualifier++)
+ /* nothing */;
+ if (!next_qualifier || !*next_qualifier)
+ /* all qualifiers executed successfully; this is
+ * our transition; return it so we can perform
+ * the associated actions & change the state
+ */
+ return *next_trans;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * llc_exec_conn_trans_actions - executes related actions
+ * @sk: connection
+ * @trans: transition that it's actions must be performed
+ * @ev: happened event
+ *
+ * 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
+ * connection was freed (llc_conn_disc was called)
+ */
+static int llc_exec_conn_trans_actions(struct sock *sk,
+ struct llc_conn_state_trans *trans,
+ struct llc_conn_state_ev *ev)
+{
+ int rc = 0;
+ llc_conn_action_t *next_action;
+
+ for (next_action = trans->ev_actions;
+ next_action && *next_action; next_action++) {
+ int rc2 = (*next_action)(sk, ev);
+
+ if (rc2 == 2) {
+ rc = rc2;
+ break;
+ } else if (rc2)
+ rc = 1;
+ }
+ return rc;
+}
+
+/**
+ * llc_find_sock - Finds connection in sap for the remote/local sap/mac
+ * @sap: SAP
+ * @daddr: address of remote LLC (MAC + SAP)
+ * @laddr: address of local LLC (MAC + SAP)
+ *
+ * Search connection list of the SAP and finds connection using the remote
+ * mac, remote sap, local mac, and local sap. Returns pointer for
+ * connection found, %NULL otherwise.
+ */
+struct sock *llc_find_sock(struct llc_sap *sap, struct llc_addr *daddr,
+ 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->laddr.lsap == laddr->lsap &&
+ llc->daddr.lsap == daddr->lsap &&
+ !memcmp(llc->laddr.mac, laddr->mac, ETH_ALEN) &&
+ !memcmp(llc->daddr.mac, daddr->mac, ETH_ALEN)) {
+ rc = llc->sk;
+ break;
+ }
+ }
+ 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.
+ * @state: state of connection.
+ *
+ * Returns 0 if data can be sent, 1 otherwise.
+ */
+u8 llc_data_accept_state(u8 state)
+{
+ if (state != LLC_CONN_STATE_NORMAL && state != LLC_CONN_STATE_BUSY &&
+ state != LLC_CONN_STATE_REJ)
+ return 1; /* data_conn_refuse */
+ return 0;
+}
+
+/**
+ * find_next_offset - finds offset for next category of transitions
+ * @state: state table.
+ * @offset: start offset.
+ *
+ * Finds offset of next category of transitions in transition table.
+ * Returns the start index of next category.
+ */
+u16 find_next_offset(struct llc_conn_state *state, u16 offset)
+{
+ u16 cnt = 0;
+ struct llc_conn_state_trans **next_trans;
+
+ for (next_trans = state->transitions + offset;
+ (*next_trans)->ev; next_trans++)
+ ++cnt;
+ return cnt;
+}
+
+/**
+ * llc_build_offset_table - builds offset table of connection
+ *
+ * Fills offset table of connection state transition table
+ * (llc_offset_table).
+ */
+void __init llc_build_offset_table(void)
+{
+ struct llc_conn_state *curr_state;
+ int state, ev_type, next_offset;
+
+ memset(llc_offset_table, 0, sizeof(llc_offset_table));
+ for (state = 0; state < NBR_CONN_STATES; state++) {
+ curr_state = &llc_conn_state_table[state];
+ next_offset = 0;
+ for (ev_type = 0; ev_type < NBR_CONN_EV; ev_type++) {
+ llc_offset_table[state][ev_type] = next_offset;
+ next_offset += find_next_offset(curr_state,
+ next_offset) + 1;
+ }
+ }
+}
+
+/**
+ * llc_find_offset - finds start offset of category of transitions
+ * @state: state of connection
+ * @ev_type: type of happened event
+ *
+ * Finds start offset of desired category of transitions. Returns the
+ * desired start offset.
+ */
+static int llc_find_offset(int state, int ev_type)
+{
+ int rc = 0;
+ /* at this stage, llc_offset_table[..][2] is not important. it is for
+ * init_pf_cycle and I don't know what is it.
+ */
+ switch (ev_type) {
+ case LLC_CONN_EV_TYPE_PRIM:
+ rc = llc_offset_table[state][0]; break;
+ case LLC_CONN_EV_TYPE_PDU:
+ rc = llc_offset_table[state][4]; break;
+ case LLC_CONN_EV_TYPE_SIMPLE:
+ rc = llc_offset_table[state][1]; break;
+ case LLC_CONN_EV_TYPE_P_TMR:
+ case LLC_CONN_EV_TYPE_ACK_TMR:
+ case LLC_CONN_EV_TYPE_REJ_TMR:
+ case LLC_CONN_EV_TYPE_BUSY_TMR:
+ rc = llc_offset_table[state][3]; break;
+ }
+ return rc;
+}
diff --git a/net/llc/llc_evnt.c b/net/llc/llc_evnt.c
new file mode 100644
index 000000000000..faabd22c8e0a
--- /dev/null
+++ b/net/llc/llc_evnt.c
@@ -0,0 +1,112 @@
+/*
+ * llc_evnt.c - LLC station component event match functions
+ * Description :
+ * Functions in this module are implementation of station component events.
+ * Details of events can be found in IEEE-802.2 standard document.
+ * All functions have one station and one event as input argument. All of
+ * them return 0 On success and 1 otherwise.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <net/llc_if.h>
+#include <net/llc_main.h>
+#include <net/llc_evnt.h>
+#include <net/llc_pdu.h>
+
+int llc_stat_ev_enable_with_dup_addr_check(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
+ ev->data.a.ev ==
+ LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
+}
+
+int llc_stat_ev_enable_without_dup_addr_check(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
+ ev->data.a.ev ==
+ LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
+}
+
+int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
+ station->retry_count < station->maximum_retry ? 0 : 1;
+}
+
+int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
+ station->retry_count == station->maximum_retry ? 0 : 1;
+}
+
+int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_STATION_EV_TYPE_PDU &&
+ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
+ !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
+ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID &&
+ !pdu->dsap ? 0 : 1; /* NULL DSAP value */
+}
+
+int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_STATION_EV_TYPE_PDU &&
+ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
+ !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
+ LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID &&
+ !pdu->dsap && /* NULL DSAP value */
+ !station->xid_r_count ? 0 : 1;
+}
+
+int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_STATION_EV_TYPE_PDU &&
+ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
+ !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
+ LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID &&
+ !pdu->dsap && /* NULL DSAP value */
+ station->xid_r_count == 1 ? 0 : 1;
+}
+
+int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_STATION_EV_TYPE_PDU &&
+ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
+ !LLC_PDU_TYPE_IS_U(pdu) && /* U type PDU */
+ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST &&
+ !pdu->dsap ? 0 : 1; /* NULL DSAP */
+}
+
+int llc_stat_ev_disable_req(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ return ev->type == LLC_STATION_EV_TYPE_PRIM &&
+ ev->data.prim.prim == LLC_DISABLE_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c
new file mode 100644
index 000000000000..f41c1ff22348
--- /dev/null
+++ b/net/llc/llc_if.c
@@ -0,0 +1,530 @@
+/*
+ * llc_if.c - Defines LLC interface to upper layer
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <asm/errno.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_conn.h>
+#include <net/sock.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_c_st.h>
+#include <net/llc_main.h>
+#include <net/llc_mac.h>
+
+static int llc_sap_req(struct llc_prim_if_block *prim);
+static int llc_unitdata_req_handler(struct llc_prim_if_block *prim);
+static int llc_test_req_handler(struct llc_prim_if_block *prim);
+static int llc_xid_req_handler(struct llc_prim_if_block *prim);
+static int llc_data_req_handler(struct llc_prim_if_block *prim);
+static int llc_conn_req_handler(struct llc_prim_if_block *prim);
+static int llc_disc_req_handler(struct llc_prim_if_block *prim);
+static int llc_rst_req_handler(struct llc_prim_if_block *prim);
+static int llc_flowcontrol_req_handler(struct llc_prim_if_block *prim);
+static int llc_sap_resp(struct llc_prim_if_block *prim);
+static int llc_conn_rsp_handler(struct llc_prim_if_block *prim);
+static int llc_rst_rsp_handler(struct llc_prim_if_block *prim);
+static int llc_no_rsp_handler(struct llc_prim_if_block *prim);
+
+extern void llc_register_sap(unsigned char sap,
+ int (*rcvfunc)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt));
+extern void llc_unregister_sap(unsigned char sap);
+
+/* table of request handler functions */
+static llc_prim_call_t llc_req_prim[LLC_NBR_PRIMITIVES] = {
+ [LLC_DATAUNIT_PRIM] = llc_unitdata_req_handler,
+ [LLC_CONN_PRIM] = llc_conn_req_handler,
+ [LLC_DATA_PRIM] = llc_data_req_handler,
+ [LLC_DISC_PRIM] = llc_disc_req_handler,
+ [LLC_RESET_PRIM] = llc_rst_req_handler,
+ [LLC_FLOWCONTROL_PRIM] = llc_flowcontrol_req_handler,
+ [LLC_XID_PRIM] = llc_xid_req_handler,
+ [LLC_TEST_PRIM] = llc_test_req_handler,
+};
+
+/* table of response handler functions */
+static llc_prim_call_t llc_resp_prim[LLC_NBR_PRIMITIVES] = {
+ [LLC_DATAUNIT_PRIM] = llc_no_rsp_handler,
+ [LLC_CONN_PRIM] = llc_conn_rsp_handler,
+ [LLC_DATA_PRIM] = llc_no_rsp_handler,
+ [LLC_DISC_PRIM] = llc_no_rsp_handler,
+ [LLC_RESET_PRIM] = llc_rst_rsp_handler,
+ [LLC_FLOWCONTROL_PRIM] = llc_no_rsp_handler,
+};
+
+/**
+ * llc_sap_open - open interface to the upper layers.
+ * @nw_indicate: pointer to indicate function of upper layer.
+ * @nw_confirm: pointer to confirm function of upper layer.
+ * @lsap: SAP number.
+ * @sap: pointer to allocated SAP (output argument).
+ *
+ * Interface function to upper layer. each one who wants to get a SAP
+ * (for example NetBEUI) should call this function. Returns 0 for
+ * success, 1 for failure.
+ */
+struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate,
+ llc_prim_call_t nw_confirm, u8 lsap)
+{
+ /* verify this SAP is not already open; if so, return error */
+ struct llc_sap *sap;
+
+ MOD_INC_USE_COUNT;
+ sap = llc_sap_find(lsap);
+ if (sap) { /* SAP already exists */
+ sap = NULL;
+ goto err;
+ }
+ /* sap requested does not yet exist */
+ sap = llc_sap_alloc();
+ if (!sap)
+ goto err;
+ /* allocated a SAP; initialize it and clear out its memory pool */
+ sap->laddr.lsap = lsap;
+ sap->req = llc_sap_req;
+ sap->resp = llc_sap_resp;
+ sap->ind = nw_indicate;
+ sap->conf = nw_confirm;
+ sap->parent_station = llc_station_get();
+ /* initialized SAP; add it to list of SAPs this station manages */
+ llc_sap_save(sap);
+ llc_register_sap(lsap, mac_indicate);
+out:
+ return sap;
+err:
+ MOD_DEC_USE_COUNT;
+ goto out;
+}
+
+/**
+ * llc_sap_close - close interface for upper layers.
+ * @sap: SAP to be closed.
+ *
+ * Close interface function to upper layer. each one who wants to
+ * close an open SAP (for example NetBEUI) should call this function.
+ */
+void llc_sap_close(struct llc_sap *sap)
+{
+ llc_unregister_sap(sap->laddr.lsap);
+ llc_free_sap(sap);
+ MOD_DEC_USE_COUNT;
+}
+
+/**
+ * llc_sap_req - Request interface for upper layers
+ * @prim: pointer to structure that contains service parameters.
+ *
+ * Request interface function to upper layer. each one who wants to
+ * request a service from LLC, must call this function. details of
+ * requested service is defined in input argument(prim). Returns 0 for
+ * success, 1 otherwise.
+ */
+static int llc_sap_req(struct llc_prim_if_block *prim)
+{
+ int rc = 1;
+
+ if (prim->prim > 8 || prim->prim == 6) {
+ printk(KERN_ERR __FUNCTION__ ": invalid primitive %d\n",
+ prim->prim);
+ goto out;
+ }
+ /* receive REQUEST primitive from network layer; call the appropriate
+ * primitive handler which then packages it up as an event and sends it
+ * to the SAP or CONNECTION event handler
+ */
+ if (prim->prim < LLC_NBR_PRIMITIVES)
+ /* valid primitive; call the function to handle it */
+ rc = llc_req_prim[prim->prim](prim);
+out:
+ return rc;
+}
+
+/**
+ * llc_unitdata_req_handler - unitdata request interface for upper layers
+ * @prim: pointer to structure that contains service parameters
+ *
+ * Upper layers calls this function when upper layer wants to send data
+ * using connection-less mode communication (UI pdu). Returns 0 for
+ * success, 1 otherwise.
+ */
+static int llc_unitdata_req_handler(struct llc_prim_if_block *prim)
+{
+ int rc = 1;
+ struct llc_sap_state_ev *ev;
+ /* accept data frame from network layer to be sent using connection-
+ * less mode communication; timeout/retries handled by network layer;
+ * package primitive as an event and send to SAP event handler
+ */
+ struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap);
+
+ if (!sap)
+ goto out;
+ ev = llc_sap_alloc_ev(sap);
+ if (!ev)
+ goto out;
+ ev->type = LLC_SAP_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_DATAUNIT_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ rc = 0;
+ llc_sap_send_ev(sap, ev);
+out:
+ return rc;
+}
+
+/**
+ * llc_test_req_handler - TEST interface for upper layers.
+ * @prim: pointer to structure that contains service parameters.
+ *
+ * This function is called when upper layer wants to send a TEST pdu.
+ * Returns 0 for success, 1 otherwise.
+ */
+static int llc_test_req_handler(struct llc_prim_if_block *prim)
+{
+ int rc = 1;
+ struct llc_sap_state_ev *ev;
+ /* package primitive as an event and send to SAP event handler */
+ struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap);
+ if (!sap)
+ goto out;
+ ev = llc_sap_alloc_ev(sap);
+ if (!ev)
+ goto out;
+ ev->type = LLC_SAP_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_TEST_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ rc = 0;
+ llc_sap_send_ev(sap, ev);
+out:
+ return rc;
+}
+
+/**
+ * llc_xid_req_handler - XID interface for upper layers
+ * @prim: pointer to structure that contains service parameters.
+ *
+ * This function is called when upper layer wants to send a XID pdu.
+ * Returns 0 for success, 1 otherwise.
+ */
+static int llc_xid_req_handler(struct llc_prim_if_block *prim)
+{
+ int rc = 1;
+ struct llc_sap_state_ev *ev;
+ /* package primitive as an event and send to SAP event handler */
+ struct llc_sap *sap = llc_sap_find(prim->data->udata.saddr.lsap);
+
+ if (!sap)
+ goto out;
+ ev = llc_sap_alloc_ev(sap);
+ if (!ev)
+ goto out;
+ ev->type = LLC_SAP_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_XID_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ rc = 0;
+ llc_sap_send_ev(sap, ev);
+out:
+ return rc;
+}
+
+/**
+ * llc_data_req_handler - Connection data sending for upper layers.
+ * @prim: pointer to structure that contains service parameters
+ *
+ * This function is called when upper layer wants to send data using
+ * connection oriented communication mode. during sending data, connection
+ * will be locked and received frames and expired timers will be queued.
+ * Returns 0 for success, -ECONNABORTED when the connection already
+ * closed. and -EBUSY when sending data is not permitted in this state or
+ * LLC has send an I pdu with p bit set to 1 and is waiting for it's
+ * response.
+ */
+static int llc_data_req_handler(struct llc_prim_if_block *prim)
+{
+ struct llc_conn_state_ev *ev;
+ int rc = -ECONNABORTED;
+ /* accept data frame from network layer to be sent using connection
+ * mode communication; timeout/retries handled by this layer;
+ * package primitive as an event and send to connection event handler
+ */
+ struct sock *sk = prim->data->data.sk;
+ struct llc_opt *llc = llc_sk(sk);
+
+ lock_sock(sk);
+ if (llc->state == LLC_CONN_STATE_ADM)
+ goto out;
+ rc = -EBUSY;
+ if (llc_data_accept_state(llc->state)) { /* data_conn_refuse */
+ llc->failed_data_req = 1;
+ goto out;
+ }
+ if (llc->p_flag) {
+ llc->failed_data_req = 1;
+ goto out;
+ }
+ rc = -ENOMEM;
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_DATA_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ prim->data->data.skb->dev = llc->dev;
+ rc = llc_conn_send_ev(sk, ev);
+ }
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * confirm_impossible - Informs upper layer about failed connection
+ * @prim: pointer to structure that contains confirmation data.
+ *
+ * Informs upper layer about failing in connection establishment. This
+ * function is called by llc_conn_req_handler.
+ */
+static void confirm_impossible(struct llc_prim_if_block *prim)
+{
+ prim->data->conn.status = LLC_STATUS_IMPOSSIBLE;
+ prim->sap->conf(prim);
+}
+
+/**
+ * llc_conn_req_handler - Called by upper layer to establish a conn
+ * @prim: pointer to structure that contains service parameters.
+ *
+ * Upper layer calls this to establish an LLC connection with a remote
+ * machine. this function packages a proper event and sends it connection
+ * component state machine. Success or failure of connection
+ * establishment will inform to upper layer via calling it's confirm
+ * function and passing proper information.
+ */
+static int llc_conn_req_handler(struct llc_prim_if_block *prim)
+{
+ int rc = -EBUSY;
+ struct llc_opt *llc;
+ struct llc_sap *sap = prim->sap;
+ struct llc_conn_state_ev *ev;
+ struct net_device *ddev = mac_dev_peer(prim->data->conn.dev,
+ prim->data->conn.dev->type,
+ prim->data->conn.daddr.mac),
+ *sdev = (ddev->flags & IFF_LOOPBACK) ?
+ ddev : prim->data->conn.dev;
+ struct llc_addr laddr, daddr;
+ /* network layer supplies addressing required to establish connection;
+ * package as an event and send it to the connection event handler
+ */
+ struct sock *sk;
+
+ memcpy(laddr.mac, sdev->dev_addr, sizeof(laddr.mac));
+ laddr.lsap = prim->data->conn.saddr.lsap;
+ memcpy(daddr.mac, ddev->dev_addr, sizeof(daddr.mac));
+ daddr.lsap = prim->data->conn.daddr.lsap;
+ sk = llc_find_sock(sap, &daddr, &laddr);
+ if (sk) {
+ confirm_impossible(prim);
+ goto out_put;
+ }
+ rc = -ENOMEM;
+ if (prim->data->conn.sk) {
+ sk = prim->data->conn.sk;
+ if (llc_sock_init(sk))
+ goto out;
+ } else {
+ sk = llc_sock_alloc();
+ if (!sk) {
+ confirm_impossible(prim);
+ goto out;
+ }
+ prim->data->conn.sk = sk;
+ }
+ sock_hold(sk);
+ lock_sock(sk);
+ /* assign new connection to it's SAP */
+ llc_sap_assign_sock(sap, sk);
+ llc = llc_sk(sk);
+ memcpy(&llc->daddr, &daddr, sizeof(llc->daddr));
+ memcpy(&llc->laddr, &laddr, sizeof(llc->laddr));
+ llc->dev = ddev;
+ llc->link = prim->data->conn.link;
+ llc->handler = prim->data->conn.handler;
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_CONN_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ rc = llc_conn_send_ev(sk, ev);
+ }
+ if (rc) {
+ llc_sap_unassign_sock(sap, sk);
+ llc_sock_free(sk);
+ confirm_impossible(prim);
+ }
+ release_sock(sk);
+out_put:
+ sock_put(sk);
+out:
+ return rc;
+}
+
+/**
+ * llc_disc_req_handler - Called by upper layer to close a connection
+ * @prim: pointer to structure that contains service parameters.
+ *
+ * Upper layer calls this when it wants to close an established LLC
+ * connection with a remote machine. this function packages a proper event
+ * and sends it to connection component state machine. Returns 0 for
+ * success, 1 otherwise.
+ */
+static int llc_disc_req_handler(struct llc_prim_if_block *prim)
+{
+ u16 rc = 1;
+ struct llc_conn_state_ev *ev;
+ struct sock* sk = prim->data->disc.sk;
+
+ sock_hold(sk);
+ lock_sock(sk);
+ if (llc_sk(sk)->state == LLC_CONN_STATE_ADM ||
+ llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC)
+ goto out;
+ /* postpone unassigning the connection from its SAP and returning the
+ * connection until all ACTIONs have been completely executed
+ */
+ ev = llc_conn_alloc_ev(sk);
+ if (!ev)
+ goto out;
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_DISC_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ rc = llc_conn_send_ev(sk, ev);
+out:
+ release_sock(sk);
+ sock_put(sk);
+ return rc;
+}
+
+/**
+ * llc_rst_req_handler - Resets an established LLC connection
+ * @prim: pointer to structure that contains service parameters.
+ *
+ * Called when upper layer wants to reset an established LLC connection
+ * with a remote machine. this function packages a proper event and sends
+ * it to connection component state machine. Returns 0 for success, 1
+ * otherwise.
+ */
+static int llc_rst_req_handler(struct llc_prim_if_block *prim)
+{
+ int rc = 1;
+ struct sock *sk = prim->data->res.sk;
+ struct llc_conn_state_ev *ev;
+
+ lock_sock(sk);
+ ev = llc_conn_alloc_ev(sk);
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_RESET_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_REQ;
+ ev->data.prim.data = prim;
+ rc = llc_conn_send_ev(sk, ev);
+ }
+ release_sock(sk);
+ return rc;
+}
+
+/* We don't support flow control. The original code from procom has
+ * some bits, but for now I'm cleaning this
+ */
+static int llc_flowcontrol_req_handler(struct llc_prim_if_block *prim)
+{
+ return 1;
+}
+
+/**
+ * llc_sap_resp - Sends response to peer
+ * @prim: pointer to structure that contains service parameters
+ *
+ * This function is a interface function to upper layer. each one who
+ * wants to response to an indicate can call this function via calling
+ * sap_resp with proper service parameters. Returns 0 for success, 1
+ * otherwise.
+ */
+static int llc_sap_resp(struct llc_prim_if_block *prim)
+{
+ u16 rc = 1;
+ /* network layer RESPONSE primitive received; package primitive
+ * as an event and send it to the connection event handler
+ */
+ if (prim->prim < LLC_NBR_PRIMITIVES)
+ /* valid primitive; call the function to handle it */
+ rc = llc_resp_prim[prim->prim](prim);
+ return rc;
+}
+
+/**
+ * llc_conn_rsp_handler - Response to connect indication
+ * @prim: pointer to structure that contains response info.
+ *
+ * Response to connect indication.
+ */
+static int llc_conn_rsp_handler(struct llc_prim_if_block *prim)
+{
+ struct sock *sk = prim->data->conn.sk;
+
+ llc_sk(sk)->link = prim->data->conn.link;
+ return 0;
+}
+
+/**
+ * llc_rst_rsp_handler - Response to RESET indication
+ * @prim: pointer to structure that contains response info
+ *
+ * Returns 0 for success, 1 otherwise
+ */
+static int llc_rst_rsp_handler(struct llc_prim_if_block *prim)
+{
+ int rc = 1;
+ /* network layer supplies connection handle; map it to a connection;
+ * package as event and send it to connection event handler
+ */
+ struct sock *sk = prim->data->res.sk;
+ struct llc_conn_state_ev *ev = llc_conn_alloc_ev(sk);
+
+ if (ev) {
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->data.prim.prim = LLC_RESET_PRIM;
+ ev->data.prim.type = LLC_PRIM_TYPE_RESP;
+ ev->data.prim.data = prim;
+ rc = llc_conn_send_ev(sk, ev);
+ }
+ return rc;
+}
+
+static int llc_no_rsp_handler(struct llc_prim_if_block *prim)
+{
+ return 0;
+}
+
+EXPORT_SYMBOL(llc_sap_open);
+EXPORT_SYMBOL(llc_sap_close);
diff --git a/net/llc/llc_mac.c b/net/llc/llc_mac.c
new file mode 100644
index 000000000000..2a6905f1f0c0
--- /dev/null
+++ b/net/llc/llc_mac.c
@@ -0,0 +1,317 @@
+/*
+ * llc_mac.c - Manages interface between LLC and MAC
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_tr.h>
+#include <linux/rtnetlink.h>
+#include <net/llc_if.h>
+#include <net/llc_mac.h>
+#include <net/llc_pdu.h>
+#include <net/llc_sap.h>
+#include <net/llc_conn.h>
+#include <net/sock.h>
+#include <net/llc_main.h>
+#include <net/llc_evnt.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_s_ev.h>
+#ifdef CONFIG_TR
+extern void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh,
+ struct net_device *dev);
+#endif
+/* function prototypes */
+static void fix_up_incoming_skb(struct sk_buff *skb);
+
+/**
+ * mac_send_pdu - Sends PDU to specific device.
+ * @skb: pdu which must be sent
+ *
+ * If module is not initialized then returns failure, else figures out
+ * where to direct this PDU. Sends PDU to specific device, at this point a
+ * device must has been assigned to the PDU; If not, can't transmit the
+ * PDU. PDU sent to MAC layer, is free to re-send at a later time. Returns
+ * 0 on success, 1 for failure.
+ */
+int mac_send_pdu(struct sk_buff *skb)
+{
+ struct sk_buff *skb2;
+ int pri = GFP_ATOMIC, rc = -1;
+
+ if (!skb->dev) {
+ printk(KERN_ERR __FUNCTION__ ": skb->dev == NULL!");
+ goto out;
+ }
+ if (skb->sk)
+ pri = (int)skb->sk->priority;
+ skb2 = skb_clone(skb, pri);
+ if (!skb2)
+ goto out;
+ rc = 0;
+ dev_queue_xmit(skb2);
+out:
+ return rc;
+}
+
+/**
+ * mac_indicate - 802.2 entry point from net lower layers
+ * @skb: received pdu
+ * @dev: device that receive pdu
+ * @pt: packet type
+ *
+ * When the system receives a 802.2 frame this function is called. It
+ * checks SAP and connection of received pdu and passes frame to
+ * llc_pdu_router for sending to proper state machine. If frame is
+ * related to a busy connection (a connection is sending data now),
+ * function queues this frame in connection's backlog.
+ */
+int mac_indicate(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+ struct llc_sap *sap;
+ llc_pdu_sn_t *pdu;
+ u8 dest;
+
+ /* When the interface is in promisc. mode, drop all the crap that it
+ * receives, do not try to analyse it.
+ */
+ if (skb->pkt_type == PACKET_OTHERHOST) {
+ printk(KERN_INFO __FUNCTION__ ": PACKET_OTHERHOST\n");
+ goto drop;
+ }
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (!skb)
+ goto out;
+ fix_up_incoming_skb(skb);
+ pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ if (!pdu->dsap) { /* NULL DSAP, refer to station */
+ llc_pdu_router(NULL, NULL, skb, 0);
+ goto out;
+ }
+ sap = llc_sap_find(pdu->dsap);
+ if (!sap) /* unknown SAP */
+ goto drop;
+ llc_decode_pdu_type(skb, &dest);
+ if (dest == LLC_DEST_SAP) /* type 1 services */
+ llc_pdu_router(sap, NULL, skb, LLC_TYPE_1);
+ else if (dest == LLC_DEST_CONN) {
+ struct llc_addr saddr, daddr;
+ struct sock *sk;
+
+ llc_pdu_decode_sa(skb, saddr.mac);
+ llc_pdu_decode_ssap(skb, &saddr.lsap);
+ llc_pdu_decode_da(skb, daddr.mac);
+ llc_pdu_decode_dsap(skb, &daddr.lsap);
+
+ sk = llc_find_sock(sap, &saddr, &daddr);
+ if (!sk) { /* didn't find an active connection; allocate a
+ * connection to use; associate it with this SAP
+ */
+ sk = llc_sock_alloc();
+ if (!sk)
+ goto drop;
+ memcpy(&llc_sk(sk)->daddr, &saddr, sizeof(saddr));
+ llc_sap_assign_sock(sap, sk);
+ sock_hold(sk);
+ }
+ bh_lock_sock(sk);
+ if (!sk->lock.users) {
+ /* FIXME: Check this on SMP as it is now calling
+ * llc_pdu_router _with_ the lock held.
+ * 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...
+ */
+ llc_pdu_router(llc_sk(sk)->sap, sk, skb, LLC_TYPE_2);
+ bh_unlock_sock(sk);
+ } else {
+ skb->cb[0] = LLC_PACKET;
+ sk_add_backlog(sk, skb);
+ bh_unlock_sock(sk);
+ }
+ sock_put(sk);
+ } else /* unknown or not supported pdu */
+ goto drop;
+out:
+ return 0;
+drop:
+ kfree_skb(skb);
+ goto out;
+}
+
+/**
+ * fix_up_incoming_skb - initializes skb pointers
+ * @skb: This argument points to incoming skb
+ *
+ * Initializes internal skb pointer to start of network layer by deriving
+ * length of LLC header; finds length of LLC control field in LLC header
+ * by looking at the two lowest-order bits of the first control field
+ * byte; field is either 3 or 4 bytes long.
+ */
+static void fix_up_incoming_skb(struct sk_buff *skb)
+{
+ u8 llc_len = 2;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->data;
+
+ if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
+ llc_len = 1;
+ llc_len += 2;
+ skb_pull(skb, llc_len);
+ if (skb->protocol == htons(ETH_P_802_2)) {
+ u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
+ data_size = ntohs(pdulen) - llc_len;
+
+ skb_trim(skb, data_size);
+ }
+}
+
+/**
+ * llc_pdu_router - routes received pdus to the upper layers
+ * @sap: current sap component structure.
+ * @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
+ * 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,
+ struct sk_buff *skb, u8 type)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+ int rc = 0;
+
+ if (!pdu->dsap) {
+ struct llc_station *station = llc_station_get();
+ struct llc_station_state_ev *stat_ev =
+ llc_station_alloc_ev(station);
+ if (stat_ev) {
+ stat_ev->type = LLC_STATION_EV_TYPE_PDU;
+ stat_ev->data.pdu.skb = skb;
+ stat_ev->data.pdu.reason = 0;
+ llc_station_send_ev(station, stat_ev);
+ }
+ } else if (type == LLC_TYPE_1) {
+ struct llc_sap_state_ev *sap_ev = llc_sap_alloc_ev(sap);
+
+ if (sap_ev) {
+ sap_ev->type = LLC_SAP_EV_TYPE_PDU;
+ sap_ev->data.pdu.skb = skb;
+ sap_ev->data.pdu.reason = 0;
+ llc_sap_send_ev(sap, sap_ev);
+ }
+ } else if (type == LLC_TYPE_2) {
+ struct llc_conn_state_ev *conn_ev = llc_conn_alloc_ev(sk);
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (!llc->dev)
+ llc->dev = skb->dev;
+ if (conn_ev) {
+ conn_ev->type = LLC_CONN_EV_TYPE_PDU;
+ conn_ev->data.pdu.skb = skb;
+ conn_ev->data.pdu.reason = 0;
+ rc = llc_conn_send_ev(sk, conn_ev);
+ }
+ }
+ return rc;
+}
+
+/**
+ * lan_hdrs_init - fills MAC header fields
+ * @skb: Address of the frame to initialize its MAC header
+ * @sa: The MAC source address
+ * @da: The MAC destination address
+ *
+ * Fills MAC header fields, depending on MAC type. Returns 0, If MAC type
+ * is a valid type and initialization completes correctly 1, otherwise.
+ */
+u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da)
+{
+ u8 *saddr;
+ u8 *daddr;
+ u16 rc = 0;
+
+ switch (skb->dev->type) {
+#ifdef CONFIG_TR
+ case ARPHRD_IEEE802_TR: {
+ struct trh_hdr *trh = (struct trh_hdr *)
+ skb_push(skb, sizeof(*trh));
+ struct net_device *dev = skb->dev;
+
+ trh->ac = AC;
+ trh->fc = LLC_FRAME;
+ if (sa)
+ memcpy(trh->saddr, sa, dev->addr_len);
+ else
+ memset(trh->saddr, 0, dev->addr_len);
+ if (da) {
+ memcpy(trh->daddr, da, dev->addr_len);
+ tr_source_route(skb, trh, dev);
+ }
+ skb->mac.raw = skb->data;
+ break;
+ }
+#endif
+ case ARPHRD_ETHER:
+ case ARPHRD_LOOPBACK: {
+ unsigned short len = skb->len;
+
+ skb->mac.raw = skb_push(skb, sizeof(struct ethhdr));
+ memset(skb->mac.raw, 0, sizeof(struct ethhdr));
+ ((struct ethhdr *)skb->mac.raw)->h_proto = htons(len);
+ daddr = ((struct ethhdr *)skb->mac.raw)->h_dest;
+ saddr = ((struct ethhdr *)skb->mac.raw)->h_source;
+ memcpy(daddr, da, ETH_ALEN);
+ memcpy(saddr, sa, ETH_ALEN);
+ break;
+ }
+ default:
+ printk(KERN_WARNING "Unknown DEVICE type : %d\n",
+ skb->dev->type);
+ rc = 1;
+ }
+ return rc;
+}
+
+/**
+ * mac_dev_peer - search the appropriate dev to send packets to peer
+ * @current_dev - Current device suggested by upper layer
+ * @type - hardware type
+ * @mac - mac address
+ *
+ * Check if the we should use loopback to send packets, i.e., if the
+ * dmac belongs to one of the local interfaces, returning the pointer
+ * to the loopback &net_device struct or the current_dev if it is not
+ * local.
+ */
+struct net_device *mac_dev_peer(struct net_device *current_dev, int type,
+ u8 *mac)
+{
+ struct net_device *dev;
+
+ rtnl_lock();
+ dev = dev_getbyhwaddr(type, mac);
+ if (dev)
+ dev = __dev_get_by_name("lo");
+ rtnl_unlock();
+ return dev ? : current_dev;
+}
diff --git a/net/llc/llc_main.c b/net/llc/llc_main.c
new file mode 100644
index 000000000000..23fb884d704a
--- /dev/null
+++ b/net/llc/llc_main.c
@@ -0,0 +1,641 @@
+/*
+ * llc_main.c - This module contains main functions to manage station, saps
+ * and connections of the LLC.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_conn.h>
+#include <net/llc_main.h>
+#include <net/llc_evnt.h>
+#include <net/llc_actn.h>
+#include <net/llc_stat.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_s_ac.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_st.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_s_st.h>
+#include <net/llc_mac.h>
+#include <linux/llc.h>
+
+/* static function prototypes */
+static void llc_station_service_events(struct llc_station *station);
+static void llc_station_free_ev(struct llc_station *station,
+ struct llc_station_state_ev *ev);
+static void llc_station_send_pdus(struct llc_station *station);
+static u16 llc_station_next_state(struct llc_station *station,
+ struct llc_station_state_ev *ev);
+static u16 llc_exec_station_trans_actions(struct llc_station *station,
+ struct llc_station_state_trans *trans,
+ struct llc_station_state_ev *ev);
+static struct llc_station_state_trans *
+ llc_find_station_trans(struct llc_station *station,
+ struct llc_station_state_ev *ev);
+static int llc_rtn_all_conns(struct llc_sap *sap);
+
+extern void llc_register_sap(unsigned char sap,
+ int (*rcvfunc)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt));
+extern void llc_unregister_sap(unsigned char sap);
+
+static struct llc_station llc_main_station; /* only one of its kind */
+struct llc_prim_if_block llc_ind_prim, llc_cfm_prim;
+static union llc_u_prim_data llc_ind_data_prim, llc_cfm_data_prim;
+
+/**
+ * llc_sap_alloc - allocates and initializes sap.
+ *
+ * Allocates and initializes sap.
+ */
+struct llc_sap *llc_sap_alloc(void)
+{
+ struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
+
+ if (sap) {
+ memset(sap, 0, sizeof(*sap));
+ sap->state = LLC_SAP_STATE_ACTIVE;
+ memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN);
+ spin_lock_init(&sap->sk_list.lock);
+ INIT_LIST_HEAD(&sap->sk_list.list);
+ skb_queue_head_init(&sap->mac_pdu_q);
+ }
+ return sap;
+}
+
+/**
+ * llc_free_sap - frees a sap
+ * @sap: Address of the sap
+ *
+ * Frees all associated connections (if any), removes this sap from
+ * the list of saps in te station and them frees the memory for this sap.
+ */
+void llc_free_sap(struct llc_sap *sap)
+{
+ struct llc_station *station = sap->parent_station;
+
+ llc_rtn_all_conns(sap);
+ spin_lock_bh(&station->sap_list.lock);
+ list_del(&sap->node);
+ spin_unlock_bh(&station->sap_list.lock);
+ kfree(sap);
+}
+
+/**
+ * llc_sap_save - add sap to station list
+ * @sap: Address of the sap
+ *
+ * Adds a sap to the LLC's station sap list.
+ */
+void llc_sap_save(struct llc_sap *sap)
+{
+ spin_lock_bh(&llc_main_station.sap_list.lock);
+ list_add_tail(&sap->node, &llc_main_station.sap_list.list);
+ spin_unlock_bh(&llc_main_station.sap_list.lock);
+}
+
+/**
+ * llc_sap_find - searchs a SAP in station
+ * @sap_value: sap to be found
+ *
+ * Searchs for a sap in the sap list of the LLC's station upon the sap ID.
+ * Returns the sap or %NULL if not found.
+ */
+struct llc_sap *llc_sap_find(u8 sap_value)
+{
+ struct llc_sap* sap = NULL;
+ struct list_head *entry;
+
+ spin_lock_bh(&llc_main_station.sap_list.lock);
+ list_for_each(entry, &llc_main_station.sap_list.list) {
+ sap = list_entry(entry, struct llc_sap, node);
+ if (sap->laddr.lsap == sap_value)
+ break;
+ }
+ if (entry == &llc_main_station.sap_list.list) /* not found */
+ sap = NULL;
+ spin_unlock_bh(&llc_main_station.sap_list.lock);
+ return sap;
+}
+
+/**
+ * llc_backlog_rcv - Processes rx frames and expired timers.
+ * @sk: LLC sock (p8022 connection)
+ * @skb: queued rx frame or event
+ *
+ * This function processes frames that has received and timers that has
+ * 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
+ * callback functions(llc_c_ac.c).
+ */
+static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = 0;
+ struct llc_opt *llc = llc_sk(sk);
+
+ if (skb->cb[0] == LLC_PACKET) {
+ if (llc->state > 1) /* not closed */
+ rc = llc_pdu_router(llc->sap, sk, skb, LLC_TYPE_2);
+ else
+ kfree_skb(skb);
+ } else if (skb->cb[0] == LLC_EVENT) {
+ struct llc_conn_state_ev *ev =
+ (struct llc_conn_state_ev *)skb->data;
+ /* timer expiration event */
+ if (llc->state > 1) /* not closed */
+ rc = llc_conn_send_ev(sk, ev);
+ else
+ llc_conn_free_ev(ev);
+ kfree_skb(skb);
+ }
+ return rc;
+}
+
+/**
+ * llc_sock_init - Initialize a socket with default llc values.
+ * @sk: socket to intiailize.
+ */
+int llc_sock_init(struct sock* sk)
+{
+ struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC);
+ int rc = -ENOMEM;
+
+ if (!llc)
+ goto out;
+ memset(llc, 0, sizeof(*llc));
+ rc = 0;
+ llc->sk = sk;
+ llc->state = LLC_CONN_STATE_ADM;
+ llc->inc_cntr = llc->dec_cntr = 2;
+ llc->dec_step = llc->connect_step = 1;
+ llc->ack_timer.expire = LLC_ACK_TIME;
+ llc->pf_cycle_timer.expire = LLC_P_TIME;
+ llc->rej_sent_timer.expire = LLC_REJ_TIME;
+ llc->busy_state_timer.expire = LLC_BUSY_TIME;
+ llc->n2 = 2; /* max retransmit */
+ llc->k = 2; /* tx win size, will adjust dynam */
+ llc->rw = 128; /* rx win size (opt and equal to
+ * tx_win of remote LLC)
+ */
+ skb_queue_head_init(&llc->pdu_unack_q);
+ sk->backlog_rcv = llc_backlog_rcv;
+ llc_sk(sk) = llc;
+out:
+ return rc;
+}
+
+/**
+ * __llc_sock_alloc - Allocates LLC sock
+ *
+ * Allocates a LLC sock and initializes it. Returns the new LLC sock
+ * or %NULL if there's no memory available for one
+ */
+struct sock *__llc_sock_alloc(void)
+{
+ struct sock *sk = sk_alloc(PF_LLC, GFP_ATOMIC, 1, NULL);
+
+ if (!sk)
+ goto out;
+ if (llc_sock_init(sk))
+ goto outsk;
+ sock_init_data(NULL, sk);
+out:
+ return sk;
+outsk:
+ sk_free(sk);
+ sk = NULL;
+ goto out;
+}
+
+/**
+ * __llc_sock_free - Frees a LLC socket
+ * @sk - socket to free
+ *
+ * Frees a LLC socket
+ */
+void __llc_sock_free(struct sock *sk, u8 free)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc->state = LLC_CONN_OUT_OF_SVC;
+ /* stop all (possibly) running timers */
+ llc_conn_ac_stop_all_timers(sk, NULL);
+ /* handle return of frames on lists */
+ printk(KERN_INFO __FUNCTION__ ": unackq=%d, txq=%d\n",
+ skb_queue_len(&llc->pdu_unack_q),
+ skb_queue_len(&sk->write_queue));
+ skb_queue_purge(&sk->write_queue);
+ skb_queue_purge(&llc->pdu_unack_q);
+ if (free)
+ sock_put(sk);
+}
+
+/**
+ * llc_sock_reset - resets a connection
+ * @sk: LLC socket to reset
+ *
+ * Resets a connection to the out of service state. Stops its timers
+ * and frees any frames in the queues of the connection.
+ */
+void llc_sock_reset(struct sock *sk)
+{
+ struct llc_opt *llc = llc_sk(sk);
+
+ llc_conn_ac_stop_all_timers(sk, NULL);
+ skb_queue_purge(&sk->write_queue);
+ skb_queue_purge(&llc->pdu_unack_q);
+ llc->remote_busy_flag = 0;
+ llc->cause_flag = 0;
+ llc->retry_count = 0;
+ llc->p_flag = 0;
+ llc->f_flag = 0;
+ llc->s_flag = 0;
+ llc->ack_pf = 0;
+ llc->first_pdu_Ns = 0;
+ llc->ack_must_be_send = 0;
+ llc->dec_step = 1;
+ llc->inc_cntr = 2;
+ llc->dec_cntr = 2;
+ llc->X = 0;
+ llc->failed_data_req = 0 ;
+ llc->last_nr = 0;
+}
+
+/**
+ * llc_rtn_all_conns - Closes all connections of a sap
+ * @sap: sap to close its connections
+ *
+ * Closes all connections of a sap. Returns 0 if all actions complete
+ * successfully, nonzero otherwise
+ */
+static int llc_rtn_all_conns(struct llc_sap *sap)
+{
+ int rc = 0;
+ union llc_u_prim_data prim_data;
+ struct llc_prim_if_block prim;
+ struct list_head *entry, *tmp;
+
+ spin_lock_bh(&sap->sk_list.lock);
+ if (list_empty(&sap->sk_list.list))
+ goto out;
+ list_for_each_safe(entry, tmp, &sap->sk_list.list) {
+ struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
+
+ prim.sap = sap;
+ prim_data.disc.sk = llc->sk;
+ prim.prim = LLC_DISC_PRIM;
+ prim.data = &prim_data;
+ llc->state = LLC_CONN_STATE_TEMP;
+ if (sap->req(&prim))
+ rc = 1;
+ }
+out:
+ spin_unlock_bh(&sap->sk_list.lock);
+ return rc;
+}
+
+/**
+ * llc_station_get - get addr of global station.
+ *
+ * Returns address of a place to copy the global station to it.
+ */
+struct llc_station *llc_station_get(void)
+{
+ return &llc_main_station;
+}
+
+/**
+ * llc_station_alloc_ev - allocates an event
+ * @station: Address of the station
+ *
+ * Allocates an event in this station. Returns the allocated event on
+ * success, %NULL otherwise.
+ */
+struct llc_station_state_ev *llc_station_alloc_ev(struct llc_station *station)
+{
+ struct llc_station_state_ev *ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+
+ if (ev)
+ memset(ev, 0, sizeof(*ev));
+ return ev;
+}
+
+/**
+ * llc_station_send_ev: queue event and try to process queue.
+ * @station: Address of the station
+ * @ev: Address of the event
+ *
+ * Queues an event (on the station event queue) for handling by the
+ * station state machine and attempts to process any queued-up events.
+ */
+void llc_station_send_ev(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ spin_lock_bh(&station->ev_q.lock);
+ list_add_tail(&ev->node, &station->ev_q.list);
+ llc_station_service_events(station);
+ spin_unlock_bh(&station->ev_q.lock);
+}
+
+/**
+ * llc_station_send_pdu - queues PDU to send
+ * @station: Address of the station
+ * @skb: Address of the PDU
+ *
+ * Queues a PDU to send to the MAC layer.
+ */
+void llc_station_send_pdu(struct llc_station *station, struct sk_buff *skb)
+{
+ skb_queue_tail(&station->mac_pdu_q, skb);
+ llc_station_send_pdus(station);
+}
+
+/**
+ * llc_station_send_pdus - tries to send queued PDUs
+ * @station: Address of the station
+ *
+ * Tries to send any PDUs queued in the station mac_pdu_q to the MAC
+ * layer.
+ */
+static void llc_station_send_pdus(struct llc_station *station)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&station->mac_pdu_q)) != NULL) {
+ int rc = mac_send_pdu(skb);
+
+ kfree_skb(skb);
+ if (rc)
+ break;
+ }
+}
+
+/**
+ * llc_station_free_ev - frees an event
+ * @station: Address of the station
+ * @event: Address of the event
+ *
+ * Frees an event.
+ */
+static void llc_station_free_ev(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ struct sk_buff *skb = ev->data.pdu.skb;
+
+ if (ev->type == LLC_STATION_EV_TYPE_PDU)
+ kfree_skb(skb);
+ kfree(ev);
+}
+
+/**
+ * llc_station_service_events - service events in the queue
+ * @station: Address of the station
+ *
+ * Get an event from the station event queue (if any); attempt to service
+ * the event; if event serviced, get the next event (if any) on the event
+ * queue; if event not service, re-queue the event on the event queue and
+ * attempt to service the next event; when serviced all events in queue,
+ * finished; if don't transition to different state, just service all
+ * events once; if transition to new state, service all events again.
+ * Caller must hold station->ev_q.lock.
+ */
+static void llc_station_service_events(struct llc_station *station)
+{
+ struct llc_station_state_ev *ev;
+ struct list_head *entry, *tmp;
+
+ list_for_each_safe(entry, tmp, &station->ev_q.list) {
+ ev = list_entry(entry, struct llc_station_state_ev, node);
+ list_del(&ev->node);
+ llc_station_next_state(station, ev);
+ }
+}
+
+/**
+ * llc_station_next_state - processes event and goes to the next state
+ * @station: Address of the station
+ * @ev: Address of the event
+ *
+ * Processes an event, executes any transitions related to that event and
+ * updates the state of the station.
+ */
+static u16 llc_station_next_state(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ u16 rc = 1;
+ struct llc_station_state_trans *trans;
+
+ if (station->state > LLC_NBR_STATION_STATES)
+ goto out;
+ trans = llc_find_station_trans(station, ev);
+ if (trans) {
+ /* got the state to which we next transition; perform the
+ * actions associated with this transition before actually
+ * transitioning to the next state
+ */
+ rc = llc_exec_station_trans_actions(station, trans, ev);
+ if (!rc)
+ /* transition station to next state if all actions
+ * execute successfully; done; wait for next event
+ */
+ station->state = trans->next_state;
+ } else
+ /* event not recognized in current state; re-queue it for
+ * processing again at a later time; return failure
+ */
+ rc = 0;
+out:
+ llc_station_free_ev(station, ev);
+ return rc;
+}
+
+/**
+ * llc_find_station_trans - finds transition for this event
+ * @station: Address of the station
+ * @ev: Address of the event
+ *
+ * Search thru events of the current state of the station until list
+ * exhausted or it's obvious that the event is not valid for the current
+ * state. Returns the address of the transition if cound, %NULL otherwise.
+ */
+static struct llc_station_state_trans *
+ llc_find_station_trans(struct llc_station *station,
+ struct llc_station_state_ev *ev)
+{
+ int i = 0;
+ struct llc_station_state_trans *rc = NULL;
+ struct llc_station_state_trans **next_trans;
+ struct llc_station_state *curr_state =
+ &llc_station_state_table[station->state - 1];
+
+ for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
+ if (!next_trans[i]->ev(station, ev)) {
+ rc = next_trans[i];
+ break;
+ }
+ return rc;
+}
+
+/**
+ * llc_exec_station_trans_actions - executes actions for transition
+ * @station: Address of the station
+ * @trans: Address of the transition
+ * @ev: Address of the event that caused the transition
+ *
+ * Executes actions of a transition of the station state machine. Returns
+ * 0 if all actions complete successfully, nonzero otherwise.
+ */
+static u16 llc_exec_station_trans_actions(struct llc_station *station,
+ struct llc_station_state_trans *trans,
+ struct llc_station_state_ev *ev)
+{
+ u16 rc = 0;
+ llc_station_action_t *next_action;
+
+ for (next_action = trans->ev_actions;
+ next_action && *next_action; next_action++)
+ if ((*next_action)(station, ev))
+ rc = 1;
+ return rc;
+}
+
+/**
+ * llc_alloc_frame - allocates sk_buff for frame
+ *
+ * Allocates an sk_buff for frame and initializes sk_buff fields.
+ * Returns allocated skb or %NULL when out of memory.
+ */
+struct sk_buff *llc_alloc_frame(void)
+{
+ struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
+
+ if (skb) {
+ skb_reserve(skb, 50);
+ skb->nh.raw = skb->h.raw = skb->data;
+ skb->protocol = htons(ETH_P_802_2);
+ skb->dev = dev_base->next;
+ skb->mac.raw = skb->head;
+ }
+ return skb;
+}
+
+static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
+{
+ struct llc_opt *llc;
+ struct list_head *sap_entry, *llc_entry;
+ off_t begin = 0, pos = 0;
+ int len = 0;
+
+ spin_lock_bh(&llc_main_station.sap_list.lock);
+ list_for_each(sap_entry, &llc_main_station.sap_list.list) {
+ struct llc_sap *sap = list_entry(sap_entry, struct llc_sap,
+ node);
+
+ len += sprintf(bf + len, "lsap=%d\n", sap->laddr.lsap);
+ spin_lock_bh(&sap->sk_list.lock);
+ if (list_empty(&sap->sk_list.list)) {
+ len += sprintf(bf + len, "no connections\n");
+ goto unlock;
+ }
+ len += sprintf(bf + len,
+ "connection list:\nstate retr txwin rxwin\n");
+ list_for_each(llc_entry, &sap->sk_list.list) {
+ llc = list_entry(llc_entry, struct llc_opt, node);
+ len += sprintf(bf + len, " %-5d%-5d%-6d%-5d\n",
+ llc->state, llc->retry_count, llc->k,
+ llc->rw);
+ }
+unlock:
+ spin_unlock_bh(&sap->sk_list.lock);
+ pos = begin + len;
+ if (pos < offset) {
+ len = 0; /* Keep dumping into the buffer start */
+ begin = pos;
+ }
+ if (pos > offset + length) /* We have dumped enough */
+ break;
+ }
+ spin_unlock_bh(&llc_main_station.sap_list.lock);
+
+ /* The data in question runs from begin to begin + len */
+ *start = bf + (offset - begin); /* Start of wanted data */
+ len -= (offset - begin); /* Remove unwanted header data from length */
+ return len;
+}
+
+static char llc_banner[] __initdata =
+ KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n"
+ KERN_INFO "NET4.0 IEEE 802.2 extended support\n";
+static char llc_error_msg[] __initdata =
+ KERN_ERR "LLC install NOT successful.\n";
+
+static int __init llc_init(void)
+{
+ u16 rc = 0;
+ struct llc_station_state_ev *ev;
+
+ printk(llc_banner);
+ INIT_LIST_HEAD(&llc_main_station.ev_q.list);
+ spin_lock_init(&llc_main_station.ev_q.lock);
+ INIT_LIST_HEAD(&llc_main_station.sap_list.list);
+ spin_lock_init(&llc_main_station.sap_list.lock);
+ skb_queue_head_init(&llc_main_station.mac_pdu_q);
+ ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+ if (!ev)
+ goto err;
+ memset(ev, 0, sizeof(*ev));
+ if(dev_base->next)
+ memcpy(llc_main_station.mac_sa, dev_base->next->dev_addr, ETH_ALEN);
+ else
+ memset(llc_main_station.mac_sa, 0, ETH_ALEN);
+ llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
+ /* initialize the station component */
+ llc_register_sap(0, mac_indicate);
+ llc_main_station.maximum_retry = 1;
+ llc_main_station.state = LLC_STATION_STATE_DOWN;
+ ev->type = LLC_STATION_EV_TYPE_SIMPLE;
+ ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
+ rc = llc_station_next_state(&llc_main_station, ev);
+ llc_build_offset_table();
+ llc_ind_prim.data = &llc_ind_data_prim;
+ llc_cfm_prim.data = &llc_cfm_data_prim;
+ proc_net_create("802.2", 0, llc_proc_get_info);
+ llc_ui_init();
+out:
+ return rc;
+err:
+ printk(llc_error_msg);
+ rc = 1;
+ goto out;
+}
+
+static void __exit llc_exit(void)
+{
+ llc_ui_exit();
+ llc_unregister_sap(0);
+ proc_net_remove("802.2");
+}
+
+module_init(llc_init);
+module_exit(llc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001");
+MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support");
diff --git a/net/llc/llc_pdu.c b/net/llc/llc_pdu.c
new file mode 100644
index 000000000000..73d0b4885722
--- /dev/null
+++ b/net/llc/llc_pdu.c
@@ -0,0 +1,654 @@
+/*
+ * llc_pdu.c - access to PDU internals
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <linux/if_tr.h>
+#include <net/llc_pdu.h>
+#include <net/llc_if.h>
+#include <net/llc_mac.h>
+#include <net/llc_main.h>
+
+static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
+static int llc_get_llc_hdr_length(u8 pdu_type);
+static u8 llc_pdu_get_pf_bit(llc_pdu_sn_t *pdu);
+
+/**
+ * llc_pdu_header_init - initializes pdu header
+ * @skb: input skb that header must be set into it.
+ * @pdu_type: type of PDU (U, I or S).
+ * @ssap: source sap.
+ * @dsap: destination sap.
+ * @cr: command/response bit (0 or 1).
+ *
+ * This function sets DSAP, SSAP and command/Response bit in LLC header.
+ */
+void llc_pdu_header_init(struct sk_buff *skb, u8 pdu_type, u8 ssap,
+ u8 dsap, u8 cr)
+{
+ llc_pdu_un_t *p;
+
+ skb->nh.raw = skb_push(skb, llc_get_llc_hdr_length(pdu_type));
+ p = (llc_pdu_un_t *)skb->nh.raw;
+ p->dsap = dsap;
+ p->ssap = ssap;
+ p->ssap |= cr;
+}
+
+void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
+{
+ ((llc_pdu_un_t *)skb->nh.raw)->ssap |= pdu_type;
+}
+
+/**
+ * pdu_set_pf_bit - sets poll/final bit in LLC header
+ * @pdu_frame: input frame that p/f bit must be set into it.
+ * @bit_value: poll/final bit (0 or 1).
+ *
+ * This function sets poll/final bit in LLC header (based on type of PDU).
+ * in I or S pdus, p/f bit is right bit of fourth byte in header. in U
+ * pdus p/f bit is fifth bit of third byte.
+ */
+void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
+{
+ u8 pdu_type;
+
+ if (llc_pdu_decode_pdu_type(skb, &pdu_type))
+ goto out;
+ switch (pdu_type) {
+ case LLC_PDU_TYPE_I:
+ case LLC_PDU_TYPE_S:
+ ((llc_pdu_sn_t *)skb->nh.raw)->ctrl_2 =
+ (((llc_pdu_sn_t *)skb->nh.raw)->ctrl_2 & 0xFE) |
+ bit_value;
+ break;
+ case LLC_PDU_TYPE_U:
+ ((llc_pdu_un_t *)skb->nh.raw)->ctrl_1 |=
+ (((llc_pdu_un_t *)skb->nh.raw)->ctrl_1 & 0xEF) |
+ (bit_value << 4);
+ break;
+ }
+out:;
+}
+
+/**
+ * llc_pdu_decode_pf_bit - extracs poll/final bit from LLC header
+ * @skb: input skb that p/f bit must be extracted from it
+ * @pf_bit: poll/final bit (0 or 1)
+ *
+ * This function extracts poll/final bit from LLC header (based on type of
+ * PDU). In I or S pdus, p/f bit is right bit of fourth byte in header. In
+ * U pdus p/f bit is fifth bit of third byte.
+ */
+int llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
+{
+ u8 pdu_type;
+ int rc = llc_pdu_decode_pdu_type(skb, &pdu_type);
+
+ if (rc)
+ goto out;
+ switch (pdu_type) {
+ case LLC_PDU_TYPE_I:
+ case LLC_PDU_TYPE_S:
+ *pf_bit = ((llc_pdu_sn_t *)skb->nh.raw)->ctrl_2 &
+ LLC_S_PF_BIT_MASK;
+ break;
+ case LLC_PDU_TYPE_U:
+ *pf_bit = (((llc_pdu_un_t *)skb->nh.raw)->ctrl_1 &
+ LLC_U_PF_BIT_MASK) >> 4;
+ break;
+ }
+out:
+ return 0;
+}
+
+/**
+ * llc_pdu_decode_cr_bit - extracs command response bit from LLC header
+ * @skb: input skb that c/r bit must be extracted from it.
+ * @cr_bit: command/response bit (0 or 1).
+ *
+ * This function extracts command/response bit from LLC header. this bit
+ * is right bit of source SAP.
+ */
+int llc_pdu_decode_cr_bit(struct sk_buff *skb, u8 *cr_bit)
+{
+ *cr_bit = ((llc_pdu_un_t *)skb->nh.raw)->ssap & LLC_PDU_CMD_RSP_MASK;
+ return 0;
+}
+
+/**
+ * llc_pdu_decode_sa - extracs source address (MAC) of input frame
+ * @skb: input skb that source address must be extracted from it.
+ * @sa: pointer to source address (6 byte array).
+ *
+ * This function extracts source address(MAC) of input frame.
+ */
+int llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
+{
+ if (skb->protocol == ntohs(ETH_P_802_2))
+ memcpy(sa, ((struct ethhdr *)skb->mac.raw)->h_source, ETH_ALEN);
+ else if (skb->protocol == ntohs(ETH_P_TR_802_2))
+ memcpy(sa, ((struct trh_hdr *)skb->mac.raw)->saddr, ETH_ALEN);
+ return 0;
+}
+
+/**
+ * llc_pdu_decode_da - extracts dest address of input frame
+ * @skb: input skb that destination address must be extracted from it
+ * @sa: pointer to destination address (6 byte array).
+ *
+ * This function extracts destination address(MAC) of input frame.
+ */
+int llc_pdu_decode_da(struct sk_buff *skb, u8 *da)
+{
+ if (skb->protocol == ntohs(ETH_P_802_2))
+ memcpy(da, ((struct ethhdr *)skb->mac.raw)->h_dest, ETH_ALEN);
+ else if (skb->protocol == ntohs(ETH_P_TR_802_2))
+ memcpy(da, ((struct trh_hdr *)skb->mac.raw)->daddr, ETH_ALEN);
+ return 0;
+}
+
+/**
+ * llc_pdu_decode_dsap - extracts dest SAP of input frame
+ * @skb: input skb that destination SAP must be extracted from it.
+ * @dsap: destination SAP (output argument).
+ *
+ * This function extracts destination SAP of input frame. right bit of
+ * DSAP designates individual/group SAP.
+ */
+int llc_pdu_decode_dsap(struct sk_buff *skb, u8 *dsap)
+{
+ *dsap = ((llc_pdu_un_t *)skb->nh.raw)->dsap & 0xFE;
+ return 0;
+}
+
+/**
+ * llc_pdu_decode_ssap - extracts source SAP of input frame
+ * @skb: input skb that source SAP must be extracted from it.
+ * @ssap: source SAP (output argument).
+ *
+ * This function extracts source SAP of input frame. right bit of SSAP is
+ * command/response bit.
+ */
+int llc_pdu_decode_ssap(struct sk_buff *skb, u8 *ssap)
+{
+ *ssap = ((llc_pdu_un_t *)skb->nh.raw)->ssap & 0xFE;
+ return 0;
+}
+
+/**
+ * llc_pdu_init_as_ui_cmd - sets LLC header as UI PDU
+ * @skb: input skb that header must be set into it.
+ *
+ * This function sets third byte of LLC header as a UI PDU.
+ */
+int llc_pdu_init_as_ui_cmd(struct sk_buff *skb)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_UI;
+ return 0;
+}
+
+/**
+ * llc_pdu_init_as_xid_cmd - sets bytes 3, 4 & 5 of LLC header as XID
+ * @skb: input skb that header must be set into it.
+ *
+ * This function sets third,fourth,fifth and sixth bytes of LLC header as
+ * a XID PDU.
+ */
+int llc_pdu_init_as_xid_cmd(struct sk_buff *skb, u8 svcs_supported,
+ u8 rx_window)
+{
+ llc_xid_info_t *xid_info;
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_XID;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+ xid_info = (llc_xid_info_t *)(((u8 *)&pdu->ctrl_1) + 1);
+ xid_info->fmt_id = LLC_XID_FMT_ID; /* 0x81 */
+ xid_info->type = svcs_supported;
+ xid_info->rw = rx_window << 1; /* size of recieve window */
+ skb_put(skb, 3);
+ return 0;
+}
+
+/**
+ * llc_pdu_init_as_test_cmd - sets PDU as TEST
+ * @skb - Address of the skb to build
+ *
+ * Sets a PDU as TEST
+ */
+int llc_pdu_init_as_test_cmd(struct sk_buff *skb)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+ return 0;
+}
+
+/**
+ * llc_pdu_init_as_disc_cmd - Builds DISC PDU
+ * @skb: Address of the skb to build
+ * @p_bit: The P bit to set in the PDU
+ *
+ * Builds a pdu frame as a DISC command.
+ */
+int llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC;
+ pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
+ return 0;
+}
+
+/**
+ * pdu_init_as_i_cmd - builds I pdu
+ * @skb: Address of the skb to build
+ * @p_bit: The P bit to set in the PDU
+ * @ns: The sequence number of the data PDU
+ * @nr: The seq. number of the expected I PDU from the remote
+ *
+ * Builds a pdu frame as an I command.
+ */
+int llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_I;
+ pdu->ctrl_2 = 0;
+ pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); /* p/f bit */
+ pdu->ctrl_1 |= (ns << 1) & 0xFE; /* set N(S) in bits 2..8 */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_rej_cmd - builds REJ PDU
+ * @skb: Address of the skb to build
+ * @p_bit: The P bit to set in the PDU
+ * @nr: The seq. number of the expected I PDU from the remote
+ *
+ * Builds a pdu frame as a REJ command.
+ */
+int llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_S;
+ pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ;
+ pdu->ctrl_2 = 0;
+ pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
+ pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_rnr_cmd - builds RNR pdu
+ * @skb: Address of the skb to build
+ * @p_bit: The P bit to set in the PDU
+ * @nr: The seq. number of the expected I PDU from the remote
+ *
+ * Builds a pdu frame as an RNR command.
+ */
+int llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_S;
+ pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR;
+ pdu->ctrl_2 = 0;
+ pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
+ pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_rr_cmd - Builds RR pdu
+ * @skb: Address of the skb to build
+ * @p_bit: The P bit to set in the PDU
+ * @nr: The seq. number of the expected I PDU from the remote
+ *
+ * Builds a pdu frame as an RR command.
+ */
+int llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_S;
+ pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
+ pdu->ctrl_2 = p_bit & LLC_S_PF_BIT_MASK;
+ pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_sabme_cmd - builds SABME pdu
+ * @skb: Address of the skb to build
+ * @p_bit: The P bit to set in the PDU
+ *
+ * Builds a pdu frame as an SABME command.
+ */
+int llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME;
+ pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
+ return 0;
+}
+
+/**
+ * pdu_init_as_dm_rsp - builds DM response pdu
+ * @skb: Address of the skb to build
+ * @f_bit: The F bit to set in the PDU
+ *
+ * Builds a pdu frame as a DM response.
+ */
+int llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_2_PDU_RSP_DM;
+ pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
+ return 0;
+}
+
+/**
+ * pdu_init_as_xid_rsp - builds XID response PDU
+ * @skb: Address of the skb to build
+ * @svcs_supported: The class of the LLC (I or II)
+ * @rx_window: The size of the receive window of the LLC
+ *
+ * Builds a pdu frame as an XID response.
+ */
+int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported,
+ u8 rx_window)
+{
+ llc_xid_info_t *xid_info;
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_XID;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+
+ xid_info = (llc_xid_info_t *)(((u8 *)&pdu->ctrl_1) + 1);
+ xid_info->fmt_id = LLC_XID_FMT_ID;
+ xid_info->type = svcs_supported;
+ xid_info->rw = rx_window << 1;
+ skb_put(skb, 3);
+ return 0;
+}
+
+/**
+ * pdu_init_as_test_rsp - build TEST response PDU
+ * @skb: Address of the skb to build
+ * @ev_skb: The received TEST command PDU frame
+ *
+ * Builds a pdu frame as a TEST response.
+ */
+int llc_pdu_init_as_test_rsp(struct sk_buff *skb, struct sk_buff *ev_skb)
+{
+ int dsize;
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_1_PDU_CMD_TEST;
+ pdu->ctrl_1 |= LLC_U_PF_BIT_MASK;
+ if (ev_skb->protocol == ntohs(ETH_P_802_2)) {
+ dsize = ntohs(((struct ethhdr *)ev_skb->mac.raw)->h_proto) - 3;
+ memcpy(((u8 *)skb->nh.raw) + 3,
+ ((u8 *)ev_skb->nh.raw) + 3, dsize);
+ skb_put(skb, dsize);
+ }
+ return 0;
+}
+
+/**
+ * pdu_init_as_frmr_rsp - builds FRMR response PDU
+ * @pdu_frame: Address of the frame to build
+ * @prev_pdu: The rejected PDU frame
+ * @f_bit: The F bit to set in the PDU
+ * @vs: tx state vari value for the data link conn at the rejecting LLC
+ * @vr: rx state var value for the data link conn at the rejecting LLC
+ * @vzyxw: completely described in the IEEE Std 802.2 document (Pg 55)
+ *
+ * Builds a pdu frame as a FRMR response.
+ */
+int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, llc_pdu_sn_t *prev_pdu,
+ u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
+{
+ llc_frmr_info_t *frmr_info;
+ u8 prev_pf = 0;
+ u8 *ctrl;
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR;
+ pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
+
+ frmr_info = (llc_frmr_info_t *)&pdu->ctrl_2;
+ ctrl = (u8 *)&prev_pdu->ctrl_1;
+ FRMR_INFO_SET_REJ_CNTRL(frmr_info,ctrl);
+ FRMR_INFO_SET_Vs(frmr_info, vs);
+ FRMR_INFO_SET_Vr(frmr_info, vr);
+ prev_pf = llc_pdu_get_pf_bit(prev_pdu);
+ FRMR_INFO_SET_C_R_BIT(frmr_info, prev_pf);
+ FRMR_INFO_SET_INVALID_PDU_CTRL_IND(frmr_info, vzyxw);
+ FRMR_INFO_SET_INVALID_PDU_INFO_IND(frmr_info, vzyxw);
+ FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw);
+ FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw);
+ FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw);
+ skb_put(skb, 5);
+ return 0;
+}
+
+/**
+ * pdu_init_as_rr_rsp - builds RR response pdu
+ * @skb: Address of the skb to build
+ * @f_bit: The F bit to set in the PDU
+ * @nr: The seq. number of the expected data PDU from the remote
+ *
+ * Builds a pdu frame as an RR response.
+ */
+int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_S;
+ pdu->ctrl_1 |= LLC_2_PDU_RSP_RR;
+ pdu->ctrl_2 = 0;
+ pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
+ pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_rej_rsp - builds REJ response pdu
+ * @skb: Address of the skb to build
+ * @f_bit: The F bit to set in the PDU
+ * @nr: The seq. number of the expected data PDU from the remote
+ *
+ * Builds a pdu frame as a REJ response.
+ */
+int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_S;
+ pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ;
+ pdu->ctrl_2 = 0;
+ pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
+ pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_rnr_rsp - builds RNR response pdu
+ * @pdu_frame: Address of the frame to build
+ * @f_bit: The F bit to set in the PDU
+ * @nr: The seq. number of the expected data PDU from the remote
+ *
+ * Builds a pdu frame as an RNR response.
+ */
+int llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
+{
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_S;
+ pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
+ pdu->ctrl_2 = 0;
+ pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
+ pdu->ctrl_1 &= 0x0F; /* setting bits 5..8 to zero(reserved) */
+ pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
+ return 0;
+}
+
+/**
+ * pdu_init_as_ua_rsp - builds UA response pdu
+ * @skb: Address of the frame to build
+ * @f_bit: The F bit to set in the PDU
+ *
+ * Builds a pdu frame as a UA response.
+ */
+int llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ pdu->ctrl_1 = LLC_PDU_TYPE_U;
+ pdu->ctrl_1 |= LLC_2_PDU_RSP_UA;
+ pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
+ return 0;
+}
+
+/**
+ * llc_pdu_decode_pdu_type - designates PDU type
+ * @skb: input skb that type of it must be designated.
+ * @type: type of PDU (output argument).
+ *
+ * This function designates type of PDU (I,S or U).
+ */
+static int llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)skb->nh.raw;
+
+ if (pdu->ctrl_1 & 1) {
+ if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
+ *type = LLC_PDU_TYPE_U;
+ else
+ *type = LLC_PDU_TYPE_S;
+ } else
+ *type = LLC_PDU_TYPE_I;
+ return 0;
+}
+
+/**
+ * llc_decode_pdu_type - designates component LLC must handle for PDU
+ * @skb: input skb
+ * @dest: destination component
+ *
+ * This function designates which component of LLC must handle this PDU.
+ */
+int llc_decode_pdu_type(struct sk_buff *skb, u8 *dest)
+{
+ u8 type = LLC_DEST_CONN; /* I-PDU or S-PDU type */
+ llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
+
+ if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) != LLC_PDU_TYPE_U)
+ goto out;
+ switch (LLC_U_PDU_CMD(pdu)) {
+ case LLC_1_PDU_CMD_XID:
+ case LLC_1_PDU_CMD_UI:
+ case LLC_1_PDU_CMD_TEST:
+ type = LLC_DEST_SAP;
+ break;
+ case LLC_2_PDU_CMD_SABME:
+ case LLC_2_PDU_CMD_DISC:
+ case LLC_2_PDU_RSP_UA:
+ case LLC_2_PDU_RSP_DM:
+ case LLC_2_PDU_RSP_FRMR:
+ break;
+ default:
+ type = LLC_DEST_INVALID;
+ break;
+ }
+out:
+ *dest = type;
+ return 0;
+}
+
+/**
+ * get_llc_hdr_len - designates LLC header length
+ * @pdu_type: type of PDU.
+ *
+ * This function designates LLC header length of PDU. header length for I
+ * and S PDU is 4 and for U is 3 bytes. Returns the length of header.
+ */
+static int llc_get_llc_hdr_length(u8 pdu_type)
+{
+ int rtn_val = 0;
+
+ switch (pdu_type) {
+ case LLC_PDU_TYPE_I:
+ case LLC_PDU_TYPE_S:
+ rtn_val = 4;
+ break;
+ case LLC_PDU_TYPE_U:
+ rtn_val = 3;
+ break;
+ }
+ return rtn_val;
+}
+
+/**
+ * llc_pdu_get_pf_bit - extracts p/f bit of input PDU
+ * @pdu: pointer to LLC header.
+ *
+ * This function extracts p/f bit of input PDU. at first examines type of
+ * PDU and then extracts p/f bit. Returns the p/f bit.
+ */
+static u8 llc_pdu_get_pf_bit(llc_pdu_sn_t *pdu)
+{
+ u8 pdu_type;
+ u8 pf_bit = 0;
+
+ if (pdu->ctrl_1 & 1) {
+ if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
+ pdu_type = LLC_PDU_TYPE_U;
+ else
+ pdu_type = LLC_PDU_TYPE_S;
+ } else
+ pdu_type = LLC_PDU_TYPE_I;
+ switch (pdu_type) {
+ case LLC_PDU_TYPE_I:
+ case LLC_PDU_TYPE_S:
+ pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
+ break;
+ case LLC_PDU_TYPE_U:
+ pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
+ break;
+ }
+ return pf_bit;
+}
diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c
new file mode 100644
index 000000000000..b5d0f4d2fd04
--- /dev/null
+++ b/net/llc/llc_s_ac.c
@@ -0,0 +1,227 @@
+/*
+ * llc_s_ac.c - actions performed during sap state transition.
+ *
+ * Description :
+ * Functions in this module are implementation of sap component actions.
+ * Details of actions can be found in IEEE-802.2 standard document.
+ * All functions have one sap and one event as input argument. All of
+ * them return 0 On success and 1 otherwise.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_main.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_pdu.h>
+#include <net/llc_mac.h>
+
+/**
+ * llc_sap_action_unit_data_ind - forward UI PDU to network layer
+ * @sap: SAP
+ * @ev: the event to forward
+ *
+ * Received a UI PDU from MAC layer; forward to network layer as a
+ * UNITDATA INDICATION; verify our event is the kind we expect
+ */
+int llc_sap_action_unitdata_ind(struct llc_sap *sap,
+ struct llc_sap_state_ev *ev)
+{
+ llc_sap_rtn_pdu(sap, ev->data.pdu.skb, ev);
+ return 0;
+}
+
+/**
+ * llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Sends a UI PDU to the MAC layer in response to a UNITDATA REQUEST
+ * primitive from the network layer. Verifies event is a primitive type of
+ * event. Verify the primitive is a UNITDATA REQUEST.
+ */
+int llc_sap_action_send_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ struct llc_prim_if_block *prim = ev->data.prim.data;
+ struct llc_prim_unit_data *prim_data = &prim->data->udata;
+ struct sk_buff *skb = prim->data->udata.skb;
+ int rc;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap,
+ prim_data->daddr.lsap, LLC_PDU_CMD);
+ rc = llc_pdu_init_as_ui_cmd(skb);
+ if (rc)
+ goto out;
+ rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac);
+ if (!rc)
+ llc_sap_send_pdu(sap, skb);
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_action_send_xid_c - send XID PDU as response to XID REQ
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Send a XID command PDU to MAC layer in response to a XID REQUEST
+ * primitive from the network layer. Verify event is a primitive type
+ * event. Verify the primitive is a XID REQUEST.
+ */
+int llc_sap_action_send_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ struct llc_prim_if_block *prim = ev->data.prim.data;
+ struct llc_prim_xid *prim_data = &prim->data->xid;
+ struct sk_buff *skb = prim_data->skb;
+ int rc;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap,
+ prim_data->daddr.lsap, LLC_PDU_CMD);
+ rc = 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);
+ if (!rc)
+ llc_sap_send_pdu(sap, skb);
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_action_send_xid_r - send XID PDU resp to MAC for received XID
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Send XID response PDU to MAC in response to an earlier received XID
+ * command PDU. Verify event is a PDU type event
+ */
+int llc_sap_action_send_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff *ev_skb = ev->data.pdu.skb;
+ struct sk_buff *skb;
+
+ llc_pdu_decode_sa(ev_skb, mac_da);
+ llc_pdu_decode_da(ev_skb, mac_sa);
+ llc_pdu_decode_ssap(ev_skb, &dsap);
+ skb = llc_alloc_frame();
+ if (!skb)
+ goto out;
+ skb->dev = ev_skb->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
+ LLC_PDU_RSP);
+ rc = llc_pdu_init_as_xid_rsp(skb, LLC_XID_NULL_CLASS_2, 0);
+ if (rc)
+ goto out;
+ rc = lan_hdrs_init(skb, mac_sa, mac_da);
+ if (!rc)
+ llc_sap_send_pdu(sap, skb);
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Send a TEST command PDU to the MAC layer in response to a TEST REQUEST
+ * primitive from the network layer. Verify event is a primitive type
+ * event; verify the primitive is a TEST REQUEST.
+ */
+int llc_sap_action_send_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ struct llc_prim_if_block *prim = ev->data.prim.data;
+ struct llc_prim_test *prim_data = &prim->data->test;
+ struct sk_buff *skb = prim_data->skb;
+ int rc;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, prim_data->saddr.lsap,
+ prim_data->daddr.lsap, LLC_PDU_CMD);
+ rc = llc_pdu_init_as_test_cmd(skb);
+ if (rc)
+ goto out;
+ rc = lan_hdrs_init(skb, prim_data->saddr.mac, prim_data->daddr.mac);
+ if (!rc)
+ llc_sap_send_pdu(sap, skb);
+out:
+ return rc;
+}
+
+int llc_sap_action_send_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff *ev_skb = ev->data.pdu.skb;
+ struct sk_buff *skb;
+
+ llc_pdu_decode_sa(ev_skb, mac_da);
+ llc_pdu_decode_da(ev_skb, mac_sa);
+ llc_pdu_decode_ssap(ev_skb, &dsap);
+ skb = llc_alloc_frame();
+ if (!skb)
+ goto out;
+ skb->dev = ev_skb->dev;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
+ LLC_PDU_RSP);
+ rc = llc_pdu_init_as_test_rsp(skb, ev_skb);
+ if (rc)
+ goto out;
+ rc = lan_hdrs_init(skb, mac_sa, mac_da);
+ if (!rc)
+ llc_sap_send_pdu(sap, skb);
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_action_report_status - report data link status to layer mgmt
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Report data link status to layer management. Verify our event is the
+ * kind we expect.
+ */
+int llc_sap_action_report_status(struct llc_sap *sap,
+ struct llc_sap_state_ev *ev)
+{
+ return 0;
+}
+
+/**
+ * llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Send a XID response PDU to the network layer via a XID INDICATION
+ * primitive.
+ */
+int llc_sap_action_xid_ind(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_sap_rtn_pdu(sap, ev->data.pdu.skb, ev);
+ return 0;
+}
+
+/**
+ * llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND
+ * @sap: SAP
+ * @ev: the event to send
+ *
+ * Send a TEST response PDU to the network layer via a TEST INDICATION
+ * primitive. Verify our event is a PDU type event.
+ */
+int llc_sap_action_test_ind(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_sap_rtn_pdu(sap, ev->data.pdu.skb, ev);
+ return 0;
+}
diff --git a/net/llc/llc_s_ev.c b/net/llc/llc_s_ev.c
new file mode 100644
index 000000000000..101e79b6e63b
--- /dev/null
+++ b/net/llc/llc_s_ev.c
@@ -0,0 +1,101 @@
+/*
+ * llc_s_ev.c - Defines SAP component events
+ *
+ * The followed event functions are SAP component events which are described
+ * in 802.2 LLC protocol standard document.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/socket.h>
+#include <net/sock.h>
+#include <net/llc_if.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_pdu.h>
+
+int llc_sap_ev_activation_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
+ ev->data.a.ev == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1;
+}
+
+int llc_sap_ev_rx_ui(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
+ !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_UI ? 0 : 1;
+}
+
+int llc_sap_ev_unitdata_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ return ev->type == LLC_SAP_EV_TYPE_PRIM &&
+ ev->data.prim.prim == LLC_DATAUNIT_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+
+}
+
+int llc_sap_ev_xid_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ return ev->type == LLC_SAP_EV_TYPE_PRIM &&
+ ev->data.prim.prim == LLC_XID_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
+ !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1;
+}
+
+int llc_sap_ev_rx_xid_r(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) &&
+ !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_XID ? 0 : 1;
+}
+
+int llc_sap_ev_test_req(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ return ev->type == LLC_SAP_EV_TYPE_PRIM &&
+ ev->data.prim.prim == LLC_TEST_PRIM &&
+ ev->data.prim.type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_CMD(pdu) &&
+ !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
+}
+
+int llc_sap_ev_rx_test_r(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ return ev->type == LLC_SAP_EV_TYPE_PDU && !LLC_PDU_IS_RSP(pdu) &&
+ !LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_1_PDU_CMD_TEST ? 0 : 1;
+}
+
+int llc_sap_ev_deactivation_req(struct llc_sap *sap,
+ struct llc_sap_state_ev *ev)
+{
+ return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
+ ev->data.a.ev == LLC_SAP_EV_DEACTIVATION_REQ ? 0 : 1;
+}
diff --git a/net/llc/llc_s_st.c b/net/llc/llc_s_st.c
new file mode 100644
index 000000000000..1c93ac638802
--- /dev/null
+++ b/net/llc/llc_s_st.c
@@ -0,0 +1,183 @@
+/*
+ * llc_s_st.c - Defines SAP component state machine transitions.
+ *
+ * The followed transitions are SAP component state machine transitions
+ * which are described in 802.2 LLC protocol standard document.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/types.h>
+#include <net/llc_if.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_s_ac.h>
+#include <net/llc_s_st.h>
+
+/* dummy last-transition indicator; common to all state transition groups
+ * last entry for this state
+ * all members are zeros, .bss zeroes it
+ */
+static struct llc_sap_state_trans llc_sap_state_trans_n;
+
+/* state LLC_SAP_STATE_INACTIVE transition for
+ * LLC_SAP_EV_ACTIVATION_REQ event
+ */
+static llc_sap_action_t llc_sap_inactive_state_actions_1[] = {
+ [0] = llc_sap_action_report_status,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_inactive_state_trans_1 = {
+ .ev = llc_sap_ev_activation_req,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_inactive_state_actions_1,
+};
+
+/* array of pointers; one to each transition */
+static struct llc_sap_state_trans *llc_sap_inactive_state_transitions[] = {
+ [0] = &llc_sap_inactive_state_trans_1,
+ [1] = &llc_sap_state_trans_n,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_UI event */
+static llc_sap_action_t llc_sap_active_state_actions_1[] = {
+ [0] = llc_sap_action_unitdata_ind,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_1 = {
+ .ev = llc_sap_ev_rx_ui,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_1,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_UNITDATA_REQ event */
+static llc_sap_action_t llc_sap_active_state_actions_2[] = {
+ [0] = llc_sap_action_send_ui,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_2 = {
+ .ev = llc_sap_ev_unitdata_req,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_2,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_XID_REQ event */
+static llc_sap_action_t llc_sap_active_state_actions_3[] = {
+ [0] = llc_sap_action_send_xid_c,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_3 = {
+ .ev = llc_sap_ev_xid_req,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_3,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_XID_C event */
+static llc_sap_action_t llc_sap_active_state_actions_4[] = {
+ [0] = llc_sap_action_send_xid_r,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_4 = {
+ .ev = llc_sap_ev_rx_xid_c,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_4,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_XID_R event */
+static llc_sap_action_t llc_sap_active_state_actions_5[] = {
+ [0] = llc_sap_action_xid_ind,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_5 = {
+ .ev = llc_sap_ev_rx_xid_r,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_5,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_TEST_REQ event */
+static llc_sap_action_t llc_sap_active_state_actions_6[] = {
+ [0] = llc_sap_action_send_test_c,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_6 = {
+ .ev = llc_sap_ev_test_req,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_6,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_TEST_C event */
+static llc_sap_action_t llc_sap_active_state_actions_7[] = {
+ [0] = llc_sap_action_send_test_r,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_7 = {
+ .ev = llc_sap_ev_rx_test_c,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_7
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for LLC_SAP_EV_RX_TEST_R event */
+static llc_sap_action_t llc_sap_active_state_actions_8[] = {
+ [0] = llc_sap_action_test_ind,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_8 = {
+ .ev = llc_sap_ev_rx_test_r,
+ .next_state = LLC_SAP_STATE_ACTIVE,
+ .ev_actions = llc_sap_active_state_actions_8,
+};
+
+/* state LLC_SAP_STATE_ACTIVE transition for
+ * LLC_SAP_EV_DEACTIVATION_REQ event
+ */
+static llc_sap_action_t llc_sap_active_state_actions_9[] = {
+ [0] = llc_sap_action_report_status,
+ [1] = NULL,
+};
+
+static struct llc_sap_state_trans llc_sap_active_state_trans_9 = {
+ .ev = llc_sap_ev_deactivation_req,
+ .next_state = LLC_SAP_STATE_INACTIVE,
+ .ev_actions = llc_sap_active_state_actions_9
+};
+
+/* array of pointers; one to each transition */
+static struct llc_sap_state_trans *llc_sap_active_state_transitions[] = {
+ [0] = &llc_sap_active_state_trans_2,
+ [1] = &llc_sap_active_state_trans_1,
+ [2] = &llc_sap_active_state_trans_3,
+ [3] = &llc_sap_active_state_trans_4,
+ [4] = &llc_sap_active_state_trans_5,
+ [5] = &llc_sap_active_state_trans_6,
+ [6] = &llc_sap_active_state_trans_7,
+ [7] = &llc_sap_active_state_trans_8,
+ [8] = &llc_sap_active_state_trans_9,
+ [9] = &llc_sap_state_trans_n,
+};
+
+/* SAP state transition table */
+struct llc_sap_state llc_sap_state_table[] = {
+ {
+ curr_state: LLC_SAP_STATE_INACTIVE,
+ transitions: llc_sap_inactive_state_transitions,
+ },
+ {
+ curr_state: LLC_SAP_STATE_ACTIVE,
+ transitions: llc_sap_active_state_transitions,
+ },
+};
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
new file mode 100644
index 000000000000..bedc49123d7d
--- /dev/null
+++ b/net/llc/llc_sap.c
@@ -0,0 +1,262 @@
+/*
+ * llc_sap.c - driver routines for SAP component.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/skbuff.h>
+#include <net/llc_conn.h>
+#include <net/llc_sap.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_s_ac.h>
+#include <net/llc_s_st.h>
+#include <net/sock.h>
+#include <net/llc_main.h>
+#include <net/llc_mac.h>
+#include <net/llc_pdu.h>
+#include <linux/if_tr.h>
+
+static void llc_sap_free_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev);
+static int llc_sap_next_state(struct llc_sap *sap, struct llc_sap_state_ev *ev);
+static int llc_exec_sap_trans_actions(struct llc_sap *sap,
+ struct llc_sap_state_trans *trans,
+ struct llc_sap_state_ev *ev);
+static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
+ struct llc_sap_state_ev *ev);
+
+/**
+ * llc_sap_assign_sock - adds a connection to a SAP
+ * @sap: pointer to SAP.
+ * @conn: pointer to connection.
+ *
+ * This function adds a connection to connection_list of a SAP.
+ */
+void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
+{
+ spin_lock_bh(&sap->sk_list.lock);
+ llc_sk(sk)->sap = sap;
+ list_add_tail(&llc_sk(sk)->node, &sap->sk_list.list);
+ sock_hold(sk);
+ spin_unlock_bh(&sap->sk_list.lock);
+}
+
+/**
+ * llc_sap_unassign_sock - removes a connection from SAP
+ * @sap: SAP
+ * @sk: pointer to connection
+ *
+ * This function removes a connection from connection_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)
+{
+ spin_lock_bh(&sap->sk_list.lock);
+ list_del(&llc_sk(sk)->node);
+ sock_put(sk);
+ spin_unlock_bh(&sap->sk_list.lock);
+}
+
+/**
+ * llc_sap_alloc_ev - allocates sap event
+ * @sap: pointer to SAP
+ * @ev: allocated event (output argument)
+ *
+ * Returns the allocated sap event or %NULL when out of memory.
+ */
+struct llc_sap_state_ev *llc_sap_alloc_ev(struct llc_sap *sap)
+{
+ struct llc_sap_state_ev *ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+
+ if (ev)
+ memset(ev, 0, sizeof(*ev));
+ return ev;
+}
+
+/**
+ * llc_sap_send_ev - sends event to SAP state machine
+ * @sap: pointer to SAP
+ * @ev: pointer to occurred event
+ *
+ * After executing actions of the event, upper layer will be indicated
+ * if needed(on receiving an UI frame).
+ */
+void llc_sap_send_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ struct llc_prim_if_block *prim;
+ u8 flag;
+
+ llc_sap_next_state(sap, ev);
+ flag = ev->ind_cfm_flag;
+ prim = ev->prim;
+ if (flag == LLC_IND) {
+ skb_get(ev->data.pdu.skb);
+ sap->ind(prim);
+ }
+ llc_sap_free_ev(sap, ev);
+}
+
+/**
+ * llc_sap_rtn_pdu - Informs upper layer on rx of an UI, XID or TEST pdu.
+ * @sap: pointer to SAP
+ * @skb: received pdu
+ * @ev: pointer to occurred event
+ */
+void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb,
+ struct llc_sap_state_ev *ev)
+{
+ llc_pdu_un_t *pdu;
+ struct llc_prim_if_block *prim = &llc_ind_prim;
+ union llc_u_prim_data *prim_data = llc_ind_prim.data;
+ u8 lfb;
+
+ llc_pdu_decode_sa(skb, prim_data->udata.saddr.mac);
+ llc_pdu_decode_da(skb, prim_data->udata.daddr.mac);
+ llc_pdu_decode_dsap(skb, &prim_data->udata.daddr.lsap);
+ llc_pdu_decode_ssap(skb, &prim_data->udata.saddr.lsap);
+ prim_data->udata.pri = 0;
+ prim_data->udata.skb = skb;
+ pdu = (llc_pdu_un_t *)skb->nh.raw;
+ switch (LLC_U_PDU_RSP(pdu)) {
+ case LLC_1_PDU_CMD_TEST:
+ prim->prim = LLC_TEST_PRIM;
+ break;
+ case LLC_1_PDU_CMD_XID:
+ prim->prim = LLC_XID_PRIM;
+ break;
+ case LLC_1_PDU_CMD_UI:
+ if (skb->protocol == ntohs(ETH_P_TR_802_2)) {
+ if (((struct trh_hdr *)skb->mac.raw)->rcf) {
+ lfb = ntohs(((struct trh_hdr *)
+ skb->mac.raw)->rcf) &
+ 0x0070;
+ prim_data->udata.lfb = lfb >> 4;
+ } else {
+ lfb = 0xFF;
+ prim_data->udata.lfb = 0xFF;
+ }
+ }
+ prim->prim = LLC_DATAUNIT_PRIM;
+ break;
+ }
+ prim->data = prim_data;
+ prim->sap = sap;
+ ev->ind_cfm_flag = LLC_IND;
+ ev->prim = prim;
+}
+
+/**
+ * llc_sap_send_pdu - Sends a frame to MAC layer for transmition
+ * @sap: pointer to SAP
+ * @skb: pdu that must be sent
+ */
+void llc_sap_send_pdu(struct llc_sap *sap, struct sk_buff *skb)
+{
+ mac_send_pdu(skb);
+ kfree_skb(skb);
+}
+
+/**
+ * llc_sap_free_ev - frees an sap event
+ * @sap: pointer to SAP
+ * @ev: released event
+ */
+static void llc_sap_free_ev(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ if (ev->type == LLC_SAP_EV_TYPE_PDU) {
+ llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
+
+ if (LLC_U_PDU_CMD(pdu) != LLC_1_PDU_CMD_UI)
+ kfree_skb(ev->data.pdu.skb);
+ }
+ kfree(ev);
+}
+
+/**
+ * llc_sap_next_state - finds transition, execs actions & change SAP state
+ * @sap: pointer to SAP
+ * @ev: happened event
+ *
+ * This function finds transition that matches with happened event, then
+ * executes related actions and finally changes state of SAP. It returns
+ * 0 on success and 1 for failure.
+ */
+static int llc_sap_next_state(struct llc_sap *sap, struct llc_sap_state_ev *ev)
+{
+ int rc = 1;
+ struct llc_sap_state_trans *trans;
+
+ if (sap->state <= LLC_NBR_SAP_STATES) {
+ trans = llc_find_sap_trans(sap, ev);
+ if (trans) {
+ /* got the state to which we next transition; perform
+ * the actions associated with this transition before
+ * actually transitioning to the next state
+ */
+ rc = llc_exec_sap_trans_actions(sap, trans, ev);
+ if (!rc)
+ /* transition SAP to next state if all actions
+ * execute successfully
+ */
+ sap->state = trans->next_state;
+ }
+ }
+ return rc;
+}
+
+/**
+ * llc_find_sap_trans - finds transition for event
+ * @sap: pointer to SAP
+ * @ev: happened event
+ *
+ * This function finds transition that matches with happened event.
+ * Returns the pointer to found transition on success or %NULL for
+ * failure.
+ */
+static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
+ struct llc_sap_state_ev* ev)
+{
+ int i = 0;
+ struct llc_sap_state_trans *rc = NULL;
+ struct llc_sap_state_trans **next_trans;
+ struct llc_sap_state *curr_state = &llc_sap_state_table[sap->state - 1];
+ /* search thru events for this state until list exhausted or until
+ * its obvious the event is not valid for the current state
+ */
+ for (next_trans = curr_state->transitions; next_trans [i]->ev; i++)
+ if (!next_trans[i]->ev(sap, ev)) {
+ /* got event match; return it */
+ rc = next_trans[i];
+ break;
+ }
+ return rc;
+}
+
+/**
+ * llc_exec_sap_trans_actions - execute actions related to event
+ * @sap: pointer to SAP
+ * @trans: pointer to transition that it's actions must be performed
+ * @ev: happened event.
+ *
+ * This function executes actions that is related to happened event.
+ * Returns 0 for success and 1 for failure of at least one action.
+ */
+static int llc_exec_sap_trans_actions(struct llc_sap *sap,
+ struct llc_sap_state_trans *trans,
+ struct llc_sap_state_ev *ev)
+{
+ int rc = 0;
+ llc_sap_action_t *next_action;
+
+ for (next_action = trans->ev_actions;
+ next_action && *next_action; next_action++)
+ if ((*next_action)(sap, ev))
+ rc = 1;
+ return rc;
+}
diff --git a/net/llc/llc_sock.c b/net/llc/llc_sock.c
new file mode 100644
index 000000000000..8a9d3fe6bb35
--- /dev/null
+++ b/net/llc/llc_sock.c
@@ -0,0 +1,1780 @@
+/*
+ * llc_sock.c - LLC User Interface SAPs
+ * Description:
+ * Functions in this module are implementation of socket based llc
+ * communications for the Linux operating system. Support of llc class
+ * one and class two is provided via SOCK_DGRAM and SOCK_STREAM
+ * respectively.
+ *
+ * An llc2 connection is (mac + sap), only one llc2 sap connection
+ * is allowed per mac. Though one sap may have multiple mac + sap
+ * connections.
+ *
+ * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <asm/uaccess.h>
+#include <asm/ioctls.h>
+#include <linux/proc_fs.h>
+#include <linux/in.h>
+#include <linux/tcp.h>
+#include <linux/netdevice.h>
+#include <linux/inetdevice.h>
+#include <linux/errno.h>
+#include <net/sock.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_pdu.h>
+#include <net/llc_conn.h>
+#include <linux/llc.h>
+#include <linux/if_arp.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+
+#define dprintk(format, a...) printk(KERN_INFO __FUNCTION__ ": " format, ##a)
+
+/* remember: uninitialized global data is zeroed because its in .bss */
+static u16 llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
+static u16 llc_ui_sap_link_no_max[256];
+static u8 llc_ui_addrany[IFHWADDRLEN];
+static struct sockaddr_llc llc_ui_addrnull;
+static struct proto_ops llc_ui_ops;
+static struct sock *llc_ui_sockets;
+static rwlock_t llc_ui_sockets_lock = RW_LOCK_UNLOCKED;
+
+static int llc_ui_indicate(struct llc_prim_if_block *prim);
+static int llc_ui_confirm(struct llc_prim_if_block *prim);
+static int llc_ui_wait_for_conn(struct sock *sk, int seconds);
+static int llc_ui_wait_for_disc(struct sock *sk, int seconds);
+
+/**
+ * llc_ui_next_link_no - return the next unused link number for a sap
+ * @sap: Address of sap to get link number from.
+ *
+ * Return the next unused link number for a given sap.
+ */
+static inline u16 llc_ui_next_link_no(int sap)
+{
+ return llc_ui_sap_link_no_max[sap]++;
+}
+
+/**
+ * llc_ui_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 u8 llc_ui_mac_match(u8 *mac1, u8 *mac2)
+{
+ return !memcmp(mac1, mac2, IFHWADDRLEN);
+}
+
+/**
+ * llc_ui_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 u8 llc_ui_mac_null(u8 *mac)
+{
+ return !memcmp(mac, llc_ui_addrany, IFHWADDRLEN);
+}
+
+/**
+ * llc_ui_addr_null - determines if a address structure is null
+ * @addr: Address to test if null.
+ */
+static inline u8 llc_ui_addr_null(struct sockaddr_llc *addr)
+{
+ return !memcmp(addr, &llc_ui_addrnull, sizeof(*addr));
+}
+
+/**
+ * llc_ui_protocol_type - return eth protocol for ARP header type
+ * @arphrd: ARP header type.
+ *
+ * Given an ARP header type return the corresponding ethernet protocol.
+ * Returns 0 if ARP header type not supported or the corresponding
+ * ethernet protocol type.
+ */
+static inline u16 llc_ui_protocol_type(u16 arphrd)
+{
+ u16 rc = htons(ETH_P_802_2);
+
+ if (arphrd == ARPHRD_IEEE802_TR)
+ rc = htons(ETH_P_TR_802_2);
+ return rc;
+}
+
+/**
+ * llc_ui_header_len - return length of llc header based on operation
+ * @sk: Socket which contains a valid llc socket type.
+ * @addr: Complete sockaddr_llc structure received from the user.
+ *
+ * Provide the length of the llc header depending on what kind of
+ * operation the user would like to perform and the type of socket.
+ * Returns the correct llc header length.
+ */
+static inline u8 llc_ui_header_len(struct sock *sk, struct sockaddr_llc *addr)
+{
+ u8 rc = LLC_PDU_LEN_U;
+
+ if (addr->sllc_test || addr->sllc_xid)
+ rc = LLC_PDU_LEN_U;
+ else if (sk->type == SOCK_STREAM)
+ rc = LLC_PDU_LEN_I;
+ return rc;
+}
+
+/**
+ * llc_ui_send_conn - send connect command for new llc2 connection
+ * @sap : Sap the socket is bound to.
+ * @addr: Source and destination fields provided by the user.
+ * @dev : Device which this connection should use.
+ * @link: Link number to assign to this connection.
+ *
+ * Send a connect command to the llc layer for a new llc2 connection.
+ * Returns 0 upon success, non-zero if action didn't succeed.
+ */
+static int llc_ui_send_conn(struct sock *sk, struct llc_sap *sap,
+ struct sockaddr_llc *addr,
+ struct net_device *dev, int link)
+{
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ union llc_u_prim_data prim_data;
+ struct llc_prim_if_block prim;
+
+ prim.data = &prim_data;
+ prim.sap = sap;
+ prim.prim = LLC_CONN_PRIM;
+ prim_data.conn.dev = dev;
+ prim_data.conn.link = link;
+ prim_data.conn.sk = NULL;
+ prim_data.conn.handler = sk;
+ prim_data.conn.pri = 0;
+ prim_data.conn.saddr.lsap = llc_ui->addr.sllc_ssap;
+ prim_data.conn.daddr.lsap = addr->sllc_dsap;
+ memcpy(prim_data.conn.saddr.mac, dev->dev_addr, IFHWADDRLEN);
+ memcpy(prim_data.conn.daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
+ return sap->req(&prim);
+}
+
+/**
+ * llc_ui_send_disc - send disc command to llc layer
+ * @sk: Socket with valid llc information.
+ *
+ * Send a disconnect command to the llc layer for an established
+ * llc2 connection.
+ * Returns 0 upon success, non-zero if action did not succeed.
+ */
+static int llc_ui_send_disc(struct sock *sk)
+{
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ union llc_u_prim_data prim_data;
+ struct llc_prim_if_block prim;
+ int rc = 0;
+
+ if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED)
+ goto out;
+ sk->state = TCP_CLOSING;
+ prim.data = &prim_data;
+ prim.sap = llc_ui->sap;
+ prim.prim = LLC_DISC_PRIM;
+ prim_data.disc.sk = llc_ui->core_sk;
+ prim_data.disc.link = llc_ui->link;
+ rc = llc_ui->sap->req(&prim);
+out:
+ return rc;
+}
+
+/**
+ * llc_ui_send_data - send data via reliable llc2 connection
+ * @sap: Sap the socket is bound to.
+ * @sk: Connection the socket is using.
+ * @skb: Data the user wishes to send.
+ * @addr: Source and destination fields provided by the user.
+ *
+ * Send data via reliable llc2 connection.
+ * Returns 0 upon success, non-zero if action did not succeed.
+ */
+static int llc_ui_send_data(struct llc_sap *sap, struct sock* sk,
+ struct sk_buff *skb, struct sockaddr_llc *addr)
+{
+ union llc_u_prim_data prim_data;
+ struct llc_prim_if_block prim;
+ struct llc_ui_opt* llc_ui = llc_ui_sk(sk);
+ struct llc_opt* llc_core = llc_sk(llc_ui->core_sk);
+ int rc;
+
+ prim.data = &prim_data;
+ prim.sap = sap;
+ prim.prim = LLC_DATA_PRIM;
+ prim_data.data.skb = skb;
+ prim_data.data.pri = 0;
+ prim_data.data.sk = llc_ui->core_sk;
+ skb->protocol = llc_ui_protocol_type(addr->sllc_arphrd);
+ sock_hold(sk);
+try:
+ rc = sap->req(&prim);
+ if (rc != -EBUSY)
+ goto out;
+ rc = wait_event_interruptible(sk->socket->wait, !llc_ui->core_sk ||
+ !llc_core->failed_data_req);
+ if (!rc)
+ goto try;
+ if (!llc_ui->core_sk)
+ rc = -ENOTCONN;
+out:
+ sock_put(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_send_llc1 - send llc1 prim data block to llc layer.
+ * @sap : Sap the socket is bound to.
+ * @skb : Data the user wishes to send.
+ * @addr : Source and destination fields provided by the user.
+ * @primitive: Action the llc layer should perform.
+ *
+ * Send an llc1 primitive data block to the llc layer for processing.
+ * This function is used for test, xid and unit_data messages.
+ * Returns 0 upon success, non-zero if action did not succeed.
+ */
+static int llc_ui_send_llc1(struct llc_sap *sap, struct sk_buff *skb,
+ struct sockaddr_llc *addr, int primitive)
+{
+ union llc_u_prim_data prim_data;
+ struct llc_prim_if_block prim;
+
+ prim.data = &prim_data;
+ prim.sap = sap;
+ prim.prim = primitive;
+ prim_data.test.skb = skb;
+ prim_data.test.saddr.lsap = sap->laddr.lsap;
+ prim_data.test.daddr.lsap = addr->sllc_dsap;
+ skb->protocol = llc_ui_protocol_type(addr->sllc_arphrd);
+ memcpy(prim_data.test.saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
+ memcpy(prim_data.test.daddr.mac, addr->sllc_dmac, IFHWADDRLEN);
+ return sap->req(&prim);
+}
+
+/**
+ * llc_ui_find_sap - returns sap struct that matches sap number specified
+ * @sap: Sap number to search for.
+ *
+ * Search the local socket list and return the first instance of the sap
+ * structure which matches the sap number the user specified.
+ * Returns llc_sap upon match, %NULL otherwise.
+ */
+static inline struct llc_sap *llc_ui_find_sap(u8 sap)
+{
+ struct sock *sk;
+ struct llc_sap *s = NULL;
+
+ read_lock_bh(&llc_ui_sockets_lock);
+ for (sk = llc_ui_sockets; sk; sk = sk->next) {
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+
+ if (!llc_ui->sap)
+ continue;
+ if (llc_ui->sap->laddr.lsap == sap) {
+ s = llc_ui->sap;
+ break;
+ }
+ }
+ read_unlock_bh(&llc_ui_sockets_lock);
+ return s;
+}
+
+static struct sock *__llc_ui_find_sk_by_exact(struct llc_addr *laddr,
+ struct llc_addr *daddr)
+{
+ struct sock *sk;
+
+ for (sk = llc_ui_sockets; sk; sk = sk->next) {
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+
+ if (llc_ui->addr.sllc_ssap == laddr->lsap &&
+ llc_ui->addr.sllc_dsap == daddr->lsap &&
+ llc_ui_mac_null(llc_ui->addr.sllc_mmac) &&
+ llc_ui_mac_match(llc_ui->addr.sllc_smac, laddr->mac) &&
+ llc_ui_mac_match(llc_ui->addr.sllc_dmac, daddr->mac))
+ break;
+ }
+ return sk;
+}
+
+/**
+ * __llc_ui_find_sk_by_addr - return socket matching local mac + sap.
+ * @addr: Local address to match.
+ *
+ * Search the local socket list and return the socket which has a matching
+ * local (mac + sap) address (allows null mac). This search will work on
+ * unconnected and connected sockets, though find_by_link_no is recommend
+ * for connected sockets.
+ * Returns sock upon match, %NULL otherwise.
+ */
+static struct sock *__llc_ui_find_sk_by_addr(struct llc_addr *laddr,
+ struct llc_addr *daddr,
+ struct net_device *dev)
+{
+ struct sock *sk, *tmp_sk;
+
+ for (sk = llc_ui_sockets; sk; sk = sk->next) {
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+
+ if (llc_ui->addr.sllc_ssap != laddr->lsap)
+ continue;
+ if (llc_ui_mac_null(llc_ui->addr.sllc_smac)) {
+ if (!llc_ui_mac_null(llc_ui->addr.sllc_mmac) &&
+ !llc_ui_mac_match(llc_ui->addr.sllc_mmac,
+ laddr->mac))
+ continue;
+ break;
+ }
+ if (dev && !llc_ui_mac_null(llc_ui->addr.sllc_mmac) &&
+ llc_ui_mac_match(llc_ui->addr.sllc_mmac, laddr->mac) &&
+ llc_ui_mac_match(llc_ui->addr.sllc_smac, dev->dev_addr))
+ break;
+ if (dev->flags & IFF_LOOPBACK)
+ break;
+ if (!llc_ui_mac_match(llc_ui->addr.sllc_smac, laddr->mac))
+ continue;
+ tmp_sk = __llc_ui_find_sk_by_exact(laddr, daddr);
+ if (tmp_sk) {
+ sk = tmp_sk;
+ break;
+ }
+ if (llc_ui_mac_null(llc_ui->addr.sllc_dmac))
+ break;
+ }
+ return sk;
+}
+
+static struct sock *llc_ui_find_sk_by_addr(struct llc_addr *addr,
+ struct llc_addr *daddr,
+ struct net_device *dev)
+{
+ struct sock *sk;
+
+ read_lock(&llc_ui_sockets_lock);
+ sk = __llc_ui_find_sk_by_addr(addr, daddr, dev);
+ if (sk)
+ sock_hold(sk);
+ read_unlock(&llc_ui_sockets_lock);
+ return sk;
+}
+
+static struct sock *llc_ui_bh_find_sk_by_addr(struct llc_addr *addr,
+ struct llc_addr *daddr,
+ struct net_device *dev)
+{
+ struct sock *sk;
+
+ read_lock_bh(&llc_ui_sockets_lock);
+ sk = __llc_ui_find_sk_by_addr(addr, daddr, dev);
+ if (sk)
+ sock_hold(sk);
+ read_unlock_bh(&llc_ui_sockets_lock);
+ return sk;
+}
+
+/**
+ * llc_ui_insert_socket - insert socket into list
+ * @sk: Socket to insert.
+ *
+ * Insert a socket into the local llc socket list.
+ */
+static inline void llc_ui_insert_socket(struct sock *sk)
+{
+ write_lock_bh(&llc_ui_sockets_lock);
+ sk->next = llc_ui_sockets;
+ if (sk->next)
+ llc_ui_sockets->pprev = &sk->next;
+ llc_ui_sockets = sk;
+ sk->pprev = &llc_ui_sockets;
+ sock_hold(sk);
+ write_unlock_bh(&llc_ui_sockets_lock);
+}
+
+/**
+ * llc_ui_remove_socket - remove socket from list
+ * @sk: Socket to remove.
+ *
+ * Remove a socket from the local llc socket list.
+ */
+static inline void llc_ui_remove_socket(struct sock *sk)
+{
+ write_lock_bh(&llc_ui_sockets_lock);
+ if (sk->pprev) {
+ if (sk->next)
+ sk->next->pprev = sk->pprev;
+ *sk->pprev = sk->next;
+ sk->pprev = NULL;
+ /* this only makes sense if the socket was inserted on the
+ * list, if sk->pprev is NULL it wasn't
+ */
+ sock_put(sk);
+ }
+ write_unlock_bh(&llc_ui_sockets_lock);
+}
+
+/**
+ * llc_ui_destroy_sk - destroy socket
+ * @data: Socket which is to be destroyed.
+ *
+ * Really destroy the socket.
+ */
+static void llc_ui_destroy_sk(struct sock *sk)
+{
+ skb_queue_purge(&sk->receive_queue);
+ skb_queue_purge(&sk->write_queue);
+ sock_put(sk);
+ MOD_DEC_USE_COUNT;
+}
+
+/**
+ * llc_ui_destroy_timer - try to destroy socket again
+ * @data: Socket which is to be destroyed.
+ *
+ * Attempt to destroy a socket which was previously destroyed but
+ * was still in use at the time.
+ */
+static void llc_ui_destroy_timer(unsigned long data)
+{
+ struct sock *sk = (struct sock *)data;
+
+ if (!atomic_read(&sk->wmem_alloc) &&
+ !atomic_read(&sk->rmem_alloc) && sk->dead)
+ llc_ui_destroy_sk(sk);
+ else {
+ sk->timer.expires = jiffies + SOCK_DESTROY_TIME;
+ add_timer(&sk->timer);
+ }
+}
+
+/**
+ * llc_ui_create - alloc and init a new llc_ui socket
+ * @sock: Socket to initialize and attach allocated sk to.
+ * @protocol: Unused.
+ *
+ * Allocate and initialize a new llc_ui socket, validate the user wants a
+ * socket type we have available.
+ * Returns 0 upon success, negative upon failure.
+ */
+static int llc_ui_create(struct socket *sock, int protocol)
+{
+ struct sock *sk;
+ struct llc_ui_opt *llc_ui;
+ int rc = -ESOCKTNOSUPPORT;
+
+ MOD_INC_USE_COUNT;
+ if (sock->type != SOCK_DGRAM && sock->type != SOCK_STREAM)
+ goto decmod;
+ rc = -ENOMEM;
+ sk = sk_alloc(PF_LLC, GFP_KERNEL, 1, NULL);
+ if (!sk)
+ goto decmod;
+ llc_ui = kmalloc(sizeof(*llc_ui), GFP_KERNEL);
+ if (!llc_ui)
+ goto outsk;
+ memset(llc_ui, 0, sizeof(*llc_ui));
+ rc = 0;
+ sock_init_data(sock, sk);
+ llc_ui_sk(sk) = llc_ui;
+ sock->ops = &llc_ui_ops;
+out:
+ return rc;
+outsk:
+ sk_free(sk);
+decmod:
+ MOD_DEC_USE_COUNT;
+ goto out;
+}
+
+/**
+ * llc_ui_release - shutdown socket
+ * @sock: Socket to release.
+ *
+ * Shutdown and deallocate an existing socket.
+ */
+static int llc_ui_release(struct socket *sock)
+{
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui;
+
+ if (!sk)
+ goto out;
+ llc_ui = llc_ui_sk(sk);
+ if (llc_ui->core_sk && !llc_ui_send_disc(sk))
+ llc_ui_wait_for_disc(sk, 255);
+ llc_ui_remove_socket(sk);
+ if (llc_ui->sap && !llc_ui_find_sap(llc_ui->sap->laddr.lsap))
+ llc_sap_close(llc_ui->sap);
+ dprintk("rxq=%d, txq=%d\n", skb_queue_len(&sk->receive_queue),
+ skb_queue_len(&sk->write_queue));
+ sock_orphan(sk);
+ sock->sk = NULL;
+ if (!atomic_read(&sk->wmem_alloc) &&
+ !atomic_read(&sk->rmem_alloc) && sk->dead)
+ llc_ui_destroy_sk(sk);
+ else {
+ init_timer(&sk->timer);
+ sk->timer.expires = jiffies + SOCK_DESTROY_TIME;
+ sk->timer.function = llc_ui_destroy_timer;
+ sk->timer.data = (unsigned long)sk;
+ add_timer(&sk->timer);
+ }
+out:
+ return 0;
+}
+
+/**
+ * llc_ui_autoport - provide dynamicly allocate SAP number
+ *
+ * Provide the caller with a dynamicly allocated SAP number according
+ * to the rules that are set in this function. Returns: 0, upon failure,
+ * SAP number otherwise.
+ */
+static int llc_ui_autoport(void)
+{
+ struct llc_sap *sap;
+ int i, tries = 0;
+
+ while (tries < LLC_SAP_DYN_TRIES) {
+ for (i = llc_ui_sap_last_autoport;
+ i < LLC_SAP_DYN_STOP; i += 2) {
+ sap = llc_ui_find_sap(i);
+ if (!sap) {
+ llc_ui_sap_last_autoport = i + 2;
+ goto out;
+ }
+ }
+ llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
+ tries++;
+ }
+ i = 0;
+out:
+ return i;
+}
+
+/**
+ * llc_ui_autobind - Bind a socket to a specific address.
+ * @sk: Socket to bind an address to.
+ * @addr: Address the user wants the socket bound to.
+ *
+ * Bind a socket to a specific address. For llc a user is able to bind to
+ * a specific sap only or mac + sap. If the user only specifies a sap and
+ * a null dmac (all zeros) the user is attempting to bind to an entire
+ * sap. This will stop anyone else on the local system from using that
+ * sap. If someone else has a mac + sap open the bind to null + sap will
+ * fail.
+ * If the user desires to bind to a specific mac + sap, it is possible to
+ * have multiple sap connections via multiple macs.
+ * Bind and autobind for that matter must enforce the correct sap usage
+ * otherwise all hell will break loose.
+ * Returns: 0 upon success, negative otherwise.
+ */
+static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
+{
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ struct llc_sap *sap;
+ struct net_device *dev = NULL;
+ int rc = -EINVAL;
+
+ if (!sk->zapped)
+ goto out;
+ /* bind to a specific mac, optional. */
+ if (!llc_ui_mac_null(addr->sllc_smac)) {
+ rtnl_lock();
+ dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac);
+ rtnl_unlock();
+ rc = -ENETUNREACH;
+ if (!dev)
+ goto out;
+ llc_ui->dev = dev;
+ }
+ /* bind to a specific sap, optional. */
+ if (!addr->sllc_ssap) {
+ rc = -EUSERS;
+ addr->sllc_ssap = llc_ui_autoport();
+ if (!addr->sllc_ssap)
+ goto out;
+ }
+ sap = llc_ui_find_sap(addr->sllc_ssap);
+ if (!sap) {
+ sap = llc_sap_open(llc_ui_indicate, llc_ui_confirm,
+ addr->sllc_ssap);
+ rc = -EBUSY; /* some other network layer is using the sap */
+ if (!sap)
+ goto out;
+ } else {
+ struct llc_addr laddr, daddr;
+ struct sock *ask;
+
+ rc = -EUSERS; /* can't get exclusive use of sap */
+ if (!dev && llc_ui_mac_null(addr->sllc_mmac))
+ goto out;
+ memset(&laddr, 0, sizeof(laddr));
+ memset(&daddr, 0, sizeof(daddr));
+ if (!llc_ui_mac_null(addr->sllc_mmac)) {
+ if (sk->type != SOCK_DGRAM) {
+ rc = -EOPNOTSUPP;
+ goto out;
+ }
+ memcpy(laddr.mac, addr->sllc_mmac, IFHWADDRLEN);
+ } else
+ memcpy(laddr.mac, addr->sllc_smac, IFHWADDRLEN);
+ laddr.lsap = addr->sllc_ssap;
+ rc = -EADDRINUSE; /* mac + sap clash. */
+ ask = llc_ui_bh_find_sk_by_addr(&laddr, &daddr, dev);
+ if (ask) {
+ sock_put(ask);
+ goto out;
+ }
+ }
+ memcpy(&llc_ui->addr, addr, sizeof(*addr));
+ llc_ui->sap = sap;
+ rc = sk->zapped = 0;
+ llc_ui_insert_socket(sk);
+out:
+ return rc;
+}
+
+/**
+ * llc_ui_bind - bind a socket to a specific address.
+ * @sock: Socket to bind an address to.
+ * @uaddr: Address the user wants the socket bound to.
+ * @addrlen: Length of the uaddr structure.
+ *
+ * Bind a socket to a specific address. For llc a user is able to bind to
+ * a specific sap only or mac + sap. If the user only specifies a sap and
+ * a null dmac (all zeros) the user is attempting to bind to an entire
+ * sap. This will stop anyone else on the local system from using that
+ * sap. If someone else has a mac + sap open the bind to null + sap will
+ * fail.
+ * If the user desires to bind to a specific mac + sap, it is possible to
+ * have multiple sap connections via multiple macs.
+ * Bind and autobind for that matter must enforce the correct sap usage
+ * otherwise all hell will break loose.
+ * Returns: 0 upon success, negative otherwise.
+ */
+static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
+{
+ struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
+ struct sock *sk = sock->sk;
+ int rc = -EINVAL;
+
+ if (!sk->zapped || addrlen != sizeof(*addr))
+ goto out;
+ rc = -EAFNOSUPPORT;
+ if (addr->sllc_family != AF_LLC)
+ goto out;
+ /* use autobind, to avoid code replication. */
+ rc = llc_ui_autobind(sock, addr);
+out:
+ return rc;
+}
+
+/**
+ * llc_ui_shutdown - shutdown a connect llc2 socket.
+ * @sock: Socket to shutdown.
+ * @how: What part of the socket to shutdown.
+ *
+ * Shutdown a connected llc2 socket. Currently this function only supports
+ * shutting down both sends and receives (2), we could probably make this
+ * function such that a user can shutdown only half the connection but not
+ * right now.
+ * Returns: 0 upon success, negative otherwise.
+ */
+static int llc_ui_shutdown(struct socket *sock, int how)
+{
+ struct sock *sk = sock->sk;
+ int rc = -ENOTCONN;
+
+ lock_sock(sk);
+ if (sk->state != TCP_ESTABLISHED)
+ goto out;
+ rc = -EINVAL;
+ if (how != 2)
+ goto out;
+ rc = llc_ui_send_disc(sk);
+ if (!rc)
+ llc_ui_wait_for_disc(sk, 255);
+ /* Wake up anyone sleeping in poll */
+ sk->state_change(sk);
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_connect - Connect to a remote llc2 mac + sap.
+ * @sock: Socket which will be connected to the remote destination.
+ * @uaddr: Remote and possibly the local address of the new connection.
+ * @addrlen: Size of uaddr structure.
+ * @flags: Operational flags specified by the user.
+ *
+ * Connect to a remote llc2 mac + sap. The caller must specify the
+ * destination mac and address to connect to. If the user previously
+ * called bind(2) with a smac the user does not need to specify the source
+ * address and mac.
+ * This function will autobind if user did not previously call bind.
+ * Returns: 0 upon success, negative otherwise.
+ */
+static int llc_ui_connect(struct socket *sock, struct sockaddr *uaddr,
+ int addrlen, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
+ struct net_device *dev;
+ int rc = -EINVAL;
+
+ lock_sock(sk);
+ if (addrlen != sizeof(*addr))
+ goto out;
+ rc = -EAFNOSUPPORT;
+ if (addr->sllc_family != AF_LLC)
+ goto out;
+ /* bind connection to sap if user hasn't done it. */
+ if (sk->zapped) {
+ /* bind to sap with null dev, exclusive */
+ rc = llc_ui_autobind(sock, addr);
+ if (rc)
+ goto out;
+ }
+ if (!llc_ui->dev) {
+ rtnl_lock();
+ dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac);
+ rtnl_unlock();
+ if (!dev)
+ goto out;
+ } else
+ dev = llc_ui->dev;
+ if (sk->type != SOCK_STREAM)
+ goto out;
+ rc = -EALREADY;
+ if (sock->state == SS_CONNECTING)
+ goto out;
+ sock->state = SS_CONNECTING;
+ sk->state = TCP_SYN_SENT;
+ llc_ui->link = llc_ui_next_link_no(llc_ui->sap->laddr.lsap);
+ rc = llc_ui_send_conn(sk, llc_ui->sap, addr, dev, llc_ui->link);
+ if (rc) {
+ sock->state = SS_UNCONNECTED;
+ sk->state = TCP_CLOSE;
+ goto out;
+ }
+ rc = llc_ui_wait_for_conn(sk, 255);
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_listen - allow a normal socket to accept incoming connections
+ * @sock: Socket to allow incoming connections on.
+ * @backlog: Number of connections to queue.
+ *
+ * Allow a normal socket to accept incoming connections.
+ * Returns 0 upon success, negative otherwise.
+ */
+static int llc_ui_listen(struct socket *sock, int backlog)
+{
+ struct sock *sk = sock->sk;
+ int rc = -EINVAL;
+
+ lock_sock(sk);
+ if (sock->state != SS_UNCONNECTED)
+ goto out;
+ rc = -EOPNOTSUPP;
+ if (sk->type != SOCK_STREAM && sk->type != SOCK_SEQPACKET)
+ goto out;
+ rc = -EAGAIN;
+ if (sk->zapped)
+ goto out;
+ rc = 0;
+ if (!(unsigned)backlog) /* BSDism */
+ backlog = 1;
+ if ((unsigned)backlog > SOMAXCONN)
+ backlog = SOMAXCONN;
+ sk->max_ack_backlog = backlog;
+ if (sk->state != TCP_LISTEN) {
+ sk->ack_backlog = 0;
+ sk->state = TCP_LISTEN;
+ }
+ sk->socket->flags |= __SO_ACCEPTCON;
+out:
+ release_sock(sk);
+ return rc;
+}
+
+static int llc_ui_wait_for_disc(struct sock *sk, int seconds)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int rc, timeout = seconds * HZ;
+
+ add_wait_queue_exclusive(sk->sleep, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ rc = 0;
+ if (sk->state != TCP_CLOSE)
+ timeout = schedule_timeout(timeout);
+ else
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ rc = -EAGAIN;
+ if (!timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sleep, &wait);
+ return rc;
+}
+
+static int llc_ui_wait_for_conn(struct sock *sk, int seconds)
+{
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ DECLARE_WAITQUEUE(wait, current);
+ int rc, timeout = seconds * HZ;
+
+ add_wait_queue_exclusive(sk->sleep, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ rc = 0;
+ if (sk->state != TCP_ESTABLISHED)
+ timeout = schedule_timeout(timeout);
+ if (sk->state == TCP_ESTABLISHED) {
+ if (!llc_ui->core_sk)
+ rc = -EAGAIN;
+ break;
+ }
+ rc = -EAGAIN;
+ if (sk->state == TCP_CLOSE)
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ rc = -EAGAIN;
+ if (!timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sleep, &wait);
+ return rc;
+}
+
+/**
+ * llc_ui_accept - accept a new incoming connection.
+ * @sock: Socket which connections arrive on.
+ * @newsock: Socket to move incoming connection to.
+ * @flags: User specified operational flags.
+ *
+ * Accept a new incoming connection.
+ * Returns 0 upon success, negative otherwise.
+ */
+static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+ struct sock *sk = sock->sk, *newsk;
+ struct llc_ui_opt *llc_ui, *newllc_ui;
+ struct llc_opt *newllc_core;
+ struct sk_buff *skb;
+ int rc = -EOPNOTSUPP;
+
+ lock_sock(sk);
+ if (sk->type != SOCK_SEQPACKET && sk->type != SOCK_STREAM)
+ goto out;
+ rc = -EINVAL;
+ if (sock->state != SS_UNCONNECTED || sk->state != TCP_LISTEN)
+ goto out;
+ /* wait for a connection to arrive. */
+ do {
+ skb = skb_dequeue(&sk->receive_queue);
+ if (!skb) {
+ rc = -EWOULDBLOCK;
+ if (flags & O_NONBLOCK)
+ goto out;
+ interruptible_sleep_on(sk->sleep);
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ goto out;
+ }
+ } while (!skb);
+
+ rc = -EINVAL;
+ if(!skb->sk)
+ goto frees;
+ /* attach connection to a new socket. */
+ rc = llc_ui_create(newsock, sk->protocol);
+ if (rc)
+ goto frees;
+ rc = 0;
+ newsk = newsock->sk;
+ newsk->pair = NULL;
+ newsk->socket = newsock;
+ newsk->sleep = &newsock->wait;
+ newsk->zapped = 0;
+ newsk->state = TCP_ESTABLISHED;
+ newsock->state = SS_CONNECTED;
+ llc_ui = llc_ui_sk(sk);
+ newllc_ui = llc_ui_sk(newsk);
+ newllc_ui->sap = llc_ui->sap;
+ newllc_ui->dev = llc_ui->dev;
+ newllc_ui->core_sk = skb->sk;
+ newllc_core = llc_sk(newllc_ui->core_sk);
+ newllc_ui->link = newllc_core->link;
+ newllc_core->handler = newsk;
+ memcpy(&newllc_ui->addr, &llc_ui->addr, sizeof(newllc_ui->addr));
+ memcpy(newllc_ui->addr.sllc_dmac, newllc_core->daddr.mac, IFHWADDRLEN);
+ newllc_ui->addr.sllc_dsap = newllc_core->daddr.lsap;
+
+ /* put original socket back into a clean listen state. */
+ sk->state = TCP_LISTEN;
+ sk->ack_backlog--;
+ llc_ui_insert_socket(newsk);
+ skb->sk = NULL;
+frees:
+ kfree_skb(skb);
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_recvmsg - copy received data to the socket user.
+ * @sock: Socket to copy data from.
+ * @msg: Various user space related information.
+ * @size: Size of user buffer.
+ * @flags: User specified flags.
+ * @scm: Unknown.
+ *
+ * Copy received data to the socket user.
+ * Returns non-negative upon success, negative otherwise.
+ */
+static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, int size,
+ int flags, struct scm_cookie *scm)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
+ struct sk_buff *skb;
+ int rc = -ENOMEM, copied = 0;
+ int noblock = flags & MSG_DONTWAIT;
+
+ lock_sock(sk);
+ skb = skb_recv_datagram(sk, flags, noblock, &rc);
+ if (!skb)
+ goto out;
+ copied = skb->len;
+ if (copied > size) {
+ copied = size;
+ msg->msg_flags |= MSG_TRUNC;
+ }
+ rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ if (rc)
+ goto dgram_free;
+ if (uaddr)
+ memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
+ msg->msg_namelen = sizeof(*uaddr);
+dgram_free:
+ skb_free_datagram(sk, skb); /* Free the datagram. */
+out:
+ release_sock(sk);
+ return rc ? : copied;
+}
+
+/**
+ * llc_ui_sendmsg - Transmit data provided by the socket user.
+ * @sock: Socket to transmit data from.
+ * @msg: Various user related information.
+ * @len: Length of data to transmit.
+ * @scm: Unknown.
+ *
+ * Transmit data provided by the socket user.
+ * Returns non-negative upon success, negative otherwise.
+ */
+static int llc_ui_sendmsg(struct socket *sock, struct msghdr *msg, int len,
+ struct scm_cookie *scm)
+{
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
+ int flags = msg->msg_flags;
+ struct net_device *dev;
+ struct sk_buff *skb;
+ int rc = -EOPNOTSUPP, size = 0;
+
+ lock_sock(sk);
+ if (flags & ~MSG_DONTWAIT)
+ goto release;
+ rc = -EINVAL;
+ if (addr) {
+ if (msg->msg_namelen < sizeof(*addr))
+ goto release;
+ } else {
+ if (llc_ui_addr_null(&llc_ui->addr))
+ goto release;
+ addr = &llc_ui->addr;
+ }
+ /* must bind connection to sap if user hasn't done it. */
+ if (sk->zapped) {
+ /* bind to sap with null dev, exclusive. */
+ rc = llc_ui_autobind(sock, addr);
+ if (rc)
+ goto release;
+ }
+ if (!llc_ui->dev) {
+ rtnl_lock();
+ dev = dev_getbyhwaddr(addr->sllc_arphrd, addr->sllc_smac);
+ rtnl_unlock();
+ rc = -ENETUNREACH;
+ if (!dev)
+ goto release;
+ } else
+ dev = llc_ui->dev;
+ size = dev->hard_header_len + len + llc_ui_header_len(sk, addr);
+ rc = -EMSGSIZE;
+ if (size > dev->mtu)
+ goto release;
+ skb = sock_alloc_send_skb(sk, size, flags & MSG_DONTWAIT, &rc);
+ if (!skb)
+ goto release;
+ skb->sk = sk;
+ skb->dev = dev;
+ skb_reserve(skb, dev->hard_header_len + llc_ui_header_len(sk, addr));
+ rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
+ if (rc)
+ goto release;
+ if (addr->sllc_test) {
+ rc = llc_ui_send_llc1(llc_ui->sap, skb, addr, LLC_TEST_PRIM);
+ goto out;
+ }
+ if (addr->sllc_xid) {
+ rc = llc_ui_send_llc1(llc_ui->sap, skb, addr, LLC_XID_PRIM);
+ goto out;
+ }
+ if (sk->type == SOCK_DGRAM || addr->sllc_ua) {
+ rc = llc_ui_send_llc1(llc_ui->sap, skb, addr, LLC_DATAUNIT_PRIM);
+ goto out;
+ }
+ rc = -ENOPROTOOPT;
+ if (!(sk->type == SOCK_STREAM && !addr->sllc_ua))
+ goto out;
+ rc = -ENOTCONN;
+ if (!llc_ui->core_sk)
+ goto out;
+ rc = llc_ui_send_data(llc_ui->sap, sk, skb, addr);
+out:
+ if (rc)
+ skb_free_datagram(sk, skb);
+release:
+ release_sock(sk);
+ return rc ? : len;
+}
+
+/**
+ * llc_ui_getname - return the address info of a socket
+ * @sock: Socket to get address of.
+ * @uaddr: Address structure to return information.
+ * @uaddrlen: Length of address structure.
+ * @peer: Does user want local or remote address information.
+ *
+ * Return the address information of a socket.
+ */
+static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr,
+ int *uaddrlen, int peer)
+{
+ struct sockaddr_llc sllc;
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ int rc = 0;
+
+ lock_sock(sk);
+ if (sk->zapped)
+ goto out;
+ *uaddrlen = sizeof(sllc);
+ memset(uaddr, 0, *uaddrlen);
+ if (peer) {
+ rc = -ENOTCONN;
+ if (sk->state != TCP_ESTABLISHED)
+ goto out;
+ if(llc_ui->dev)
+ sllc.sllc_arphrd = llc_ui->dev->type;
+ sllc.sllc_dsap = llc_sk(llc_ui->core_sk)->daddr.lsap;
+ memcpy(&sllc.sllc_dmac, &llc_sk(llc_ui->core_sk)->daddr.mac,
+ IFHWADDRLEN);
+ } else {
+ rc = -EINVAL;
+ if (!llc_ui->sap)
+ goto out;
+ sllc.sllc_ssap = llc_ui->sap->laddr.lsap;
+
+ if (llc_ui->dev) {
+ sllc.sllc_arphrd = llc_ui->dev->type;
+ memcpy(&sllc.sllc_smac, &llc_ui->dev->dev_addr,
+ IFHWADDRLEN);
+ }
+ }
+ rc = 0;
+ sllc.sllc_family = AF_LLC;
+ memcpy(uaddr, &sllc, sizeof(sllc));
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_ioctl - io controls for PF_LLC
+ * @sock: Socket to get/set info
+ * @cmd: command
+ * @arg: optional argument for cmd
+ *
+ * get/set info on llc sockets
+ */
+static int llc_ui_ioctl(struct socket *sock, unsigned int cmd,
+ unsigned long arg)
+{
+ return dev_ioctl(cmd, (void *)arg);
+}
+
+/**
+ * llc_ui_setsockopt - set various connection specific parameters.
+ * @sock: Socket to set options on.
+ * @level: Socket level user is requesting operations on.
+ * @optname: Operation name.
+ * @optval User provided operation data.
+ * @optlen: Length of optval.
+ *
+ * Set various connection specific parameters.
+ */
+static int llc_ui_setsockopt(struct socket *sock, int level, int optname,
+ char *optval, int optlen)
+{
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ struct llc_opt *llc_core;
+ int rc = -EINVAL, opt;
+
+ lock_sock(sk);
+ if (level != SOL_LLC || optlen != sizeof(int))
+ goto out;
+ rc = -ENOTCONN;
+ if (!llc_ui->core_sk)
+ goto out;
+ rc = get_user(opt, (int *)optval);
+ if (rc)
+ goto out;
+ rc = -EINVAL;
+ llc_core = llc_sk(llc_ui->core_sk);
+ switch (optname) {
+ case LLC_OPT_RETRY:
+ if (opt > LLC_OPT_MAX_RETRY)
+ goto out;
+ llc_core->n2 = opt;
+ break;
+ case LLC_OPT_SIZE:
+ if (opt > LLC_OPT_MAX_SIZE)
+ goto out;
+ llc_core->n1 = opt;
+ break;
+ case LLC_OPT_ACK_TMR_EXP:
+ if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
+ goto out;
+ llc_core->ack_timer.expire = opt;
+ break;
+ case LLC_OPT_P_TMR_EXP:
+ if (opt > LLC_OPT_MAX_P_TMR_EXP)
+ goto out;
+ llc_core->pf_cycle_timer.expire = opt;
+ break;
+ case LLC_OPT_REJ_TMR_EXP:
+ if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
+ goto out;
+ llc_core->rej_sent_timer.expire = opt;
+ break;
+ case LLC_OPT_BUSY_TMR_EXP:
+ if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
+ goto out;
+ llc_core->busy_state_timer.expire = opt;
+ break;
+ case LLC_OPT_TX_WIN:
+ if (opt > LLC_OPT_MAX_WIN)
+ goto out;
+ llc_core->k = opt;
+ break;
+ case LLC_OPT_RX_WIN:
+ if (opt > LLC_OPT_MAX_WIN)
+ goto out;
+ llc_core->rw = opt;
+ break;
+ default:
+ rc = -ENOPROTOOPT;
+ goto out;
+ }
+ rc = 0;
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_getsockopt - get connection specific socket info
+ * @sock: Socket to get information from.
+ * @level: Socket level user is requesting operations on.
+ * @optname: Operation name.
+ * @optval: Variable to return operation data in.
+ * @optlen: Length of optval.
+ *
+ * Get connection specific socket information.
+ */
+static int llc_ui_getsockopt(struct socket *sock, int level, int optname,
+ char *optval, int *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct llc_ui_opt *llc_ui = llc_ui_sk(sk);
+ struct llc_opt *llc_core;
+ int val = 0, len = 0, rc = -EINVAL;
+
+ lock_sock(sk);
+ if (level != SOL_LLC)
+ goto out;
+ rc = -ENOTCONN;
+ if (!llc_ui->core_sk)
+ goto out;
+ rc = get_user(len, optlen);
+ if (rc)
+ goto out;
+ rc = -EINVAL;
+ if (len != sizeof(int))
+ goto out;
+ llc_core = llc_sk(llc_ui->core_sk);
+ switch (optname) {
+ case LLC_OPT_RETRY:
+ val = llc_core->n2; break;
+ case LLC_OPT_SIZE:
+ val = llc_core->n1; break;
+ case LLC_OPT_ACK_TMR_EXP:
+ val = llc_core->ack_timer.expire; break;
+ case LLC_OPT_P_TMR_EXP:
+ val = llc_core->pf_cycle_timer.expire; break;
+ case LLC_OPT_REJ_TMR_EXP:
+ val = llc_core->rej_sent_timer.expire; break;
+ case LLC_OPT_BUSY_TMR_EXP:
+ val = llc_core->busy_state_timer.expire; break;
+ case LLC_OPT_TX_WIN:
+ val = llc_core->k; break;
+ case LLC_OPT_RX_WIN:
+ val = llc_core->rw; break;
+ default:
+ rc = -ENOPROTOOPT;
+ goto out;
+ }
+ rc = 0;
+ if (put_user(len, optlen) || copy_to_user(optval, &val, len))
+ rc = -EFAULT;
+out:
+ release_sock(sk);
+ return rc;
+}
+
+/**
+ * llc_ui_ind_test - handle TEST indication
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle TEST indication.
+ */
+static void llc_ui_ind_test(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_test *prim_data = &prim->data->test;
+ struct sk_buff *skb = prim_data->skb;
+ struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb);
+ struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr,
+ &prim_data->saddr, skb->dev);
+ if (!sk)
+ goto out;
+ if (sk->state == TCP_LISTEN)
+ goto out_put;
+ /* save primitive for use by the user. */
+ llc_ui->sllc_family = AF_LLC;
+ llc_ui->sllc_arphrd = skb->dev->type;
+ llc_ui->sllc_test = 1;
+ llc_ui->sllc_xid = 0;
+ llc_ui->sllc_ua = 0;
+ llc_ui->sllc_dsap = prim_data->daddr.lsap;
+ memcpy(llc_ui->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN);
+ llc_ui->sllc_ssap = prim_data->saddr.lsap;
+ memcpy(llc_ui->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN);
+ /* queue skb to the user. */
+ if (sock_queue_rcv_skb(sk, skb))
+ kfree_skb(skb);
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_ind_xid - handle XID indication
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle XID indication.
+ */
+static void llc_ui_ind_xid(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_xid *prim_data = &prim->data->xid;
+ struct sk_buff *skb = prim_data->skb;
+ struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb);
+ struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr,
+ &prim_data->saddr, skb->dev);
+ if (!sk)
+ goto out;
+ if (sk->state == TCP_LISTEN)
+ goto out_put;
+ /* save primitive for use by the user. */
+ llc_ui->sllc_family = AF_LLC;
+ llc_ui->sllc_arphrd = 0;
+ llc_ui->sllc_test = 0;
+ llc_ui->sllc_xid = 1;
+ llc_ui->sllc_ua = 0;
+ llc_ui->sllc_dsap = prim_data->daddr.lsap;
+ memcpy(llc_ui->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN);
+ llc_ui->sllc_ssap = prim_data->saddr.lsap;
+ memcpy(llc_ui->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN);
+ /* queue skb to the user. */
+ if (sock_queue_rcv_skb(sk, skb))
+ kfree_skb(skb);
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_ind_dataunit - handle DATAUNIT indication
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle DATAUNIT indication.
+ */
+static void llc_ui_ind_dataunit(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_unit_data *prim_data = &prim->data->udata;
+ struct sk_buff *skb = prim_data->skb;
+ struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb);
+ struct sock *sk = llc_ui_find_sk_by_addr(&prim_data->daddr,
+ &prim_data->saddr, skb->dev);
+ if (!sk)
+ goto out;
+ if (sk->state == TCP_LISTEN)
+ goto out_put;
+ /* save primitive for use by the user. */
+ llc_ui->sllc_family = AF_LLC;
+ llc_ui->sllc_arphrd = skb->dev->type;
+ llc_ui->sllc_test = 0;
+ llc_ui->sllc_xid = 0;
+ llc_ui->sllc_ua = 1;
+ llc_ui->sllc_dsap = prim_data->daddr.lsap;
+ memcpy(llc_ui->sllc_dmac, prim_data->daddr.mac, IFHWADDRLEN);
+ llc_ui->sllc_ssap = prim_data->saddr.lsap;
+ memcpy(llc_ui->sllc_smac, prim_data->saddr.mac, IFHWADDRLEN);
+ /* queue skb to the user. */
+ if (sock_queue_rcv_skb(sk, skb))
+ kfree_skb(skb);
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_ind_conn - handle CONNECT indication
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle CONNECT indication.
+ */
+static void llc_ui_ind_conn(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_conn *prim_data = &prim->data->conn;
+ struct sock* sk;
+ struct sk_buff *skb2;
+
+ llc_sk(prim_data->sk)->laddr.lsap = prim->sap->laddr.lsap;
+ sk = llc_ui_find_sk_by_addr(&llc_sk(prim_data->sk)->laddr,
+ &prim_data->saddr, prim_data->dev);
+ if (!sk) {
+ dprintk("llc_ui_find_sk_by_addr failed\n");
+ goto out;
+ }
+ if (sk->type != SOCK_STREAM || sk->state != TCP_LISTEN)
+ goto out_put;
+ if (prim->data->conn.status)
+ goto out_put; /* bad status. */
+ /* give this connection a link number. */
+ llc_sk(prim_data->sk)->link =
+ llc_ui_next_link_no(llc_sk(prim_data->sk)->laddr.lsap);
+ skb2 = alloc_skb(0, GFP_ATOMIC);
+ if (!skb2)
+ goto out_put;
+ skb2->sk = prim_data->sk;
+ skb_queue_tail(&sk->receive_queue, skb2);
+ sk->state_change(sk);
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_ind_data - handle DATA indication
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle CONNECT indication.
+ */
+static void llc_ui_ind_data(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_data *prim_data = &prim->data->data;
+ struct sk_buff *skb = prim_data->skb;
+ struct sockaddr_llc *llc_ui = llc_ui_skb_cb(skb);
+ struct sock* sk = llc_sk(prim_data->sk)->handler;
+
+ if (!sk)
+ goto out;
+ sock_hold(sk);
+ if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED)
+ goto out_put;
+ /* save primitive for use by the user. */
+ llc_ui->sllc_family = AF_LLC;
+ llc_ui->sllc_arphrd = skb->dev->type;
+ llc_ui->sllc_test = 0;
+ llc_ui->sllc_xid = 0;
+ llc_ui->sllc_ua = 0;
+ llc_ui->sllc_dsap = llc_ui_sk(sk)->sap->laddr.lsap;
+ memcpy(llc_ui->sllc_dmac, llc_sk(prim_data->sk)->laddr.mac,
+ IFHWADDRLEN);
+ llc_ui->sllc_ssap = llc_sk(prim_data->sk)->daddr.lsap;
+ memcpy(llc_ui->sllc_smac, llc_sk(prim_data->sk)->daddr.mac,
+ IFHWADDRLEN);
+ /* queue skb to the user. */
+ if (sock_queue_rcv_skb(sk, skb)) {
+ dprintk("sock_queue_rcv_skb failed!\n");
+ kfree_skb(skb);
+ }
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_ind_disc - handle DISC indication
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle DISC indication.
+ */
+static void llc_ui_ind_disc(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_disc *prim_data = &prim->data->disc;
+ struct sock* sk = llc_sk(prim_data->sk)->handler;
+
+ if (!sk)
+ goto out;
+ sock_hold(sk);
+ if (sk->type != SOCK_STREAM || sk->state != TCP_ESTABLISHED)
+ goto out_put;
+ llc_ui_sk(sk)->core_sk = NULL;
+ sk->shutdown = SHUTDOWN_MASK;
+ sk->socket->state = SS_UNCONNECTED;
+ sk->state = TCP_CLOSE;
+ if (!sk->dead) {
+ sk->state_change(sk);
+ sk->dead = 1;
+ }
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_indicate - LLC user interface hook into the LLC layer.
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * LLC user interface hook into the LLC layer, every llc_ui sap references
+ * this function as its indicate handler.
+ * Always returns 0 to indicate reception of primitive.
+ */
+static int llc_ui_indicate(struct llc_prim_if_block *prim)
+{
+ switch (prim->prim) {
+ case LLC_TEST_PRIM:
+ llc_ui_ind_test(prim); break;
+ case LLC_XID_PRIM:
+ llc_ui_ind_xid(prim); break;
+ case LLC_DATAUNIT_PRIM:
+ llc_ui_ind_dataunit(prim); break;
+ case LLC_CONN_PRIM:
+ llc_ui_ind_conn(prim); break;
+ case LLC_DATA_PRIM:
+ llc_ui_ind_data(prim); break;
+ case LLC_DISC_PRIM:
+ llc_ui_ind_disc(prim); break;
+ case LLC_RESET_PRIM:
+ case LLC_FLOWCONTROL_PRIM:
+ default: break;
+ }
+ return 0;
+}
+
+/**
+ * llc_ui_conf_conn - handle CONN confirm.
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle CONN confirm.
+ */
+static void llc_ui_conf_conn(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_conn *prim_data = &prim->data->conn;
+ struct llc_opt *llc_core = llc_sk(prim_data->sk);
+ struct llc_ui_opt *llc_ui = llc_ui_sk(prim_data->sk);
+ struct sock* sk = llc_core->handler;
+
+ if (!sk) {
+ dprintk("llc_core->handler == NULL!\n");
+ goto out;
+ }
+ sock_hold(sk);
+ if (sk->type != SOCK_STREAM || sk->state != TCP_SYN_SENT)
+ goto out_put;
+ if (!prim->data->conn.status) {
+ sk->socket->state = SS_CONNECTED;
+ sk->state = TCP_ESTABLISHED;
+ llc_ui->core_sk = prim_data->sk;
+ } else {
+ dprintk("prim->data->conn.status = %d\n",
+ prim->data->conn.status);
+ sk->socket->state = SS_UNCONNECTED;
+ sk->state = TCP_CLOSE;
+ llc_ui->core_sk = NULL;
+ }
+ sk->state_change(sk);
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_conf_data - handle DATA confirm.
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle DATA confirm.
+ */
+static void llc_ui_conf_data(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_data *prim_data = &prim->data->data;
+ struct sock* sk = llc_sk(prim_data->sk)->handler;
+
+ if (sk)
+ wake_up(sk->sleep);
+}
+
+/**
+ * llc_ui_conf_disc - handle DISC confirm.
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * handle DISC confirm.
+ */
+static void llc_ui_conf_disc(struct llc_prim_if_block *prim)
+{
+ struct llc_prim_disc *prim_data = &prim->data->disc;
+ struct sock* sk = llc_sk(prim_data->sk)->handler;
+
+ if (!sk)
+ goto out;
+ sock_hold(sk);
+ if (sk->type != SOCK_STREAM || sk->state != TCP_CLOSING)
+ goto out_put;
+ llc_ui_sk(sk)->core_sk = NULL;
+ sk->socket->state = SS_UNCONNECTED;
+ sk->state = TCP_CLOSE;
+ sk->state_change(sk);
+out_put:
+ sock_put(sk);
+out:;
+}
+
+/**
+ * llc_ui_confirm - LLC user interface hook into the LLC layer
+ * @prim: Primitive block provided by the llc layer.
+ *
+ * LLC user interface hook into the LLC layer, every llc_ui sap references
+ * this function as its confirm handler.
+ * Always returns 0 to indicate reception of primitive.
+ */
+static int llc_ui_confirm(struct llc_prim_if_block *prim)
+{
+ switch (prim->prim) {
+ case LLC_CONN_PRIM:
+ llc_ui_conf_conn(prim); break;
+ case LLC_DATA_PRIM:
+ llc_ui_conf_data(prim); break;
+ case LLC_DISC_PRIM:
+ llc_ui_conf_disc(prim); break;
+ case LLC_RESET_PRIM: break;
+ default:
+ printk(KERN_ERR __FUNCTION__ ": unknown prim %d\n",
+ prim->prim);
+ break;
+ }
+ return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+/**
+ * llc_ui_get_info - return info to procfs
+ * @buffer: where to put the formatted output
+ * @start: starting from
+ * @offset: offset into buffer.
+ * @length: size of the buffer
+ *
+ * Get the output of the local llc ui socket list to the caller.
+ * Returns the length of data wrote to buffer.
+ */
+static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
+{
+ off_t pos = 0;
+ off_t begin = 0;
+ struct sock *s;
+ int len = sprintf(buffer, "SocketID SKt Mc local_mac_sap\t "
+ "remote_mac_sap\t tx_queue rx_queue st uid "
+ "link_no\n");
+ /* Output the LLC socket data for the /proc filesystem */
+ read_lock_bh(&llc_ui_sockets_lock);
+ for (s = llc_ui_sockets; s; s = s->next) {
+ struct llc_ui_opt *llc_ui = llc_ui_sk(s);
+ len += sprintf(buffer + len, "%p %02X %02X ", s, s->type,
+ !llc_ui_mac_null(llc_ui->addr.sllc_mmac));
+ if (llc_ui->sap) {
+ if (llc_ui->dev &&
+ llc_ui_mac_null(llc_ui->addr.sllc_mmac))
+ len += sprintf(buffer + len,
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ llc_ui->dev->dev_addr[0],
+ llc_ui->dev->dev_addr[1],
+ llc_ui->dev->dev_addr[2],
+ llc_ui->dev->dev_addr[3],
+ llc_ui->dev->dev_addr[4],
+ llc_ui->dev->dev_addr[5]);
+ else {
+ if (!llc_ui_mac_null(llc_ui->addr.sllc_mmac))
+ len += sprintf(buffer + len,
+ "%02X:%02X:%02X:%02X:%02X:%02X",
+ llc_ui->addr.sllc_mmac[0],
+ llc_ui->addr.sllc_mmac[1],
+ llc_ui->addr.sllc_mmac[2],
+ llc_ui->addr.sllc_mmac[3],
+ llc_ui->addr.sllc_mmac[4],
+ llc_ui->addr.sllc_mmac[5]);
+ else
+ len += sprintf(buffer + len,
+ "00:00:00:00:00:00");
+ }
+ len += sprintf(buffer + len, "@%02X ",
+ llc_ui->sap->laddr.lsap);
+ } else
+ len += sprintf(buffer + len, "00:00:00:00:00:00@00 ");
+ len += sprintf(buffer + len,
+ "%02X:%02X:%02X:%02X:%02X:%02X@%02X "
+ "%08X:%08X %02X %-3d ",
+ llc_ui->addr.sllc_dmac[0],
+ llc_ui->addr.sllc_dmac[1],
+ llc_ui->addr.sllc_dmac[2],
+ llc_ui->addr.sllc_dmac[3],
+ llc_ui->addr.sllc_dmac[4],
+ llc_ui->addr.sllc_dmac[5],
+ llc_ui->addr.sllc_dsap,
+ atomic_read(&s->wmem_alloc),
+ atomic_read(&s->rmem_alloc), s->state,
+ SOCK_INODE(s->socket)->i_uid);
+ if (llc_ui->core_sk)
+ len += sprintf(buffer + len, "%-7d\n",
+ llc_sk(llc_ui->core_sk)->link);
+ else
+ len += sprintf(buffer + len, "no_link\n");
+ /* Are we still dumping unwanted data then discard the record */
+ pos = begin + len;
+
+ if (pos < offset) {
+ len = 0; /* Keep dumping into the buffer start */
+ begin = pos;
+ }
+ if (pos > offset + length) /* We have dumped enough */
+ break;
+ }
+ read_unlock_bh(&llc_ui_sockets_lock);
+
+ /* The data in question runs from begin to begin + len */
+ *start = buffer + offset - begin; /* Start of wanted data */
+ len -= offset - begin; /* Remove unwanted header data from length */
+ if (len > length)
+ len = length; /* Remove unwanted tail data from length */
+ return len;
+}
+#endif /* CONFIG_PROC_FS */
+
+static struct net_proto_family llc_ui_family_ops = {
+ .family = PF_LLC,
+ .create = llc_ui_create,
+};
+
+static struct proto_ops SOCKOPS_WRAPPED(llc_ui_ops) = {
+ .family = PF_LLC,
+ .release = llc_ui_release,
+ .bind = llc_ui_bind,
+ .connect = llc_ui_connect,
+ .socketpair = sock_no_socketpair,
+ .accept = llc_ui_accept,
+ .getname = llc_ui_getname,
+ .poll = datagram_poll,
+ .ioctl = llc_ui_ioctl,
+ .listen = llc_ui_listen,
+ .shutdown = llc_ui_shutdown,
+ .setsockopt = llc_ui_setsockopt,
+ .getsockopt = llc_ui_getsockopt,
+ .sendmsg = llc_ui_sendmsg,
+ .recvmsg = llc_ui_recvmsg,
+ .mmap = sock_no_mmap,
+ .sendpage = sock_no_sendpage,
+};
+
+#include <linux/smp_lock.h>
+SOCKOPS_WRAP(llc_ui, PF_LLC);
+
+static char llc_ui_banner[] __initdata =
+ KERN_INFO "NET4.0 IEEE 802.2 User Interface SAPs, Jay Schulist, 2001\n";
+
+int __init llc_ui_init(void)
+{
+ llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
+ sock_register(&llc_ui_family_ops);
+ proc_net_create("llc", 0, llc_ui_get_info);
+ printk(llc_ui_banner);
+ return 0;
+}
+
+void __exit llc_ui_exit(void)
+{
+ proc_net_remove("llc");
+ sock_unregister(PF_LLC);
+}
diff --git a/net/llc/llc_stat.c b/net/llc/llc_stat.c
new file mode 100644
index 000000000000..7e2e89cd4e57
--- /dev/null
+++ b/net/llc/llc_stat.c
@@ -0,0 +1,218 @@
+/*
+ * llc_stat.c - Implementation of LLC station component state machine
+ * transitions
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/types.h>
+#include <net/llc_if.h>
+#include <net/llc_sap.h>
+#include <net/llc_evnt.h>
+#include <net/llc_actn.h>
+#include <net/llc_stat.h>
+
+/* COMMON STATION STATE transitions */
+
+/* dummy last-transition indicator; common to all state transition groups
+ * last entry for this state
+ * all members are zeros, .bss zeroes it
+ */
+static struct llc_station_state_trans llc_stat_state_trans_n;
+
+/* DOWN STATE transitions */
+
+/* state transition for LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK event */
+static llc_station_action_t llc_stat_down_state_actions_1[] = {
+ [0] = llc_station_ac_start_ack_timer,
+ [1] = llc_station_ac_set_retry_cnt_0,
+ [2] = llc_station_ac_set_xid_r_cnt_0,
+ [3] = llc_station_ac_send_null_dsap_xid_c,
+ [4] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_down_state_trans_1 = {
+ .ev = llc_stat_ev_enable_with_dup_addr_check,
+ .next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
+ .ev_actions = llc_stat_down_state_actions_1,
+};
+
+/* state transition for LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK event */
+static llc_station_action_t llc_stat_down_state_actions_2[] = {
+ [0] = llc_station_ac_report_status, /* STATION UP */
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_down_state_trans_2 = {
+ .ev = llc_stat_ev_enable_without_dup_addr_check,
+ .next_state = LLC_STATION_STATE_UP,
+ .ev_actions = llc_stat_down_state_actions_2,
+};
+
+/* array of pointers; one to each transition */
+static struct llc_station_state_trans *llc_stat_dwn_state_trans[] = {
+ [0] = &llc_stat_down_state_trans_1,
+ [1] = &llc_stat_down_state_trans_2,
+ [2] = &llc_stat_state_trans_n,
+};
+
+/* UP STATE transitions */
+/* state transition for LLC_STATION_EV_DISABLE_REQ event */
+static llc_station_action_t llc_stat_up_state_actions_1[] = {
+ [0] = llc_station_ac_report_status, /* STATION DOWN */
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_up_state_trans_1 = {
+ .ev = llc_stat_ev_disable_req,
+ .next_state = LLC_STATION_STATE_DOWN,
+ .ev_actions = llc_stat_up_state_actions_1,
+};
+
+/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */
+static llc_station_action_t llc_stat_up_state_actions_2[] = {
+ [0] = llc_station_ac_send_xid_r,
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_up_state_trans_2 = {
+ .ev = llc_stat_ev_rx_null_dsap_xid_c,
+ .next_state = LLC_STATION_STATE_UP,
+ .ev_actions = llc_stat_up_state_actions_2,
+};
+
+/* state transition for LLC_STATION_EV_RX_NULL_DSAP_TEST_C event */
+static llc_station_action_t llc_stat_up_state_actions_3[] = {
+ [0] = llc_station_ac_send_test_r,
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_up_state_trans_3 = {
+ .ev = llc_stat_ev_rx_null_dsap_test_c,
+ .next_state = LLC_STATION_STATE_UP,
+ .ev_actions = llc_stat_up_state_actions_3,
+};
+
+/* array of pointers; one to each transition */
+static struct llc_station_state_trans *llc_stat_up_state_trans [] = {
+ [0] = &llc_stat_up_state_trans_1,
+ [1] = &llc_stat_up_state_trans_2,
+ [2] = &llc_stat_up_state_trans_3,
+ [3] = &llc_stat_state_trans_n,
+};
+
+/* DUP ADDR CHK STATE transitions */
+/* state transition for LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ
+ * event
+ */
+static llc_station_action_t llc_stat_dupaddr_state_actions_1[] = {
+ [0] = llc_station_ac_inc_xid_r_cnt_by_1,
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_dupaddr_state_trans_1 = {
+ .ev = llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq,
+ .next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
+ .ev_actions = llc_stat_dupaddr_state_actions_1,
+};
+
+/* state transition for LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ
+ * event
+ */
+static llc_station_action_t llc_stat_dupaddr_state_actions_2[] = {
+ [0] = llc_station_ac_report_status, /* DUPLICATE ADDRESS FOUND */
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_dupaddr_state_trans_2 = {
+ .ev = llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq,
+ .next_state = LLC_STATION_STATE_DOWN,
+ .ev_actions = llc_stat_dupaddr_state_actions_2,
+};
+
+/* state transition for LLC_STATION_EV_RX_NULL_DSAP_XID_C event */
+static llc_station_action_t llc_stat_dupaddr_state_actions_3[] = {
+ [0] = llc_station_ac_send_xid_r,
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_dupaddr_state_trans_3 = {
+ .ev = llc_stat_ev_rx_null_dsap_xid_c,
+ .next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
+ .ev_actions = llc_stat_dupaddr_state_actions_3,
+};
+
+/* state transition for LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY
+ * event
+ */
+static llc_station_action_t llc_stat_dupaddr_state_actions_4[] = {
+ [0] = llc_station_ac_start_ack_timer,
+ [1] = llc_station_ac_inc_retry_cnt_by_1,
+ [2] = llc_station_ac_set_xid_r_cnt_0,
+ [3] = llc_station_ac_send_null_dsap_xid_c,
+ [4] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_dupaddr_state_trans_4 = {
+ .ev = llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry,
+ .next_state = LLC_STATION_STATE_DUP_ADDR_CHK,
+ .ev_actions = llc_stat_dupaddr_state_actions_4
+};
+
+/* state transition for LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY
+ * event
+ */
+static llc_station_action_t llc_stat_dupaddr_state_actions_5[] = {
+ [0] = llc_station_ac_report_status, /* STATION UP */
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_dupaddr_state_trans_5 = {
+ .ev = llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry,
+ .next_state = LLC_STATION_STATE_UP,
+ .ev_actions = llc_stat_dupaddr_state_actions_5,
+};
+
+/* state transition for LLC_STATION_EV_DISABLE_REQ event */
+static llc_station_action_t llc_stat_dupaddr_state_actions_6[] = {
+ [0] = llc_station_ac_report_status, /* STATION DOWN */
+ [1] = NULL,
+};
+
+static struct llc_station_state_trans llc_stat_dupaddr_state_trans_6 = {
+ .ev = llc_stat_ev_disable_req,
+ .next_state = LLC_STATION_STATE_DOWN,
+ .ev_actions = llc_stat_dupaddr_state_actions_6,
+};
+
+/* array of pointers; one to each transition */
+static struct llc_station_state_trans *llc_stat_dupaddr_state_trans[] = {
+ [0] = &llc_stat_dupaddr_state_trans_6, /* Request */
+ [1] = &llc_stat_dupaddr_state_trans_4, /* Timer */
+ [2] = &llc_stat_dupaddr_state_trans_5,
+ [3] = &llc_stat_dupaddr_state_trans_1, /* Receive frame */
+ [4] = &llc_stat_dupaddr_state_trans_2,
+ [5] = &llc_stat_dupaddr_state_trans_3,
+ [6] = &llc_stat_state_trans_n
+};
+
+struct llc_station_state llc_station_state_table[LLC_NBR_STATION_STATES] = {
+ {
+ .curr_state = LLC_STATION_STATE_DOWN,
+ .transitions = llc_stat_dwn_state_trans,
+ },
+ {
+ .curr_state = LLC_STATION_STATE_DUP_ADDR_CHK,
+ .transitions = llc_stat_dupaddr_state_trans,
+ },
+ {
+ .curr_state = LLC_STATION_STATE_UP,
+ .transitions = llc_stat_up_state_trans,
+ }
+};
diff --git a/net/netsyms.c b/net/netsyms.c
index f27ec8319217..658dca434a79 100644
--- a/net/netsyms.c
+++ b/net/netsyms.c
@@ -444,6 +444,7 @@ EXPORT_SYMBOL(arp_find);
#endif /* CONFIG_INET */
#ifdef CONFIG_TR
+EXPORT_SYMBOL(tr_source_route);
EXPORT_SYMBOL(tr_type_trans);
#endif
@@ -462,6 +463,7 @@ EXPORT_SYMBOL(dev_get_by_index);
EXPORT_SYMBOL(__dev_get_by_index);
EXPORT_SYMBOL(dev_get_by_name);
EXPORT_SYMBOL(__dev_get_by_name);
+EXPORT_SYMBOL(dev_getbyhwaddr);
EXPORT_SYMBOL(netdev_finish_unregister);
EXPORT_SYMBOL(netdev_set_master);
EXPORT_SYMBOL(eth_type_trans);