summaryrefslogtreecommitdiff
path: root/net/llc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-17 02:20:36 +0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-17 02:20:36 +0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/llc
downloadlinux-1da177e4c3f41524e886b7f1b8a0c1fc7321cac2.tar.xz
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'net/llc')
-rw-r--r--net/llc/Kconfig10
-rw-r--r--net/llc/Makefile24
-rw-r--r--net/llc/af_llc.c1079
-rw-r--r--net/llc/llc_c_ac.c1514
-rw-r--r--net/llc/llc_c_ev.c769
-rw-r--r--net/llc/llc_c_st.c4946
-rw-r--r--net/llc/llc_conn.c915
-rw-r--r--net/llc/llc_core.c179
-rw-r--r--net/llc/llc_if.c157
-rw-r--r--net/llc/llc_input.c189
-rw-r--r--net/llc/llc_output.c107
-rw-r--r--net/llc/llc_output.h20
-rw-r--r--net/llc/llc_pdu.c372
-rw-r--r--net/llc/llc_proc.c267
-rw-r--r--net/llc/llc_s_ac.c205
-rw-r--r--net/llc/llc_s_ev.c115
-rw-r--r--net/llc/llc_s_st.c183
-rw-r--r--net/llc/llc_sap.c316
-rw-r--r--net/llc/llc_station.c713
19 files changed, 12080 insertions, 0 deletions
diff --git a/net/llc/Kconfig b/net/llc/Kconfig
new file mode 100644
index 000000000000..b91c65108162
--- /dev/null
+++ b/net/llc/Kconfig
@@ -0,0 +1,10 @@
+config LLC
+ tristate
+ depends on NET
+
+config LLC2
+ tristate "ANSI/IEEE 802.2 LLC type 2 Support"
+ select LLC
+ help
+ This is a Logical Link Layer type 2, connection oriented support.
+ Select this if you want to have support for PF_LLC sockets.
diff --git a/net/llc/Makefile b/net/llc/Makefile
new file mode 100644
index 000000000000..5ebd4ed2bd42
--- /dev/null
+++ b/net/llc/Makefile
@@ -0,0 +1,24 @@
+###########################################################################
+# Makefile for the Linux 802.2 LLC (fully-functional) layer.
+#
+# Copyright (c) 1997 by Procom Technology,Inc.
+# 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+#
+# This program can be redistributed or modified under the terms of the
+# GNU General Public License as published by the Free Software Foundation.
+# This program is distributed without any warranty or implied warranty
+# of merchantability or fitness for a particular purpose.
+#
+# See the GNU General Public License for more details.
+###########################################################################
+
+obj-$(CONFIG_LLC) += llc.o
+
+llc-y := llc_core.o llc_input.o llc_output.o
+
+obj-$(CONFIG_LLC2) += llc2.o
+
+llc2-y := llc_if.o llc_c_ev.o llc_c_ac.o llc_conn.o llc_c_st.o llc_pdu.o \
+ llc_sap.o llc_s_ac.o llc_s_ev.o llc_s_st.o af_llc.o llc_station.o
+
+llc2-$(CONFIG_PROC_FS) += llc_proc.o
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
new file mode 100644
index 000000000000..20b4cfebd74c
--- /dev/null
+++ b/net/llc/af_llc.c
@@ -0,0 +1,1079 @@
+/*
+ * af_llc.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>
+ * 2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/tcp.h>
+#include <linux/rtnetlink.h>
+#include <linux/init.h>
+#include <net/llc.h>
+#include <net/llc_sap.h>
+#include <net/llc_pdu.h>
+#include <net/llc_conn.h>
+
+/* 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 struct sockaddr_llc llc_ui_addrnull;
+static struct proto_ops llc_ui_ops;
+
+static int llc_ui_wait_for_conn(struct sock *sk, int timeout);
+static int llc_ui_wait_for_disc(struct sock *sk, int timeout);
+static int llc_ui_wait_for_data(struct sock *sk, int timeout);
+static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout);
+
+#if 0
+#define dprintk(args...) printk(KERN_DEBUG args)
+#else
+#define dprintk(args...)
+#endif
+
+/**
+ * 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_proto_type - return eth protocol for ARP header type
+ * @arphrd: ARP header type.
+ *
+ * Given an ARP header type return the corresponding ethernet protocol.
+ */
+static __inline__ u16 llc_proto_type(u16 arphrd)
+{
+ return arphrd == ARPHRD_IEEE802_TR ?
+ htons(ETH_P_TR_802_2) : htons(ETH_P_802_2);
+}
+
+/**
+ * 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_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->sk_type == SOCK_STREAM)
+ rc = LLC_PDU_LEN_I;
+ return rc;
+}
+
+/**
+ * llc_ui_send_data - send data via reliable llc2 connection
+ * @sk: Connection the socket is using.
+ * @skb: Data the user wishes to send.
+ * @addr: Source and destination fields provided by the user.
+ * @noblock: can we block waiting for data?
+ *
+ * Send data via reliable llc2 connection.
+ * Returns 0 upon success, non-zero if action did not succeed.
+ */
+static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
+{
+ struct llc_sock* llc = llc_sk(sk);
+ int rc = 0;
+
+ if (llc_data_accept_state(llc->state) || llc->p_flag) {
+ int timeout = sock_sndtimeo(sk, noblock);
+
+ rc = llc_ui_wait_for_busy_core(sk, timeout);
+ }
+ if (!rc)
+ rc = llc_build_and_send_pkt(sk, skb);
+ return rc;
+}
+
+static void llc_ui_sk_init(struct socket *sock, struct sock *sk)
+{
+ sk->sk_type = sock->type;
+ sk->sk_sleep = &sock->wait;
+ sk->sk_socket = sock;
+ sock->sk = sk;
+ sock->ops = &llc_ui_ops;
+}
+
+static struct proto llc_proto = {
+ .name = "DDP",
+ .owner = THIS_MODULE,
+ .obj_size = sizeof(struct llc_sock),
+};
+
+/**
+ * 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;
+ int rc = -ESOCKTNOSUPPORT;
+
+ if (sock->type == SOCK_DGRAM || sock->type == SOCK_STREAM) {
+ rc = -ENOMEM;
+ sk = llc_sk_alloc(PF_LLC, GFP_KERNEL, &llc_proto);
+ if (sk) {
+ rc = 0;
+ llc_ui_sk_init(sock, sk);
+ }
+ }
+ return rc;
+}
+
+/**
+ * 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_sock *llc;
+
+ if (!sk)
+ goto out;
+ sock_hold(sk);
+ lock_sock(sk);
+ llc = llc_sk(sk);
+ dprintk("%s: closing local(%02X) remote(%02X)\n", __FUNCTION__,
+ llc->laddr.lsap, llc->daddr.lsap);
+ if (!llc_send_disc(sk))
+ llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
+ if (!sock_flag(sk, SOCK_ZAPPED))
+ llc_sap_remove_socket(llc->sap, sk);
+ release_sock(sk);
+ if (llc->sap && hlist_empty(&llc->sap->sk_list.list)) {
+ llc_release_sockets(llc->sap);
+ llc_sap_close(llc->sap);
+ }
+ if (llc->dev)
+ dev_put(llc->dev);
+ sock_put(sk);
+ llc_sk_free(sk);
+out:
+ return 0;
+}
+
+/**
+ * llc_ui_autoport - provide dynamically allocate SAP number
+ *
+ * Provide the caller with a dynamically 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_sap_find(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_sock *llc = llc_sk(sk);
+ struct llc_sap *sap;
+ int rc = -EINVAL;
+
+ if (!sock_flag(sk, SOCK_ZAPPED))
+ goto out;
+ rc = -ENODEV;
+ llc->dev = dev_getfirstbyhwtype(addr->sllc_arphrd);
+ if (!llc->dev)
+ goto out;
+ rc = -EUSERS;
+ llc->laddr.lsap = llc_ui_autoport();
+ if (!llc->laddr.lsap)
+ goto out;
+ rc = -EBUSY; /* some other network layer is using the sap */
+ sap = llc_sap_open(llc->laddr.lsap, NULL);
+ if (!sap)
+ goto out;
+ memcpy(llc->laddr.mac, llc->dev->dev_addr, IFHWADDRLEN);
+ memcpy(&llc->addr, addr, sizeof(llc->addr));
+ /* assign new connection to its SAP */
+ llc_sap_add_socket(sap, sk);
+ sock_reset_flag(sk, SOCK_ZAPPED);
+ rc = 0;
+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;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap;
+ int rc = -EINVAL;
+
+ dprintk("%s: binding %02X\n", __FUNCTION__, addr->sllc_sap);
+ if (!sock_flag(sk, SOCK_ZAPPED) || addrlen != sizeof(*addr))
+ goto out;
+ rc = -EAFNOSUPPORT;
+ if (addr->sllc_family != AF_LLC)
+ goto out;
+ if (!addr->sllc_sap) {
+ rc = -EUSERS;
+ addr->sllc_sap = llc_ui_autoport();
+ if (!addr->sllc_sap)
+ goto out;
+ }
+ sap = llc_sap_find(addr->sllc_sap);
+ if (!sap) {
+ sap = llc_sap_open(addr->sllc_sap, NULL);
+ rc = -EBUSY; /* some other network layer is using the sap */
+ if (!sap)
+ goto out;
+ } else {
+ struct llc_addr laddr, daddr;
+ struct sock *ask;
+
+ memset(&laddr, 0, sizeof(laddr));
+ memset(&daddr, 0, sizeof(daddr));
+ /*
+ * FIXME: check if the the address is multicast,
+ * only SOCK_DGRAM can do this.
+ */
+ memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
+ laddr.lsap = addr->sllc_sap;
+ rc = -EADDRINUSE; /* mac + sap clash. */
+ ask = llc_lookup_established(sap, &daddr, &laddr);
+ if (ask) {
+ sock_put(ask);
+ goto out;
+ }
+ }
+ llc->laddr.lsap = addr->sllc_sap;
+ memcpy(llc->laddr.mac, addr->sllc_mac, IFHWADDRLEN);
+ memcpy(&llc->addr, addr, sizeof(llc->addr));
+ /* assign new connection to its SAP */
+ llc_sap_add_socket(sap, sk);
+ sock_reset_flag(sk, SOCK_ZAPPED);
+ rc = 0;
+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->sk_state != TCP_ESTABLISHED)
+ goto out;
+ rc = -EINVAL;
+ if (how != 2)
+ goto out;
+ rc = llc_send_disc(sk);
+ if (!rc)
+ rc = llc_ui_wait_for_disc(sk, sk->sk_rcvtimeo);
+ /* Wake up anyone sleeping in poll */
+ sk->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 hasn't previously
+ * called bind(2) with a smac the address of the first interface of the
+ * specified arp type will be used.
+ * 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_sock *llc = llc_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 (sock_flag(sk, SOCK_ZAPPED)) {
+ /* bind to sap with null dev, exclusive */
+ rc = llc_ui_autobind(sock, addr);
+ if (rc)
+ goto out;
+ llc->daddr.lsap = addr->sllc_sap;
+ memcpy(llc->daddr.mac, addr->sllc_mac, IFHWADDRLEN);
+ }
+ dev = llc->dev;
+ if (sk->sk_type != SOCK_STREAM)
+ goto out;
+ rc = -EALREADY;
+ if (sock->state == SS_CONNECTING)
+ goto out;
+ sock->state = SS_CONNECTING;
+ sk->sk_state = TCP_SYN_SENT;
+ llc->link = llc_ui_next_link_no(llc->sap->laddr.lsap);
+ rc = llc_establish_connection(sk, dev->dev_addr,
+ addr->sllc_mac, addr->sllc_sap);
+ if (rc) {
+ dprintk("%s: llc_ui_send_conn failed :-(\n", __FUNCTION__);
+ sock->state = SS_UNCONNECTED;
+ sk->sk_state = TCP_CLOSE;
+ goto out;
+ }
+ rc = llc_ui_wait_for_conn(sk, sk->sk_rcvtimeo);
+ if (rc)
+ dprintk("%s: llc_ui_wait_for_conn failed=%d\n", __FUNCTION__, rc);
+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->sk_type != SOCK_STREAM)
+ goto out;
+ rc = -EAGAIN;
+ if (sock_flag(sk, SOCK_ZAPPED))
+ goto out;
+ rc = 0;
+ if (!(unsigned)backlog) /* BSDism */
+ backlog = 1;
+ sk->sk_max_ack_backlog = backlog;
+ if (sk->sk_state != TCP_LISTEN) {
+ sk->sk_ack_backlog = 0;
+ sk->sk_state = TCP_LISTEN;
+ }
+ sk->sk_socket->flags |= __SO_ACCEPTCON;
+out:
+ release_sock(sk);
+ return rc;
+}
+
+static int llc_ui_wait_for_disc(struct sock *sk, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int rc;
+
+ add_wait_queue_exclusive(sk->sk_sleep, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ rc = 0;
+ if (sk->sk_state != TCP_CLOSE) {
+ release_sock(sk);
+ timeout = schedule_timeout(timeout);
+ lock_sock(sk);
+ } else
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ rc = -EAGAIN;
+ if (!timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sk_sleep, &wait);
+ return rc;
+}
+
+static int llc_ui_wait_for_conn(struct sock *sk, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int rc;
+
+ add_wait_queue_exclusive(sk->sk_sleep, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ rc = -EAGAIN;
+ if (sk->sk_state == TCP_CLOSE)
+ break;
+ rc = 0;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ release_sock(sk);
+ timeout = schedule_timeout(timeout);
+ lock_sock(sk);
+ } else
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ rc = -EAGAIN;
+ if (!timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sk_sleep, &wait);
+ return rc;
+}
+
+static int llc_ui_wait_for_data(struct sock *sk, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ int rc = 0;
+
+ add_wait_queue_exclusive(sk->sk_sleep, &wait);
+ for (;;) {
+ __set_current_state(TASK_INTERRUPTIBLE);
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ break;
+ /*
+ * Well, if we have backlog, try to process it now.
+ */
+ if (sk->sk_backlog.tail) {
+ release_sock(sk);
+ lock_sock(sk);
+ }
+ rc = 0;
+ if (skb_queue_empty(&sk->sk_receive_queue)) {
+ release_sock(sk);
+ timeout = schedule_timeout(timeout);
+ lock_sock(sk);
+ } else
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ rc = -EAGAIN;
+ if (!timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->sk_sleep, &wait);
+ return rc;
+}
+
+static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct llc_sock *llc = llc_sk(sk);
+ int rc;
+
+ add_wait_queue_exclusive(sk->sk_sleep, &wait);
+ for (;;) {
+ dprintk("%s: looping...\n", __FUNCTION__);
+ __set_current_state(TASK_INTERRUPTIBLE);
+ rc = -ENOTCONN;
+ if (sk->sk_shutdown & RCV_SHUTDOWN)
+ break;
+ rc = 0;
+ if (llc_data_accept_state(llc->state) || llc->p_flag) {
+ release_sock(sk);
+ timeout = schedule_timeout(timeout);
+ lock_sock(sk);
+ } else
+ break;
+ rc = -ERESTARTSYS;
+ if (signal_pending(current))
+ break;
+ rc = -EAGAIN;
+ if (!timeout)
+ break;
+ }
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(sk->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_sock *llc, *newllc;
+ struct sk_buff *skb;
+ int rc = -EOPNOTSUPP;
+
+ dprintk("%s: accepting on %02X\n", __FUNCTION__,
+ llc_sk(sk)->laddr.lsap);
+ lock_sock(sk);
+ if (sk->sk_type != SOCK_STREAM)
+ goto out;
+ rc = -EINVAL;
+ if (sock->state != SS_UNCONNECTED || sk->sk_state != TCP_LISTEN)
+ goto out;
+ /* wait for a connection to arrive. */
+ rc = llc_ui_wait_for_data(sk, sk->sk_rcvtimeo);
+ if (rc)
+ goto out;
+ dprintk("%s: got a new connection on %02X\n", __FUNCTION__,
+ llc_sk(sk)->laddr.lsap);
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ rc = -EINVAL;
+ if (!skb->sk)
+ goto frees;
+ rc = 0;
+ newsk = skb->sk;
+ /* attach connection to a new socket. */
+ llc_ui_sk_init(newsock, newsk);
+ sock_reset_flag(newsk, SOCK_ZAPPED);
+ newsk->sk_state = TCP_ESTABLISHED;
+ newsock->state = SS_CONNECTED;
+ llc = llc_sk(sk);
+ newllc = llc_sk(newsk);
+ memcpy(&newllc->addr, &llc->addr, sizeof(newllc->addr));
+ newllc->link = llc_ui_next_link_no(newllc->laddr.lsap);
+
+ /* put original socket back into a clean listen state. */
+ sk->sk_state = TCP_LISTEN;
+ sk->sk_ack_backlog--;
+ skb->sk = NULL;
+ dprintk("%s: ok success on %02X, client on %02X\n", __FUNCTION__,
+ llc_sk(sk)->addr.sllc_sap, newllc->daddr.lsap);
+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.
+ *
+ * Copy received data to the socket user.
+ * Returns non-negative upon success, negative otherwise.
+ */
+static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t size, int flags)
+{
+ struct sock *sk = sock->sk;
+ struct sockaddr_llc *uaddr = (struct sockaddr_llc *)msg->msg_name;
+ struct sk_buff *skb;
+ size_t copied = 0;
+ int rc = -ENOMEM, timeout;
+ int noblock = flags & MSG_DONTWAIT;
+
+ dprintk("%s: receiving in %02X from %02X\n", __FUNCTION__,
+ llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
+ lock_sock(sk);
+ timeout = sock_rcvtimeo(sk, noblock);
+ rc = llc_ui_wait_for_data(sk, timeout);
+ if (rc) {
+ dprintk("%s: llc_ui_wait_for_data failed recv "
+ "in %02X from %02X\n", __FUNCTION__,
+ llc_sk(sk)->laddr.lsap, llc_sk(sk)->daddr.lsap);
+ goto out;
+ }
+ skb = skb_dequeue(&sk->sk_receive_queue);
+ if (!skb) /* shutdown */
+ goto out;
+ copied = skb->len;
+ if (copied > size)
+ copied = size;
+ rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+ if (rc)
+ goto dgram_free;
+ if (skb->len > copied) {
+ skb_pull(skb, copied);
+ skb_queue_head(&sk->sk_receive_queue, skb);
+ }
+ if (uaddr)
+ memcpy(uaddr, llc_ui_skb_cb(skb), sizeof(*uaddr));
+ msg->msg_namelen = sizeof(*uaddr);
+ if (!skb->list) {
+dgram_free:
+ kfree_skb(skb);
+ }
+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.
+ *
+ * Transmit data provided by the socket user.
+ * Returns non-negative upon success, negative otherwise.
+ */
+static int llc_ui_sendmsg(struct kiocb *iocb, struct socket *sock,
+ struct msghdr *msg, size_t len)
+{
+ struct sock *sk = sock->sk;
+ struct llc_sock *llc = llc_sk(sk);
+ struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
+ int flags = msg->msg_flags;
+ int noblock = flags & MSG_DONTWAIT;
+ struct net_device *dev;
+ struct sk_buff *skb;
+ size_t size = 0;
+ int rc = -EINVAL, copied = 0, hdrlen;
+
+ dprintk("%s: sending from %02X to %02X\n", __FUNCTION__,
+ llc->laddr.lsap, llc->daddr.lsap);
+ lock_sock(sk);
+ if (addr) {
+ if (msg->msg_namelen < sizeof(*addr))
+ goto release;
+ } else {
+ if (llc_ui_addr_null(&llc->addr))
+ goto release;
+ addr = &llc->addr;
+ }
+ /* must bind connection to sap if user hasn't done it. */
+ if (sock_flag(sk, SOCK_ZAPPED)) {
+ /* bind to sap with null dev, exclusive. */
+ rc = llc_ui_autobind(sock, addr);
+ if (rc)
+ goto release;
+ }
+ dev = llc->dev;
+ hdrlen = dev->hard_header_len + llc_ui_header_len(sk, addr);
+ size = hdrlen + len;
+ if (size > dev->mtu)
+ size = dev->mtu;
+ copied = size - hdrlen;
+ release_sock(sk);
+ skb = sock_alloc_send_skb(sk, size, noblock, &rc);
+ lock_sock(sk);
+ if (!skb)
+ goto release;
+ skb->sk = sk;
+ skb->dev = dev;
+ skb->protocol = llc_proto_type(addr->sllc_arphrd);
+ skb_reserve(skb, hdrlen);
+ rc = memcpy_fromiovec(skb_put(skb, copied), msg->msg_iov, copied);
+ if (rc)
+ goto out;
+ if (sk->sk_type == SOCK_DGRAM || addr->sllc_ua) {
+ llc_build_and_send_ui_pkt(llc->sap, skb, addr->sllc_mac,
+ addr->sllc_sap);
+ goto out;
+ }
+ if (addr->sllc_test) {
+ llc_build_and_send_test_pkt(llc->sap, skb, addr->sllc_mac,
+ addr->sllc_sap);
+ goto out;
+ }
+ if (addr->sllc_xid) {
+ llc_build_and_send_xid_pkt(llc->sap, skb, addr->sllc_mac,
+ addr->sllc_sap);
+ goto out;
+ }
+ rc = -ENOPROTOOPT;
+ if (!(sk->sk_type == SOCK_STREAM && !addr->sllc_ua))
+ goto out;
+ rc = llc_ui_send_data(sk, skb, noblock);
+ if (rc)
+ dprintk("%s: llc_ui_send_data failed: %d\n", __FUNCTION__, rc);
+out:
+ if (rc)
+ kfree_skb(skb);
+release:
+ if (rc)
+ dprintk("%s: failed sending from %02X to %02X: %d\n",
+ __FUNCTION__, llc->laddr.lsap, llc->daddr.lsap, rc);
+ release_sock(sk);
+ return rc ? : copied;
+}
+
+/**
+ * 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_sock *llc = llc_sk(sk);
+ int rc = 0;
+
+ lock_sock(sk);
+ if (sock_flag(sk, SOCK_ZAPPED))
+ goto out;
+ *uaddrlen = sizeof(sllc);
+ memset(uaddr, 0, *uaddrlen);
+ if (peer) {
+ rc = -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED)
+ goto out;
+ if(llc->dev)
+ sllc.sllc_arphrd = llc->dev->type;
+ sllc.sllc_sap = llc->daddr.lsap;
+ memcpy(&sllc.sllc_mac, &llc->daddr.mac, IFHWADDRLEN);
+ } else {
+ rc = -EINVAL;
+ if (!llc->sap)
+ goto out;
+ sllc.sllc_sap = llc->sap->laddr.lsap;
+
+ if (llc->dev) {
+ sllc.sllc_arphrd = llc->dev->type;
+ memcpy(&sllc.sllc_mac, &llc->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 __user *)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 __user *optval, int optlen)
+{
+ struct sock *sk = sock->sk;
+ struct llc_sock *llc = llc_sk(sk);
+ int rc = -EINVAL, opt;
+
+ lock_sock(sk);
+ if (level != SOL_LLC || optlen != sizeof(int))
+ goto out;
+ rc = get_user(opt, (int __user *)optval);
+ if (rc)
+ goto out;
+ rc = -EINVAL;
+ switch (optname) {
+ case LLC_OPT_RETRY:
+ if (opt > LLC_OPT_MAX_RETRY)
+ goto out;
+ llc->n2 = opt;
+ break;
+ case LLC_OPT_SIZE:
+ if (opt > LLC_OPT_MAX_SIZE)
+ goto out;
+ llc->n1 = opt;
+ break;
+ case LLC_OPT_ACK_TMR_EXP:
+ if (opt > LLC_OPT_MAX_ACK_TMR_EXP)
+ goto out;
+ llc->ack_timer.expire = opt;
+ break;
+ case LLC_OPT_P_TMR_EXP:
+ if (opt > LLC_OPT_MAX_P_TMR_EXP)
+ goto out;
+ llc->pf_cycle_timer.expire = opt;
+ break;
+ case LLC_OPT_REJ_TMR_EXP:
+ if (opt > LLC_OPT_MAX_REJ_TMR_EXP)
+ goto out;
+ llc->rej_sent_timer.expire = opt;
+ break;
+ case LLC_OPT_BUSY_TMR_EXP:
+ if (opt > LLC_OPT_MAX_BUSY_TMR_EXP)
+ goto out;
+ llc->busy_state_timer.expire = opt;
+ break;
+ case LLC_OPT_TX_WIN:
+ if (opt > LLC_OPT_MAX_WIN)
+ goto out;
+ llc->k = opt;
+ break;
+ case LLC_OPT_RX_WIN:
+ if (opt > LLC_OPT_MAX_WIN)
+ goto out;
+ llc->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 __user *optval, int __user *optlen)
+{
+ struct sock *sk = sock->sk;
+ struct llc_sock *llc = llc_sk(sk);
+ int val = 0, len = 0, rc = -EINVAL;
+
+ lock_sock(sk);
+ if (level != SOL_LLC)
+ goto out;
+ rc = get_user(len, optlen);
+ if (rc)
+ goto out;
+ rc = -EINVAL;
+ if (len != sizeof(int))
+ goto out;
+ switch (optname) {
+ case LLC_OPT_RETRY:
+ val = llc->n2; break;
+ case LLC_OPT_SIZE:
+ val = llc->n1; break;
+ case LLC_OPT_ACK_TMR_EXP:
+ val = llc->ack_timer.expire; break;
+ case LLC_OPT_P_TMR_EXP:
+ val = llc->pf_cycle_timer.expire; break;
+ case LLC_OPT_REJ_TMR_EXP:
+ val = llc->rej_sent_timer.expire; break;
+ case LLC_OPT_BUSY_TMR_EXP:
+ val = llc->busy_state_timer.expire; break;
+ case LLC_OPT_TX_WIN:
+ val = llc->k; break;
+ case LLC_OPT_RX_WIN:
+ val = llc->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;
+}
+
+static struct net_proto_family llc_ui_family_ops = {
+ .family = PF_LLC,
+ .create = llc_ui_create,
+ .owner = THIS_MODULE,
+};
+
+static struct proto_ops llc_ui_ops = {
+ .family = PF_LLC,
+ .owner = THIS_MODULE,
+ .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,
+};
+
+extern void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb);
+extern void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb);
+
+static int __init llc2_init(void)
+{
+ int rc = proto_register(&llc_proto, 0);
+
+ if (rc != 0)
+ goto out;
+
+ llc_build_offset_table();
+ llc_station_init();
+ llc_ui_sap_last_autoport = LLC_SAP_DYN_START;
+ rc = llc_proc_init();
+ if (rc != 0)
+ goto out_unregister_llc_proto;
+ sock_register(&llc_ui_family_ops);
+ llc_add_pack(LLC_DEST_SAP, llc_sap_handler);
+ llc_add_pack(LLC_DEST_CONN, llc_conn_handler);
+out:
+ return rc;
+out_unregister_llc_proto:
+ proto_unregister(&llc_proto);
+ goto out;
+}
+
+static void __exit llc2_exit(void)
+{
+ llc_station_exit();
+ llc_remove_pack(LLC_DEST_SAP);
+ llc_remove_pack(LLC_DEST_CONN);
+ sock_unregister(PF_LLC);
+ llc_proc_exit();
+ proto_unregister(&llc_proto);
+}
+
+module_init(llc2_init);
+module_exit(llc2_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
+MODULE_DESCRIPTION("IEEE 802.2 PF_LLC support");
+MODULE_ALIAS_NETPROTO(PF_LLC);
diff --git a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
new file mode 100644
index 000000000000..b218be4c10ec
--- /dev/null
+++ b/net/llc/llc_c_ac.c
@@ -0,0 +1,1514 @@
+/*
+ * 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-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/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_c_ac.h>
+#include <net/llc_c_st.h>
+#include <net/llc_pdu.h>
+#include <net/llc.h>
+
+#include "llc_output.h"
+
+static int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb);
+static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb);
+static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *ev);
+
+static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb);
+
+static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk,
+ struct sk_buff *skb);
+
+static int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb);
+
+#define INCORRECT 0
+
+int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (llc->remote_busy_flag) {
+ u8 nr;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ llc->remote_busy_flag = 0;
+ del_timer(&llc->busy_state_timer.timer);
+ nr = LLC_I_GET_NR(pdu);
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
+ }
+ return 0;
+}
+
+int llc_conn_ac_conn_ind(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOTCONN;
+ u8 dsap;
+ struct llc_sap *sap;
+
+ llc_pdu_decode_dsap(skb, &dsap);
+ sap = llc_sap_find(dsap);
+ if (sap) {
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc_pdu_decode_sa(skb, llc->daddr.mac);
+ llc_pdu_decode_da(skb, llc->laddr.mac);
+ llc->dev = skb->dev;
+ ev->ind_prim = LLC_CONN_PRIM;
+ rc = 0;
+ }
+ return rc;
+}
+
+int llc_conn_ac_conn_confirm(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->cfm_prim = LLC_CONN_PRIM;
+ return 0;
+}
+
+static int llc_conn_ac_data_confirm(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->cfm_prim = LLC_DATA_PRIM;
+ return 0;
+}
+
+int llc_conn_ac_data_ind(struct sock *sk, struct sk_buff *skb)
+{
+ llc_conn_rtn_pdu(sk, skb);
+ return 0;
+}
+
+int llc_conn_ac_disc_ind(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+ u8 reason = 0;
+ int rc = 0;
+
+ if (ev->type == LLC_CONN_EV_TYPE_PDU) {
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ if (LLC_PDU_IS_RSP(pdu) &&
+ LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM)
+ reason = LLC_DISC_REASON_RX_DM_RSP_PDU;
+ else if (LLC_PDU_IS_CMD(pdu) &&
+ LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC)
+ reason = LLC_DISC_REASON_RX_DISC_CMD_PDU;
+ } else if (ev->type == LLC_CONN_EV_TYPE_ACK_TMR)
+ reason = LLC_DISC_REASON_ACK_TMR_EXP;
+ else {
+ reason = 0;
+ rc = -EINVAL;
+ }
+ if (!rc) {
+ ev->reason = reason;
+ ev->ind_prim = LLC_DISC_PRIM;
+ }
+ return rc;
+}
+
+int llc_conn_ac_disc_confirm(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->reason = ev->status;
+ ev->cfm_prim = LLC_DISC_PRIM;
+ return 0;
+}
+
+int llc_conn_ac_rst_ind(struct sock *sk, struct sk_buff *skb)
+{
+ u8 reason = 0;
+ int rc = 1;
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+ struct llc_sock *llc = llc_sk(sk);
+
+ switch (ev->type) {
+ case LLC_CONN_EV_TYPE_PDU:
+ if (LLC_PDU_IS_RSP(pdu) &&
+ LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR) {
+ reason = LLC_RESET_REASON_LOCAL;
+ rc = 0;
+ } else if (LLC_PDU_IS_CMD(pdu) &&
+ LLC_PDU_TYPE_IS_U(pdu) &&
+ LLC_U_PDU_CMD(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) {
+ ev->reason = reason;
+ ev->ind_prim = LLC_RESET_PRIM;
+ }
+ return rc;
+}
+
+int llc_conn_ac_rst_confirm(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->reason = 0;
+ ev->cfm_prim = LLC_RESET_PRIM;
+ return 0;
+}
+
+int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ if (LLC_PDU_IS_RSP(pdu) &&
+ LLC_PDU_TYPE_IS_I(pdu) &&
+ LLC_I_PF_IS_1(pdu) && llc_sk(sk)->ack_pf)
+ llc_conn_ac_clear_remote_busy(sk, skb);
+ return 0;
+}
+
+int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (llc->data_flag == 2)
+ del_timer(&llc->rej_sent_timer.timer);
+ return 0;
+}
+
+int llc_conn_ac_send_disc_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_disc_cmd(nskb, 1);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ llc_conn_ac_set_p_flag_1(sk, skb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_dm_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit;
+
+ nskb->dev = llc->dev;
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_dm_rsp(nskb, f_bit);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_dm_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_dm_rsp(nskb, f_bit);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, struct sk_buff *skb)
+{
+ u8 f_bit;
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc->rx_pdu_hdr = *((u32 *)pdu);
+ if (LLC_PDU_IS_CMD(pdu))
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ else
+ f_bit = 0;
+ nskb = llc_alloc_frame();
+ if (nskb) {
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
+ llc->vR, INCORRECT);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ u8 f_bit = 0;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
+ llc->vR, INCORRECT);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
+{
+ u8 f_bit;
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb;
+
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ nskb = llc_alloc_frame();
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_frmr_rsp(nskb, pdu, f_bit, llc->vS,
+ llc->vR, INCORRECT);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc;
+ struct llc_sock *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, 1, llc->vS, llc->vR);
+ rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ if (!rc) {
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, skb);
+ }
+ return rc;
+}
+
+static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc;
+ struct llc_sock *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, 0, llc->vS, llc->vR);
+ rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ if (!rc) {
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, skb);
+ }
+ return rc;
+}
+
+int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc;
+ struct llc_sock *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, 0, llc->vS, llc->vR);
+ rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ if (!rc) {
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, skb);
+ }
+ return 0;
+}
+
+int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ u8 nr = LLC_I_GET_NR(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 sk_buff *skb)
+{
+ u8 nr;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (!rc)
+ llc_conn_send_pdu(sk, nskb);
+ else
+ kfree_skb(skb);
+ }
+ if (rc) {
+ nr = LLC_I_GET_NR(pdu);
+ rc = 0;
+ llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
+ }
+ return rc;
+}
+
+int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ u8 nr = LLC_I_GET_NR(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 sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rej_cmd(nskb, 1, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rej_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ u8 f_bit = 1;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rej_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 0;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rej_rsp(nskb, f_bit, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rnr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rnr_cmd(nskb, 1, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rnr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ u8 f_bit = 0;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rnr_rsp(nskb, f_bit, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (!llc->remote_busy_flag) {
+ llc->remote_busy_flag = 1;
+ mod_timer(&llc->busy_state_timer.timer,
+ jiffies + llc->busy_state_timer.expire * HZ);
+ }
+ return 0;
+}
+
+int llc_conn_ac_opt_send_rnr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rnr_rsp(nskb, 0, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rr_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_rr_cmd(nskb, 1, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rr_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_ack_rsp_f_set_1(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+ u8 f_bit = 1;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(nskb, f_bit, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_rr_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_ack_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(nskb, 0, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+void llc_conn_set_p_flag(struct sock *sk, u8 value)
+{
+ int state_changed = llc_sk(sk)->p_flag && !value;
+
+ llc_sk(sk)->p_flag = value;
+
+ if (state_changed)
+ sk->sk_state_change(sk);
+}
+
+int llc_conn_ac_send_sabme_cmd_p_set_x(struct sock *sk, struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (nskb) {
+ struct llc_sap *sap = llc->sap;
+ u8 *dmac = llc->daddr.mac;
+
+ if (llc->dev->flags & IFF_LOOPBACK)
+ dmac = llc->dev->dev_addr;
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_sabme_cmd(nskb, 1);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, dmac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ llc_conn_set_p_flag(sk, 1);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_send_ua_rsp_f_set_p(struct sock *sk, struct sk_buff *skb)
+{
+ u8 f_bit;
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_ua_rsp(nskb, f_bit);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+int llc_conn_ac_set_s_flag_0(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->s_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_s_flag_1(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->s_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc_conn_set_p_flag(sk, 1);
+ mod_timer(&llc->pf_cycle_timer.timer,
+ jiffies + llc->pf_cycle_timer.expire * HZ);
+ return 0;
+}
+
+/**
+ * llc_conn_ac_send_ack_if_needed - check if ack is needed
+ * @sk: current connection structure
+ * @skb: 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 sk_buff *skb)
+{
+ u8 pf_bit;
+ struct llc_sock *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, skb);
+ llc->ack_must_be_send = 0;
+ llc->ack_pf = 0;
+ llc_conn_ac_inc_npta_value(sk, skb);
+ }
+ return 0;
+}
+
+/**
+ * llc_conn_ac_rst_sendack_flag - resets ack_must_be_send flag
+ * @sk: current connection structure
+ * @skb: 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 sk_buff *skb)
+{
+ 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
+ * @skb: 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.
+ */
+static int llc_conn_ac_send_i_rsp_f_set_ackpf(struct sock *sk,
+ struct sk_buff *skb)
+{
+ int rc;
+ struct llc_sock *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_RSP);
+ llc_pdu_init_as_i_cmd(skb, llc->ack_pf, llc->vS, llc->vR);
+ rc = llc_mac_hdr_init(skb, llc->dev->dev_addr, llc->daddr.mac);
+ if (!rc) {
+ llc_conn_send_pdu(sk, skb);
+ llc_conn_ac_inc_vs_by_1(sk, skb);
+ }
+ return rc;
+}
+
+/**
+ * llc_conn_ac_send_i_as_ack - sends an I-format PDU to acknowledge rx PDUs
+ * @sk: current connection structure.
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (llc->ack_must_be_send) {
+ llc_conn_ac_send_i_rsp_f_set_ackpf(sk, skb);
+ llc->ack_must_be_send = 0 ;
+ llc->ack_pf = 0;
+ } else
+ llc_conn_ac_send_i_cmd_p_set_0(sk, skb);
+ return 0;
+}
+
+/**
+ * llc_conn_ac_send_rr_rsp_f_set_ackpf - ack all rx PDUs not yet acked
+ * @sk: current connection structure.
+ * @skb: 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.
+ */
+static int llc_conn_ac_send_rr_rsp_f_set_ackpf(struct sock *sk,
+ struct sk_buff *skb)
+{
+ int rc = -ENOBUFS;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (nskb) {
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ nskb->dev = llc->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_S, sap->laddr.lsap,
+ llc->daddr.lsap, LLC_PDU_RSP);
+ llc_pdu_init_as_rr_rsp(nskb, llc->ack_pf, llc->vR);
+ rc = llc_mac_hdr_init(nskb, llc->dev->dev_addr, llc->daddr.mac);
+ if (rc)
+ goto free;
+ llc_conn_send_pdu(sk, nskb);
+ }
+out:
+ return rc;
+free:
+ kfree_skb(nskb);
+ goto out;
+}
+
+/**
+ * llc_conn_ac_inc_npta_value - tries to make value of npta greater
+ * @sk: current connection structure.
+ * @skb: 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.
+ */
+static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *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.
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sock *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.
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sock *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.
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sock *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.
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sock *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 sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ del_timer(&llc->pf_cycle_timer.timer);
+ del_timer(&llc->ack_timer.timer);
+ del_timer(&llc->rej_sent_timer.timer);
+ del_timer(&llc->busy_state_timer.timer);
+ llc->ack_must_be_send = 0;
+ llc->ack_pf = 0;
+ return 0;
+}
+
+int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ del_timer(&llc->rej_sent_timer.timer);
+ del_timer(&llc->pf_cycle_timer.timer);
+ del_timer(&llc->busy_state_timer.timer);
+ llc->ack_must_be_send = 0;
+ llc->ack_pf = 0;
+ return 0;
+}
+
+int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ);
+ return 0;
+}
+
+int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ mod_timer(&llc->rej_sent_timer.timer,
+ jiffies + llc->rej_sent_timer.expire * HZ);
+ return 0;
+}
+
+int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (!timer_pending(&llc->ack_timer.timer))
+ mod_timer(&llc->ack_timer.timer,
+ jiffies + llc->ack_timer.expire * HZ);
+ return 0;
+}
+
+int llc_conn_ac_stop_ack_timer(struct sock *sk, struct sk_buff *skb)
+{
+ del_timer(&llc_sk(sk)->ack_timer.timer);
+ return 0;
+}
+
+int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ del_timer(&llc->pf_cycle_timer.timer);
+ llc_conn_set_p_flag(sk, 0);
+ return 0;
+}
+
+int llc_conn_ac_stop_rej_timer(struct sock *sk, struct sk_buff *skb)
+{
+ del_timer(&llc_sk(sk)->rej_sent_timer.timer);
+ return 0;
+}
+
+int llc_conn_ac_upd_nr_received(struct sock *sk, struct sk_buff *skb)
+{
+ int acked;
+ u16 unacked = 0;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc->last_nr = PDU_SUPV_GET_Nr(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);
+ 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, skb);
+ }
+ if (unacked)
+ mod_timer(&llc->ack_timer.timer,
+ jiffies + llc->ack_timer.expire * HZ);
+ } else if (llc->failed_data_req) {
+ u8 f_bit;
+
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ if (f_bit == 1) {
+ llc->failed_data_req = 0;
+ llc_conn_ac_data_confirm(sk, skb);
+ }
+ }
+ return 0;
+}
+
+int llc_conn_ac_upd_p_flag(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ if (LLC_PDU_IS_RSP(pdu)) {
+ u8 f_bit;
+
+ llc_pdu_decode_pf_bit(skb, &f_bit);
+ if (f_bit) {
+ llc_conn_set_p_flag(sk, 0);
+ llc_conn_ac_stop_p_timer(sk, skb);
+ }
+ }
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_2(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->data_flag = 2;
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_0(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->data_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_data_flag_1(struct sock *sk, struct sk_buff *skb)
+{
+ 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 sk_buff *skb)
+{
+ 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 sk_buff *skb)
+{
+ llc_conn_set_p_flag(sk, 0);
+ return 0;
+}
+
+static int llc_conn_ac_set_p_flag_1(struct sock *sk, struct sk_buff *skb)
+{
+ llc_conn_set_p_flag(sk, 1);
+ return 0;
+}
+
+int llc_conn_ac_set_remote_busy_0(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->remote_busy_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_cause_flag_0(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->cause_flag = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_cause_flag_1(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->cause_flag = 1;
+ return 0;
+}
+
+int llc_conn_ac_set_retry_cnt_0(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->retry_count = 0;
+ return 0;
+}
+
+int llc_conn_ac_inc_retry_cnt_by_1(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->retry_count++;
+ return 0;
+}
+
+int llc_conn_ac_set_vr_0(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->vR = 0;
+ return 0;
+}
+
+int llc_conn_ac_inc_vr_by_1(struct sock *sk, struct sk_buff *skb)
+{
+ 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 sk_buff *skb)
+{
+ llc_sk(sk)->vS = 0;
+ return 0;
+}
+
+int llc_conn_ac_set_vs_nr(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->vS = llc_sk(sk)->last_nr;
+ return 0;
+}
+
+int llc_conn_ac_inc_vs_by_1(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->vS = (llc_sk(sk)->vS + 1) % 128;
+ return 0;
+}
+
+void llc_conn_pf_cycle_tmr_cb(unsigned long timeout_data)
+{
+ struct sock *sk = (struct sock *)timeout_data;
+ struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
+
+ bh_lock_sock(sk);
+ if (skb) {
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ skb->sk = sk;
+ ev->type = LLC_CONN_EV_TYPE_P_TMR;
+ llc_process_tmr_ev(sk, skb);
+ }
+ bh_unlock_sock(sk);
+}
+
+void llc_conn_busy_tmr_cb(unsigned long timeout_data)
+{
+ struct sock *sk = (struct sock *)timeout_data;
+ struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
+
+ bh_lock_sock(sk);
+ if (skb) {
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ skb->sk = sk;
+ ev->type = LLC_CONN_EV_TYPE_BUSY_TMR;
+ llc_process_tmr_ev(sk, skb);
+ }
+ bh_unlock_sock(sk);
+}
+
+void llc_conn_ack_tmr_cb(unsigned long timeout_data)
+{
+ struct sock* sk = (struct sock *)timeout_data;
+ struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
+
+ bh_lock_sock(sk);
+ if (skb) {
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ skb->sk = sk;
+ ev->type = LLC_CONN_EV_TYPE_ACK_TMR;
+ llc_process_tmr_ev(sk, skb);
+ }
+ bh_unlock_sock(sk);
+}
+
+void llc_conn_rej_tmr_cb(unsigned long timeout_data)
+{
+ struct sock *sk = (struct sock *)timeout_data;
+ struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
+
+ bh_lock_sock(sk);
+ if (skb) {
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ skb->sk = sk;
+ ev->type = LLC_CONN_EV_TYPE_REJ_TMR;
+ llc_process_tmr_ev(sk, skb);
+ }
+ bh_unlock_sock(sk);
+}
+
+int llc_conn_ac_rst_vs(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk(sk)->X = llc_sk(sk)->vS;
+ llc_conn_ac_set_vs_nr(sk, skb);
+ return 0;
+}
+
+int llc_conn_ac_upd_vs(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ u8 nr = PDU_SUPV_GET_Nr(pdu);
+
+ if (llc_circular_between(llc_sk(sk)->vS, nr, llc_sk(sk)->X))
+ llc_conn_ac_set_vs_nr(sk, skb);
+ 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
+ * @skb: occurred event
+ */
+int llc_conn_disc(struct sock *sk, struct sk_buff *skb)
+{
+ /* FIXME: this thing seems to want to die */
+ return 0;
+}
+
+/**
+ * llc_conn_reset - resets connection
+ * @sk : reseting connection.
+ * @skb: occurred event.
+ *
+ * Stop all timers, empty all queues and reset all flags.
+ */
+int llc_conn_reset(struct sock *sk, struct sk_buff *skb)
+{
+ llc_sk_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
+ * @skb: 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 llc_backlog_rcv function after sending
+ * data frame.
+ */
+static void llc_process_tmr_ev(struct sock *sk, struct sk_buff *skb)
+{
+ if (llc_sk(sk)->state == LLC_CONN_OUT_OF_SVC) {
+ printk(KERN_WARNING "%s: timer called on closed connection\n",
+ __FUNCTION__);
+ kfree_skb(skb);
+ } else {
+ if (!sock_owned_by_user(sk))
+ llc_conn_state_process(sk, skb);
+ else {
+ llc_set_backlog_type(skb, LLC_EVENT);
+ sk_add_backlog(sk, skb);
+ }
+ }
+}
diff --git a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c
new file mode 100644
index 000000000000..cd130c3b72bc
--- /dev/null
+++ b/net/llc/llc_c_ev.c
@@ -0,0 +1,769 @@
+/*
+ * 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-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/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 1
+#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;
+ struct llc_pdu_sn *pdu;
+ struct llc_sock *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_hdr(skb);
+ nr1 = LLC_I_GET_NS(pdu);
+ skb = skb_peek_tail(&llc->pdu_unack_q);
+ pdu = llc_pdu_sn_hdr(skb);
+ 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 sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->prim == LLC_CONN_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_data_req(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->prim == LLC_DATA_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_disc_req(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->prim == LLC_DISC_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_rst_req(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->prim == LLC_RESET_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_conn_ev_local_busy_detected(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
+ ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_DETECTED ? 0 : 1;
+}
+
+int llc_conn_ev_local_busy_cleared(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
+ ev->prim_type == LLC_CONN_EV_LOCAL_BUSY_CLEARED ? 0 : 1;
+}
+
+int llc_conn_ev_rx_bad_pdu(struct sock *sk, struct sk_buff *skb)
+{
+ return 1;
+}
+
+int llc_conn_ev_rx_disc_cmd_pbit_set_x(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ return llc_conn_space(sk, skb) &&
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ return llc_conn_space(sk, skb) &&
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn * pdu = llc_pdu_sn_hdr(skb);
+ 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("%s: matched, state=%d, ns=%d, vr=%d\n",
+ __FUNCTION__, llc_sk(sk)->state, ns, vr);
+ return rc;
+}
+
+int llc_conn_ev_rx_i_rsp_fbit_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ return llc_conn_space(sk, skb) &&
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ return llc_conn_space(sk, skb) &&
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ 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("%s: matched, state=%d, ns=%d, vr=%d\n",
+ __FUNCTION__, llc_sk(sk)->state, ns, vr);
+ return rc;
+}
+
+int llc_conn_ev_rx_rej_cmd_pbit_set_0(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ return llc_conn_space(sk, skb) &&
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ return llc_conn_space(sk, skb) &&
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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_x(struct sock *sk, struct sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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_zzz_cmd_pbit_set_x_inval_nr(struct sock *sk,
+ struct sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ u8 vs = llc_sk(sk)->vS;
+ u8 nr = LLC_I_GET_NR(pdu);
+
+ if (LLC_PDU_IS_CMD(pdu) &&
+ (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
+ nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
+ dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
+ __FUNCTION__, 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 sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+ u8 vs = llc_sk(sk)->vS;
+ u8 nr = LLC_I_GET_NR(pdu);
+
+ if (LLC_PDU_IS_RSP(pdu) &&
+ (LLC_PDU_TYPE_IS_I(pdu) || LLC_PDU_TYPE_IS_S(pdu)) &&
+ nr != vs && llc_util_nr_inside_tx_window(sk, nr)) {
+ rc = 0;
+ dprintk("%s: matched, state=%d, vs=%d, nr=%d\n",
+ __FUNCTION__, llc_sk(sk)->state, vs, nr);
+ }
+ return rc;
+}
+
+int llc_conn_ev_rx_any_frame(struct sock *sk, struct sk_buff *skb)
+{
+ return 0;
+}
+
+int llc_conn_ev_p_tmr_exp(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type != LLC_CONN_EV_TYPE_P_TMR;
+}
+
+int llc_conn_ev_ack_tmr_exp(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type != LLC_CONN_EV_TYPE_ACK_TMR;
+}
+
+int llc_conn_ev_rej_tmr_exp(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type != LLC_CONN_EV_TYPE_REJ_TMR;
+}
+
+int llc_conn_ev_busy_tmr_exp(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type != LLC_CONN_EV_TYPE_BUSY_TMR;
+}
+
+int llc_conn_ev_init_p_f_cycle(struct sock *sk, struct sk_buff *skb)
+{
+ return 1;
+}
+
+int llc_conn_ev_tx_buffer_full(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ return ev->type == LLC_CONN_EV_TYPE_SIMPLE &&
+ ev->prim_type == 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 sk_buff *skb)
+{
+ return llc_sk(sk)->data_flag != 1;
+}
+
+int llc_conn_ev_qlfy_data_flag_eq_0(struct sock *sk, struct sk_buff *skb)
+{
+ return llc_sk(sk)->data_flag;
+}
+
+int llc_conn_ev_qlfy_data_flag_eq_2(struct sock *sk, struct sk_buff *skb)
+{
+ return llc_sk(sk)->data_flag != 2;
+}
+
+int llc_conn_ev_qlfy_p_flag_eq_1(struct sock *sk, struct sk_buff *skb)
+{
+ 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.
+ * @skb: 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 sk_buff *skb)
+{
+ 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.
+ * @skb: 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 sk_buff *skb)
+{
+ 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 sk_buff *skb)
+{
+ return llc_sk(sk)->p_flag;
+}
+
+int llc_conn_ev_qlfy_p_flag_eq_f(struct sock *sk, struct sk_buff *skb)
+{
+ u8 f_bit;
+
+ 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 sk_buff *skb)
+{
+ return llc_sk(sk)->remote_busy_flag;
+}
+
+int llc_conn_ev_qlfy_remote_busy_eq_1(struct sock *sk, struct sk_buff *skb)
+{
+ return !llc_sk(sk)->remote_busy_flag;
+}
+
+int llc_conn_ev_qlfy_retry_cnt_lt_n2(struct sock *sk, struct sk_buff *skb)
+{
+ return !(llc_sk(sk)->retry_count < llc_sk(sk)->n2);
+}
+
+int llc_conn_ev_qlfy_retry_cnt_gte_n2(struct sock *sk, struct sk_buff *skb)
+{
+ return !(llc_sk(sk)->retry_count >= llc_sk(sk)->n2);
+}
+
+int llc_conn_ev_qlfy_s_flag_eq_1(struct sock *sk, struct sk_buff *skb)
+{
+ return !llc_sk(sk)->s_flag;
+}
+
+int llc_conn_ev_qlfy_s_flag_eq_0(struct sock *sk, struct sk_buff *skb)
+{
+ return llc_sk(sk)->s_flag;
+}
+
+int llc_conn_ev_qlfy_cause_flag_eq_1(struct sock *sk, struct sk_buff *skb)
+{
+ return !llc_sk(sk)->cause_flag;
+}
+
+int llc_conn_ev_qlfy_cause_flag_eq_0(struct sock *sk, struct sk_buff *skb)
+{
+ return llc_sk(sk)->cause_flag;
+}
+
+int llc_conn_ev_qlfy_set_status_conn(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->status = LLC_STATUS_CONN;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_disc(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->status = LLC_STATUS_DISC;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_failed(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->status = LLC_STATUS_FAILED;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_remote_busy(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->status = LLC_STATUS_REMOTE_BUSY;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_refuse(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->status = LLC_STATUS_REFUSE;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_conflict(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->status = LLC_STATUS_CONFLICT;
+ return 0;
+}
+
+int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ 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..818a9428823b
--- /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-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/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_end;
+
+/* 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_end,
+ [2] = &llc_common_state_trans_end, /* local_busy */
+ [3] = &llc_common_state_trans_end, /* init_pf_cycle */
+ [4] = &llc_common_state_trans_end, /* 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_end,
+};
+
+/* 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_end, /* Request */
+ [1] = &llc_common_state_trans_end, /* local busy */
+ [2] = &llc_common_state_trans_end, /* 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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [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_end,
+ [10] = &llc_normal_state_trans_18, /* Init pf cycle */
+ [11] = &llc_common_state_trans_end,
+ [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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [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_end,
+ [13] = &llc_busy_state_trans_22, /* Initiate PF cycle */
+ [14] = &llc_common_state_trans_end,
+ [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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [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_end,
+ [9] = &llc_reject_state_trans_17, /* Initiate PF cycle */
+ [10] = &llc_common_state_trans_end,
+ [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_end,
+ [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,
+ [39] = &llc_reject_state_trans_10a,
+ [40] = &llc_reject_state_trans_10b,
+ [41] = &llc_reject_state_trans_10c,
+ [42] = &llc_reject_state_trans_11,
+ [43] = &llc_reject_state_trans_12a,
+ [44] = &llc_reject_state_trans_12b,
+ [45] = &llc_reject_state_trans_12c,
+ [46] = &llc_reject_state_trans_13,
+ [47] = &llc_reject_state_trans_14a,
+ [48] = &llc_reject_state_trans_14b,
+ [49] = &llc_reject_state_trans_15a,
+ [50] = &llc_reject_state_trans_15b,
+ [51] = &llc_reject_state_trans_16,
+ [52] = &llc_common_state_trans_end,
+};
+
+/* 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_end,
+ [4] = &llc_await_state_trans_1, /* Local busy */
+ [5] = &llc_common_state_trans_end,
+ [6] = &llc_common_state_trans_end, /* 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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [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_end,
+ [8] = &llc_common_state_trans_end, /* 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_end,
+ [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_end,
+};
+
+/* ----------------- 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_end,
+ [4] = &llc_await_rejct_state_trans_1, /* local busy */
+ [5] = &llc_common_state_trans_end,
+ [6] = &llc_common_state_trans_end, /* 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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [2] = &llc_common_state_trans_end, /* Local busy */
+ [3] = &llc_common_state_trans_end, /* 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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [2] = &llc_common_state_trans_end, /* Local busy */
+ [3] = &llc_common_state_trans_end, /* 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_end,
+ [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_end,
+};
+
+/* 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_end,
+ [2] = &llc_common_state_trans_end, /* Local busy */
+ [3] = &llc_common_state_trans_end, /* Initiate PF cycle */
+ [4] = &llc_error_state_trans_7, /* Timer */
+ [5] = &llc_error_state_trans_8,
+ [6] = &llc_common_state_trans_end,
+ [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_end,
+};
+
+/* 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_end,
+ [2] = &llc_common_state_trans_end, /* local busy */
+ [3] = &llc_common_state_trans_end, /* init_pf_cycle */
+ [4] = &llc_common_state_trans_end, /* timer */
+ [5] = &llc_common_state_trans_end, /* receive */
+};
+
+/* Connection State Transition Table */
+struct llc_conn_state llc_conn_state_table[NBR_CONN_STATES] = {
+ [LLC_CONN_STATE_ADM - 1] = {
+ .current_state = LLC_CONN_STATE_ADM,
+ .transitions = llc_adm_state_transitions,
+ },
+ [LLC_CONN_STATE_SETUP - 1] = {
+ .current_state = LLC_CONN_STATE_SETUP,
+ .transitions = llc_setup_state_transitions,
+ },
+ [LLC_CONN_STATE_NORMAL - 1] = {
+ .current_state = LLC_CONN_STATE_NORMAL,
+ .transitions = llc_normal_state_transitions,
+ },
+ [LLC_CONN_STATE_BUSY - 1] = {
+ .current_state = LLC_CONN_STATE_BUSY,
+ .transitions = llc_busy_state_transitions,
+ },
+ [LLC_CONN_STATE_REJ - 1] = {
+ .current_state = LLC_CONN_STATE_REJ,
+ .transitions = llc_reject_state_transitions,
+ },
+ [LLC_CONN_STATE_AWAIT - 1] = {
+ .current_state = LLC_CONN_STATE_AWAIT,
+ .transitions = llc_await_state_transitions,
+ },
+ [LLC_CONN_STATE_AWAIT_BUSY - 1] = {
+ .current_state = LLC_CONN_STATE_AWAIT_BUSY,
+ .transitions = llc_await_busy_state_transitions,
+ },
+ [LLC_CONN_STATE_AWAIT_REJ - 1] = {
+ .current_state = LLC_CONN_STATE_AWAIT_REJ,
+ .transitions = llc_await_rejct_state_transitions,
+ },
+ [LLC_CONN_STATE_D_CONN - 1] = {
+ .current_state = LLC_CONN_STATE_D_CONN,
+ .transitions = llc_d_conn_state_transitions,
+ },
+ [LLC_CONN_STATE_RESET - 1] = {
+ .current_state = LLC_CONN_STATE_RESET,
+ .transitions = llc_rst_state_transitions,
+ },
+ [LLC_CONN_STATE_ERROR - 1] = {
+ .current_state = LLC_CONN_STATE_ERROR,
+ .transitions = llc_error_state_transitions,
+ },
+ [LLC_CONN_STATE_TEMP - 1] = {
+ .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..eba812a9c69c
--- /dev/null
+++ b/net/llc/llc_conn.c
@@ -0,0 +1,915 @@
+/*
+ * llc_conn.c - Driver routines for connection component.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <net/llc_sap.h>
+#include <net/llc_conn.h>
+#include <net/sock.h>
+#include <linux/tcp.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_c_st.h>
+#include <net/llc_pdu.h>
+
+#if 0
+#define dprintk(args...) printk(KERN_DEBUG args)
+#else
+#define dprintk(args...)
+#endif
+
+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 sk_buff *skb);
+static int llc_exec_conn_trans_actions(struct sock *sk,
+ struct llc_conn_state_trans *trans,
+ struct sk_buff *ev);
+static struct llc_conn_state_trans *llc_qualify_conn_ev(struct sock *sk,
+ struct sk_buff *skb);
+
+/* Offset table on connection states transition diagram */
+static int llc_offset_table[NBR_CONN_STATES][NBR_CONN_EV];
+
+/**
+ * llc_conn_state_process - sends event to connection state machine
+ * @sk: connection
+ * @skb: 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_state_process(struct sock *sk, struct sk_buff *skb)
+{
+ int rc;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ /*
+ * We have to hold the skb, because llc_conn_service will kfree it in
+ * the sending path and we need to look at the skb->cb, where we encode
+ * llc_conn_state_ev.
+ */
+ skb_get(skb);
+ ev->ind_prim = ev->cfm_prim = 0;
+ rc = llc_conn_service(sk, skb); /* sending event to state machine */
+ if (rc) {
+ printk(KERN_ERR "%s: llc_conn_service failed\n", __FUNCTION__);
+ goto out_kfree_skb;
+ }
+
+ if (!ev->ind_prim && !ev->cfm_prim) {
+ /* indicate or confirm not required */
+ if (!skb->list)
+ goto out_kfree_skb;
+ goto out_skb_put;
+ }
+
+ if (ev->ind_prim && ev->cfm_prim) /* Paranoia */
+ skb_get(skb);
+
+ switch (ev->ind_prim) {
+ case LLC_DATA_PRIM:
+ llc_save_primitive(skb, LLC_DATA_PRIM);
+ if (sock_queue_rcv_skb(sk, skb)) {
+ /*
+ * shouldn't happen
+ */
+ printk(KERN_ERR "%s: sock_queue_rcv_skb failed!\n",
+ __FUNCTION__);
+ kfree_skb(skb);
+ }
+ break;
+ case LLC_CONN_PRIM: {
+ struct sock *parent = skb->sk;
+
+ skb->sk = sk;
+ skb_queue_tail(&parent->sk_receive_queue, skb);
+ sk->sk_state_change(parent);
+ }
+ break;
+ case LLC_DISC_PRIM:
+ sock_hold(sk);
+ if (sk->sk_type == SOCK_STREAM &&
+ sk->sk_state == TCP_ESTABLISHED) {
+ sk->sk_shutdown = SHUTDOWN_MASK;
+ sk->sk_socket->state = SS_UNCONNECTED;
+ sk->sk_state = TCP_CLOSE;
+ if (!sock_flag(sk, SOCK_DEAD)) {
+ sk->sk_state_change(sk);
+ sock_set_flag(sk, SOCK_DEAD);
+ }
+ }
+ kfree_skb(skb);
+ sock_put(sk);
+ break;
+ case LLC_RESET_PRIM:
+ /*
+ * FIXME:
+ * RESET is not being notified to upper layers for now
+ */
+ printk(KERN_INFO "%s: received a reset ind!\n", __FUNCTION__);
+ kfree_skb(skb);
+ break;
+ default:
+ if (ev->ind_prim) {
+ printk(KERN_INFO "%s: received unknown %d prim!\n",
+ __FUNCTION__, ev->ind_prim);
+ kfree_skb(skb);
+ }
+ /* No indication */
+ break;
+ }
+
+ switch (ev->cfm_prim) {
+ case LLC_DATA_PRIM:
+ if (!llc_data_accept_state(llc->state))
+ sk->sk_write_space(sk);
+ else
+ rc = llc->failed_data_req = 1;
+ break;
+ case LLC_CONN_PRIM:
+ if (sk->sk_type == SOCK_STREAM &&
+ sk->sk_state == TCP_SYN_SENT) {
+ if (ev->status) {
+ sk->sk_socket->state = SS_UNCONNECTED;
+ sk->sk_state = TCP_CLOSE;
+ } else {
+ sk->sk_socket->state = SS_CONNECTED;
+ sk->sk_state = TCP_ESTABLISHED;
+ }
+ sk->sk_state_change(sk);
+ }
+ break;
+ case LLC_DISC_PRIM:
+ sock_hold(sk);
+ if (sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_CLOSING) {
+ sk->sk_socket->state = SS_UNCONNECTED;
+ sk->sk_state = TCP_CLOSE;
+ sk->sk_state_change(sk);
+ }
+ sock_put(sk);
+ break;
+ case LLC_RESET_PRIM:
+ /*
+ * FIXME:
+ * RESET is not being notified to upper layers for now
+ */
+ printk(KERN_INFO "%s: received a reset conf!\n", __FUNCTION__);
+ break;
+ default:
+ if (ev->cfm_prim) {
+ printk(KERN_INFO "%s: received unknown %d prim!\n",
+ __FUNCTION__, ev->cfm_prim);
+ break;
+ }
+ goto out_skb_put; /* No confirmation */
+ }
+out_kfree_skb:
+ kfree_skb(skb);
+out_skb_put:
+ kfree_skb(skb);
+ return rc;
+}
+
+void llc_conn_send_pdu(struct sock *sk, struct sk_buff *skb)
+{
+ /* queue PDU to send to MAC layer */
+ skb_queue_tail(&sk->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
+ *
+ * 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_state_process.
+ */
+void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->ind_prim = LLC_DATA_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;
+ struct llc_pdu_sn *pdu;
+ u16 nbr_unack_pdus;
+ struct llc_sock *llc;
+ 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.
+ */
+ llc = llc_sk(sk);
+
+ while ((skb = skb_dequeue(&llc->pdu_unack_q)) != NULL) {
+ pdu = llc_pdu_sn_hdr(skb);
+ llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD);
+ llc_pdu_set_pf_bit(skb, first_p_bit);
+ skb_queue_tail(&sk->sk_write_queue, skb);
+ first_p_bit = 0;
+ llc->vS = LLC_I_GET_NS(pdu);
+ howmany_resend++;
+ }
+ if (howmany_resend > 0)
+ llc->vS = (llc->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;
+ u16 nbr_unack_pdus;
+ struct llc_sock *llc = llc_sk(sk);
+ 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->pdu_unack_q)) != NULL) {
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP);
+ llc_pdu_set_pf_bit(skb, first_f_bit);
+ skb_queue_tail(&sk->sk_write_queue, skb);
+ first_f_bit = 0;
+ llc->vS = LLC_I_GET_NS(pdu);
+ howmany_resend++;
+ }
+ if (howmany_resend > 0)
+ llc->vS = (llc->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;
+ struct llc_pdu_sn *pdu;
+ int nbr_acked = 0;
+ struct llc_sock *llc = llc_sk(sk);
+ int q_len = skb_queue_len(&llc->pdu_unack_q);
+
+ if (!q_len)
+ goto out;
+ skb = skb_peek(&llc->pdu_unack_q);
+ pdu = llc_pdu_sn_hdr(skb);
+
+ /* 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->pdu_unack_q);
+ if (skb)
+ kfree_skb(skb);
+ nbr_acked++;
+ }
+out:
+ *how_many_unacked = skb_queue_len(&llc->pdu_unack_q);
+ return nbr_acked;
+}
+
+/**
+ * llc_conn_send_pdus - Sends queued PDUs
+ * @sk: active connection
+ *
+ * Sends queued pdus to MAC layer for transmission.
+ */
+static void llc_conn_send_pdus(struct sock *sk)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&sk->sk_write_queue)) != NULL) {
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ if (LLC_PDU_TYPE_IS_I(pdu) &&
+ !(skb->dev->flags & IFF_LOOPBACK)) {
+ struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
+
+ skb_queue_tail(&llc_sk(sk)->pdu_unack_q, skb);
+ if (!skb2)
+ break;
+ skb = skb2;
+ }
+ dev_queue_xmit(skb);
+ }
+}
+
+/**
+ * llc_conn_service - finds transition and changes state of connection
+ * @sk: connection
+ * @skb: 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 sk_buff *skb)
+{
+ int rc = 1;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_conn_state_trans *trans;
+
+ if (llc->state > NBR_CONN_STATES)
+ goto out;
+ rc = 0;
+ trans = llc_qualify_conn_ev(sk, skb);
+ if (trans) {
+ rc = llc_exec_conn_trans_actions(sk, trans, skb);
+ if (!rc && trans->next_state != NO_STATE_CHANGE) {
+ llc->state = trans->next_state;
+ if (!llc_data_accept_state(llc->state))
+ sk->sk_state_change(sk);
+ }
+ }
+out:
+ return rc;
+}
+
+/**
+ * llc_qualify_conn_ev - finds transition for event
+ * @sk: connection
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_conn_state_trans **next_trans;
+ llc_conn_ev_qfyr_t *next_qualifier;
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_conn_state *curr_state =
+ &llc_conn_state_table[llc->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->state - 1, ev->type);
+ (*next_trans)->ev; next_trans++) {
+ if (!((*next_trans)->ev)(sk, skb)) {
+ /* 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, skb); 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
+ * @skb: event
+ *
+ * Executes actions that is related to happened event. Returns 0 for
+ * success, 1 to indicate failure of at least one action.
+ */
+static int llc_exec_conn_trans_actions(struct sock *sk,
+ struct llc_conn_state_trans *trans,
+ struct sk_buff *skb)
+{
+ 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, skb);
+
+ if (rc2 == 2) {
+ rc = rc2;
+ break;
+ } else if (rc2)
+ rc = 1;
+ }
+ return rc;
+}
+
+/**
+ * llc_lookup_established - Finds connection 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_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
+ struct llc_addr *laddr)
+{
+ struct sock *rc;
+ struct hlist_node *node;
+
+ read_lock_bh(&sap->sk_list.lock);
+ sk_for_each(rc, node, &sap->sk_list.list) {
+ struct llc_sock *llc = llc_sk(rc);
+
+ if (llc->laddr.lsap == laddr->lsap &&
+ llc->daddr.lsap == daddr->lsap &&
+ llc_mac_match(llc->laddr.mac, laddr->mac) &&
+ llc_mac_match(llc->daddr.mac, daddr->mac)) {
+ sock_hold(rc);
+ goto found;
+ }
+ }
+ rc = NULL;
+found:
+ read_unlock_bh(&sap->sk_list.lock);
+ return rc;
+}
+
+/**
+ * llc_lookup_listener - Finds listener for local MAC + SAP
+ * @sap: SAP
+ * @laddr: address of local LLC (MAC + SAP)
+ *
+ * Search connection list of the SAP and finds connection listening on
+ * local mac, and local sap. Returns pointer for parent socket found,
+ * %NULL otherwise.
+ */
+static struct sock *llc_lookup_listener(struct llc_sap *sap,
+ struct llc_addr *laddr)
+{
+ struct sock *rc;
+ struct hlist_node *node;
+
+ read_lock_bh(&sap->sk_list.lock);
+ sk_for_each(rc, node, &sap->sk_list.list) {
+ struct llc_sock *llc = llc_sk(rc);
+
+ if (rc->sk_type == SOCK_STREAM && rc->sk_state == TCP_LISTEN &&
+ llc->laddr.lsap == laddr->lsap &&
+ (llc_mac_match(llc->laddr.mac, laddr->mac) ||
+ llc_mac_null(llc->laddr.mac))) {
+ sock_hold(rc);
+ goto found;
+ }
+ }
+ rc = NULL;
+found:
+ read_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)
+{
+ return state != LLC_CONN_STATE_NORMAL && state != LLC_CONN_STATE_BUSY &&
+ state != LLC_CONN_STATE_REJ;
+}
+
+/**
+ * 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.
+ */
+static 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;
+
+ 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;
+}
+
+/**
+ * llc_sap_add_socket - adds a socket to a SAP
+ * @sap: SAP
+ * @sk: socket
+ *
+ * This function adds a socket to sk_list of a SAP.
+ */
+void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk)
+{
+ write_lock_bh(&sap->sk_list.lock);
+ llc_sk(sk)->sap = sap;
+ sk_add_node(sk, &sap->sk_list.list);
+ write_unlock_bh(&sap->sk_list.lock);
+}
+
+/**
+ * llc_sap_remove_socket - removes a socket from SAP
+ * @sap: SAP
+ * @sk: socket
+ *
+ * This function removes a connection from sk_list.list of a SAP if
+ * the connection was in this list.
+ */
+void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk)
+{
+ write_lock_bh(&sap->sk_list.lock);
+ sk_del_node_init(sk);
+ write_unlock_bh(&sap->sk_list.lock);
+}
+
+/**
+ * llc_conn_rcv - sends received pdus to the connection state machine
+ * @sk: current connection structure.
+ * @skb: received frame.
+ *
+ * Sends received pdus to the connection state machine.
+ */
+static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+ struct llc_sock *llc = llc_sk(sk);
+
+ if (!llc->dev)
+ llc->dev = skb->dev;
+ ev->type = LLC_CONN_EV_TYPE_PDU;
+ ev->reason = 0;
+ return llc_conn_state_process(sk, skb);
+}
+
+void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
+{
+ 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_lookup_established(sap, &saddr, &daddr);
+ if (!sk) {
+ /*
+ * Didn't find an active connection; verify if there
+ * is a listening socket for this llc addr
+ */
+ struct llc_sock *llc;
+ struct sock *parent = llc_lookup_listener(sap, &daddr);
+
+ if (!parent) {
+ dprintk("llc_lookup_listener failed!\n");
+ goto drop;
+ }
+
+ sk = llc_sk_alloc(parent->sk_family, GFP_ATOMIC, parent->sk_prot);
+ if (!sk) {
+ sock_put(parent);
+ goto drop;
+ }
+ llc = llc_sk(sk);
+ memcpy(&llc->laddr, &daddr, sizeof(llc->laddr));
+ memcpy(&llc->daddr, &saddr, sizeof(llc->daddr));
+ llc_sap_add_socket(sap, sk);
+ sock_hold(sk);
+ sock_put(parent);
+ skb->sk = parent;
+ } else
+ skb->sk = sk;
+ bh_lock_sock(sk);
+ if (!sock_owned_by_user(sk))
+ llc_conn_rcv(sk, skb);
+ else {
+ dprintk("%s: adding to backlog...\n", __FUNCTION__);
+ llc_set_backlog_type(skb, LLC_PACKET);
+ sk_add_backlog(sk, skb);
+ }
+ bh_unlock_sock(sk);
+ sock_put(sk);
+ return;
+drop:
+ kfree_skb(skb);
+}
+
+#undef LLC_REFCNT_DEBUG
+#ifdef LLC_REFCNT_DEBUG
+static atomic_t llc_sock_nr;
+#endif
+
+/**
+ * llc_release_sockets - releases all sockets in a sap
+ * @sap: sap to release its sockets
+ *
+ * Releases all connections of a sap. Returns 0 if all actions complete
+ * successfully, nonzero otherwise
+ */
+int llc_release_sockets(struct llc_sap *sap)
+{
+ int rc = 0;
+ struct sock *sk;
+ struct hlist_node *node;
+
+ write_lock_bh(&sap->sk_list.lock);
+
+ sk_for_each(sk, node, &sap->sk_list.list) {
+ llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
+
+ if (llc_send_disc(sk))
+ rc = 1;
+ }
+
+ write_unlock_bh(&sap->sk_list.lock);
+ return rc;
+}
+
+/**
+ * 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 llc_rcv 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_sock *llc = llc_sk(sk);
+
+ if (llc_backlog_type(skb) == LLC_PACKET) {
+ if (llc->state > 1) /* not closed */
+ rc = llc_conn_rcv(sk, skb);
+ else
+ goto out_kfree_skb;
+ } else if (llc_backlog_type(skb) == LLC_EVENT) {
+ /* timer expiration event */
+ if (llc->state > 1) /* not closed */
+ rc = llc_conn_state_process(sk, skb);
+ else
+ goto out_kfree_skb;
+ } else {
+ printk(KERN_ERR "%s: invalid skb in backlog\n", __FUNCTION__);
+ goto out_kfree_skb;
+ }
+out:
+ return rc;
+out_kfree_skb:
+ kfree_skb(skb);
+ goto out;
+}
+
+/**
+ * llc_sk_init - Initializes a socket with default llc values.
+ * @sk: socket to initialize.
+ *
+ * Initializes a socket with default llc values.
+ */
+static void llc_sk_init(struct sock* sk)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc->state = LLC_CONN_STATE_ADM;
+ llc->inc_cntr = llc->dec_cntr = 2;
+ llc->dec_step = llc->connect_step = 1;
+
+ init_timer(&llc->ack_timer.timer);
+ llc->ack_timer.expire = LLC_ACK_TIME;
+ llc->ack_timer.timer.data = (unsigned long)sk;
+ llc->ack_timer.timer.function = llc_conn_ack_tmr_cb;
+
+ init_timer(&llc->pf_cycle_timer.timer);
+ llc->pf_cycle_timer.expire = LLC_P_TIME;
+ llc->pf_cycle_timer.timer.data = (unsigned long)sk;
+ llc->pf_cycle_timer.timer.function = llc_conn_pf_cycle_tmr_cb;
+
+ init_timer(&llc->rej_sent_timer.timer);
+ llc->rej_sent_timer.expire = LLC_REJ_TIME;
+ llc->rej_sent_timer.timer.data = (unsigned long)sk;
+ llc->rej_sent_timer.timer.function = llc_conn_rej_tmr_cb;
+
+ init_timer(&llc->busy_state_timer.timer);
+ llc->busy_state_timer.expire = LLC_BUSY_TIME;
+ llc->busy_state_timer.timer.data = (unsigned long)sk;
+ llc->busy_state_timer.timer.function = llc_conn_busy_tmr_cb;
+
+ 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->sk_backlog_rcv = llc_backlog_rcv;
+}
+
+/**
+ * llc_sk_alloc - Allocates LLC sock
+ * @family: upper layer protocol family
+ * @priority: for allocation (%GFP_KERNEL, %GFP_ATOMIC, etc)
+ *
+ * Allocates a LLC sock and initializes it. Returns the new LLC sock
+ * or %NULL if there's no memory available for one
+ */
+struct sock *llc_sk_alloc(int family, int priority, struct proto *prot)
+{
+ struct sock *sk = sk_alloc(family, priority, prot, 1);
+
+ if (!sk)
+ goto out;
+ llc_sk_init(sk);
+ sock_init_data(NULL, sk);
+#ifdef LLC_REFCNT_DEBUG
+ atomic_inc(&llc_sock_nr);
+ printk(KERN_DEBUG "LLC socket %p created in %s, now we have %d alive\n", sk,
+ __FUNCTION__, atomic_read(&llc_sock_nr));
+#endif
+out:
+ return sk;
+}
+
+/**
+ * llc_sk_free - Frees a LLC socket
+ * @sk - socket to free
+ *
+ * Frees a LLC socket
+ */
+void llc_sk_free(struct sock *sk)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc->state = LLC_CONN_OUT_OF_SVC;
+ /* Stop all (possibly) running timers */
+ llc_conn_ac_stop_all_timers(sk, NULL);
+#ifdef DEBUG_LLC_CONN_ALLOC
+ printk(KERN_INFO "%s: unackq=%d, txq=%d\n", __FUNCTION__,
+ skb_queue_len(&llc->pdu_unack_q),
+ skb_queue_len(&sk->sk_write_queue));
+#endif
+ skb_queue_purge(&sk->sk_receive_queue);
+ skb_queue_purge(&sk->sk_write_queue);
+ skb_queue_purge(&llc->pdu_unack_q);
+#ifdef LLC_REFCNT_DEBUG
+ if (atomic_read(&sk->sk_refcnt) != 1) {
+ printk(KERN_DEBUG "Destruction of LLC sock %p delayed in %s, cnt=%d\n",
+ sk, __FUNCTION__, atomic_read(&sk->sk_refcnt));
+ printk(KERN_DEBUG "%d LLC sockets are still alive\n",
+ atomic_read(&llc_sock_nr));
+ } else {
+ atomic_dec(&llc_sock_nr);
+ printk(KERN_DEBUG "LLC socket %p released in %s, %d are still alive\n", sk,
+ __FUNCTION__, atomic_read(&llc_sock_nr));
+ }
+#endif
+ sock_put(sk);
+}
+
+/**
+ * llc_sk_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_sk_reset(struct sock *sk)
+{
+ struct llc_sock *llc = llc_sk(sk);
+
+ llc_conn_ac_stop_all_timers(sk, NULL);
+ skb_queue_purge(&sk->sk_write_queue);
+ skb_queue_purge(&llc->pdu_unack_q);
+ llc->remote_busy_flag = 0;
+ llc->cause_flag = 0;
+ llc->retry_count = 0;
+ llc_conn_set_p_flag(sk, 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;
+}
diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c
new file mode 100644
index 000000000000..5ff02c080a0b
--- /dev/null
+++ b/net/llc/llc_core.c
@@ -0,0 +1,179 @@
+/*
+ * llc_core.c - Minimum needed routines for sap handling and module init/exit
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <net/llc.h>
+
+LIST_HEAD(llc_sap_list);
+DEFINE_RWLOCK(llc_sap_list_lock);
+
+unsigned char llc_station_mac_sa[ETH_ALEN];
+
+/**
+ * llc_sap_alloc - allocates and initializes sap.
+ *
+ * Allocates and initializes sap.
+ */
+static struct llc_sap *llc_sap_alloc(void)
+{
+ struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC);
+
+ if (sap) {
+ memset(sap, 0, sizeof(*sap));
+ sap->state = LLC_SAP_STATE_ACTIVE;
+ memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN);
+ rwlock_init(&sap->sk_list.lock);
+ }
+ return sap;
+}
+
+/**
+ * llc_add_sap - add sap to station list
+ * @sap: Address of the sap
+ *
+ * Adds a sap to the LLC's station sap list.
+ */
+static void llc_add_sap(struct llc_sap *sap)
+{
+ write_lock_bh(&llc_sap_list_lock);
+ list_add_tail(&sap->node, &llc_sap_list);
+ write_unlock_bh(&llc_sap_list_lock);
+}
+
+/**
+ * llc_del_sap - del sap from station list
+ * @sap: Address of the sap
+ *
+ * Removes a sap to the LLC's station sap list.
+ */
+static void llc_del_sap(struct llc_sap *sap)
+{
+ write_lock_bh(&llc_sap_list_lock);
+ list_del(&sap->node);
+ write_unlock_bh(&llc_sap_list_lock);
+}
+
+/**
+ * llc_sap_find - searchs a SAP in station
+ * @sap_value: sap to be found
+ *
+ * Searchs for a sap in the sap list of the LLC's station upon the sap ID.
+ * Returns the sap or %NULL if not found.
+ */
+struct llc_sap *llc_sap_find(unsigned char sap_value)
+{
+ struct llc_sap* sap;
+
+ read_lock_bh(&llc_sap_list_lock);
+ list_for_each_entry(sap, &llc_sap_list, node)
+ if (sap->laddr.lsap == sap_value)
+ goto out;
+ sap = NULL;
+out:
+ read_unlock_bh(&llc_sap_list_lock);
+ return sap;
+}
+
+/**
+ * llc_sap_open - open interface to the upper layers.
+ * @lsap: SAP number.
+ * @func: rcv func for datalink protos
+ *
+ * Interface function to upper layer. Each one who wants to get a SAP
+ * (for example NetBEUI) should call this function. Returns the opened
+ * SAP for success, NULL for failure.
+ */
+struct llc_sap *llc_sap_open(unsigned char lsap,
+ int (*func)(struct sk_buff *skb,
+ struct net_device *dev,
+ struct packet_type *pt))
+{
+ struct llc_sap *sap = llc_sap_find(lsap);
+
+ if (sap) { /* SAP already exists */
+ sap = NULL;
+ goto out;
+ }
+ sap = llc_sap_alloc();
+ if (!sap)
+ goto out;
+ sap->laddr.lsap = lsap;
+ sap->rcv_func = func;
+ llc_add_sap(sap);
+out:
+ return sap;
+}
+
+/**
+ * llc_sap_close - close interface for upper layers.
+ * @sap: SAP to be closed.
+ *
+ * Close interface function to upper layer. Each one who wants to
+ * close an open SAP (for example NetBEUI) should call this function.
+ * Removes this sap from the list of saps in the station and then
+ * frees the memory for this sap.
+ */
+void llc_sap_close(struct llc_sap *sap)
+{
+ WARN_ON(!hlist_empty(&sap->sk_list.list));
+ llc_del_sap(sap);
+ kfree(sap);
+}
+
+static struct packet_type llc_packet_type = {
+ .type = __constant_htons(ETH_P_802_2),
+ .func = llc_rcv,
+};
+
+static struct packet_type llc_tr_packet_type = {
+ .type = __constant_htons(ETH_P_TR_802_2),
+ .func = llc_rcv,
+};
+
+static int __init llc_init(void)
+{
+ if (dev_base->next)
+ memcpy(llc_station_mac_sa, dev_base->next->dev_addr, ETH_ALEN);
+ else
+ memset(llc_station_mac_sa, 0, ETH_ALEN);
+ dev_add_pack(&llc_packet_type);
+ dev_add_pack(&llc_tr_packet_type);
+ return 0;
+}
+
+static void __exit llc_exit(void)
+{
+ dev_remove_pack(&llc_packet_type);
+ dev_remove_pack(&llc_tr_packet_type);
+}
+
+module_init(llc_init);
+module_exit(llc_exit);
+
+EXPORT_SYMBOL(llc_station_mac_sa);
+EXPORT_SYMBOL(llc_sap_list);
+EXPORT_SYMBOL(llc_sap_list_lock);
+EXPORT_SYMBOL(llc_sap_find);
+EXPORT_SYMBOL(llc_sap_open);
+EXPORT_SYMBOL(llc_sap_close);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Procom 1997, Jay Schullist 2001, Arnaldo C. Melo 2001-2003");
+MODULE_DESCRIPTION("LLC IEEE 802.2 core support");
diff --git a/net/llc/llc_if.c b/net/llc/llc_if.c
new file mode 100644
index 000000000000..0f9fc48aeaf9
--- /dev/null
+++ b/net/llc/llc_if.c
@@ -0,0 +1,157 @@
+/*
+ * llc_if.c - Defines LLC interface to upper layer
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/tcp.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>
+
+u8 llc_mac_null_var[IFHWADDRLEN];
+
+/**
+ * llc_build_and_send_pkt - Connection data sending for upper layers.
+ * @sk: connection
+ * @skb: packet to send
+ *
+ * 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.
+ */
+int llc_build_and_send_pkt(struct sock *sk, struct sk_buff *skb)
+{
+ struct llc_conn_state_ev *ev;
+ int rc = -ECONNABORTED;
+ struct llc_sock *llc = llc_sk(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;
+ }
+ ev = llc_conn_ev(skb);
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->prim = LLC_DATA_PRIM;
+ ev->prim_type = LLC_PRIM_TYPE_REQ;
+ skb->dev = llc->dev;
+ rc = llc_conn_state_process(sk, skb);
+out:
+ return rc;
+}
+
+/**
+ * llc_establish_connection - Called by upper layer to establish a conn
+ * @sk: connection
+ * @lmac: local mac address
+ * @dmac: destination mac address
+ * @dsap: destination sap
+ *
+ * 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.
+ */
+int llc_establish_connection(struct sock *sk, u8 *lmac, u8 *dmac, u8 dsap)
+{
+ int rc = -EISCONN;
+ struct llc_addr laddr, daddr;
+ struct sk_buff *skb;
+ struct llc_sock *llc = llc_sk(sk);
+ struct sock *existing;
+
+ laddr.lsap = llc->sap->laddr.lsap;
+ daddr.lsap = dsap;
+ memcpy(daddr.mac, dmac, sizeof(daddr.mac));
+ memcpy(laddr.mac, lmac, sizeof(laddr.mac));
+ existing = llc_lookup_established(llc->sap, &daddr, &laddr);
+ if (existing) {
+ if (existing->sk_state == TCP_ESTABLISHED) {
+ sk = existing;
+ goto out_put;
+ } else
+ sock_put(existing);
+ }
+ sock_hold(sk);
+ rc = -ENOMEM;
+ skb = alloc_skb(0, GFP_ATOMIC);
+ if (skb) {
+ struct llc_conn_state_ev *ev = llc_conn_ev(skb);
+
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->prim = LLC_CONN_PRIM;
+ ev->prim_type = LLC_PRIM_TYPE_REQ;
+ rc = llc_conn_state_process(sk, skb);
+ }
+out_put:
+ sock_put(sk);
+ return rc;
+}
+
+/**
+ * llc_send_disc - Called by upper layer to close a connection
+ * @sk: connection to be closed
+ *
+ * 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.
+ */
+int llc_send_disc(struct sock *sk)
+{
+ u16 rc = 1;
+ struct llc_conn_state_ev *ev;
+ struct sk_buff *skb;
+
+ sock_hold(sk);
+ if (sk->sk_type != SOCK_STREAM || sk->sk_state != TCP_ESTABLISHED ||
+ 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
+ */
+ skb = alloc_skb(0, GFP_ATOMIC);
+ if (!skb)
+ goto out;
+ sk->sk_state = TCP_CLOSING;
+ ev = llc_conn_ev(skb);
+ ev->type = LLC_CONN_EV_TYPE_PRIM;
+ ev->prim = LLC_DISC_PRIM;
+ ev->prim_type = LLC_PRIM_TYPE_REQ;
+ rc = llc_conn_state_process(sk, skb);
+out:
+ sock_put(sk);
+ return rc;
+}
+
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
new file mode 100644
index 000000000000..4da6976efc9c
--- /dev/null
+++ b/net/llc/llc_input.c
@@ -0,0 +1,189 @@
+/*
+ * llc_input.c - Minimal input path for LLC
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/netdevice.h>
+#include <net/llc.h>
+#include <net/llc_pdu.h>
+#include <net/llc_sap.h>
+
+#if 0
+#define dprintk(args...) printk(KERN_DEBUG args)
+#else
+#define dprintk(args...)
+#endif
+
+/*
+ * Packet handler for the station, registerable because in the minimal
+ * LLC core that is taking shape only the very minimal subset of LLC that
+ * is needed for things like IPX, Appletalk, etc will stay, with all the
+ * rest in the llc1 and llc2 modules.
+ */
+static void (*llc_station_handler)(struct sk_buff *skb);
+
+/*
+ * Packet handlers for LLC_DEST_SAP and LLC_DEST_CONN.
+ */
+static void (*llc_type_handlers[2])(struct llc_sap *sap,
+ struct sk_buff *skb);
+
+void llc_add_pack(int type, void (*handler)(struct llc_sap *sap,
+ struct sk_buff *skb))
+{
+ if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
+ llc_type_handlers[type - 1] = handler;
+}
+
+void llc_remove_pack(int type)
+{
+ if (type == LLC_DEST_SAP || type == LLC_DEST_CONN)
+ llc_type_handlers[type - 1] = NULL;
+}
+
+void llc_set_station_handler(void (*handler)(struct sk_buff *skb))
+{
+ llc_station_handler = handler;
+}
+
+/**
+ * llc_pdu_type - returns which LLC component must handle for PDU
+ * @skb: input skb
+ *
+ * This function returns which LLC component must handle this PDU.
+ */
+static __inline__ int llc_pdu_type(struct sk_buff *skb)
+{
+ int type = LLC_DEST_CONN; /* I-PDU or S-PDU type */
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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:
+ return type;
+}
+
+/**
+ * llc_fixup_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 inline int llc_fixup_skb(struct sk_buff *skb)
+{
+ u8 llc_len = 2;
+ struct llc_pdu_sn *pdu;
+
+ if (!pskb_may_pull(skb, sizeof(*pdu)))
+ return 0;
+
+ pdu = (struct llc_pdu_sn *)skb->data;
+ if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
+ llc_len = 1;
+ llc_len += 2;
+ skb->h.raw += llc_len;
+ skb_pull(skb, llc_len);
+ if (skb->protocol == htons(ETH_P_802_2)) {
+ u16 pdulen = eth_hdr(skb)->h_proto,
+ data_size = ntohs(pdulen) - llc_len;
+
+ skb_trim(skb, data_size);
+ }
+ return 1;
+}
+
+/**
+ * llc_rcv - 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_{station,sap,conn}_rcv for sending to proper state machine. If
+ * the frame is related to a busy connection (a connection is sending
+ * data now), it queues this frame in the connection's backlog.
+ */
+int llc_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *pt)
+{
+ struct llc_sap *sap;
+ struct llc_pdu_sn *pdu;
+ int dest;
+
+ /*
+ * When the interface is in promisc. mode, drop all the crap that it
+ * receives, do not try to analyse it.
+ */
+ if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) {
+ dprintk("%s: PACKET_OTHERHOST\n", __FUNCTION__);
+ goto drop;
+ }
+ skb = skb_share_check(skb, GFP_ATOMIC);
+ if (unlikely(!skb))
+ goto out;
+ if (unlikely(!llc_fixup_skb(skb)))
+ goto drop;
+ pdu = llc_pdu_sn_hdr(skb);
+ if (unlikely(!pdu->dsap)) /* NULL DSAP, refer to station */
+ goto handle_station;
+ sap = llc_sap_find(pdu->dsap);
+ if (unlikely(!sap)) {/* unknown SAP */
+ dprintk("%s: llc_sap_find(%02X) failed!\n", __FUNCTION__,
+ pdu->dsap);
+ goto drop;
+ }
+ /*
+ * First the upper layer protocols that don't need the full
+ * LLC functionality
+ */
+ if (sap->rcv_func) {
+ sap->rcv_func(skb, dev, pt);
+ goto out;
+ }
+ dest = llc_pdu_type(skb);
+ if (unlikely(!dest || !llc_type_handlers[dest - 1]))
+ goto drop;
+ llc_type_handlers[dest - 1](sap, skb);
+out:
+ return 0;
+drop:
+ kfree_skb(skb);
+ goto out;
+handle_station:
+ if (!llc_station_handler)
+ goto drop;
+ llc_station_handler(skb);
+ goto out;
+}
+
+EXPORT_SYMBOL(llc_add_pack);
+EXPORT_SYMBOL(llc_remove_pack);
+EXPORT_SYMBOL(llc_set_station_handler);
diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c
new file mode 100644
index 000000000000..ab5784cf163e
--- /dev/null
+++ b/net/llc/llc_output.c
@@ -0,0 +1,107 @@
+/*
+ * llc_output.c - LLC minimal output path
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License version 2 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 version 2 for more details.
+ */
+
+#include <linux/if_arp.h>
+#include <linux/if_tr.h>
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include <linux/skbuff.h>
+#include <net/llc.h>
+#include <net/llc_pdu.h>
+
+/**
+ * llc_mac_hdr_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.
+ */
+int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da)
+{
+ int rc = 0;
+
+ switch (skb->dev->type) {
+#ifdef CONFIG_TR
+ case ARPHRD_IEEE802_TR: {
+ struct net_device *dev = skb->dev;
+ struct trh_hdr *trh;
+
+ skb->mac.raw = skb_push(skb, sizeof(*trh));
+ trh = tr_hdr(skb);
+ 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;
+ struct ethhdr *eth;
+
+ skb->mac.raw = skb_push(skb, sizeof(*eth));
+ eth = eth_hdr(skb);
+ eth->h_proto = htons(len);
+ memcpy(eth->h_dest, da, ETH_ALEN);
+ memcpy(eth->h_source, sa, ETH_ALEN);
+ break;
+ }
+ default:
+ printk(KERN_WARNING "device type not supported: %d\n",
+ skb->dev->type);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+/**
+ * llc_build_and_send_ui_pkt - unitdata request interface for upper layers
+ * @sap: sap to use
+ * @skb: packet to send
+ * @dmac: destination mac address
+ * @dsap: destination sap
+ *
+ * Upper layers calls this function when upper layer wants to send data
+ * using connection-less mode communication (UI pdu).
+ *
+ * Accept data frame from network layer to be sent using connection-
+ * less mode communication; timeout/retries handled by network layer;
+ * package primitive as an event and send to SAP event handler
+ */
+int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb,
+ unsigned char *dmac, unsigned char dsap)
+{
+ int rc;
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
+ dsap, LLC_PDU_CMD);
+ llc_pdu_init_as_ui_cmd(skb);
+ rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac);
+ if (!rc)
+ rc = dev_queue_xmit(skb);
+ return rc;
+}
+
+EXPORT_SYMBOL(llc_mac_hdr_init);
+EXPORT_SYMBOL(llc_build_and_send_ui_pkt);
diff --git a/net/llc/llc_output.h b/net/llc/llc_output.h
new file mode 100644
index 000000000000..179edf753f00
--- /dev/null
+++ b/net/llc/llc_output.h
@@ -0,0 +1,20 @@
+#ifndef LLC_OUTPUT_H
+#define LLC_OUTPUT_H
+/*
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License version 2 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 version 2 for more details.
+ */
+
+struct sk_buff;
+
+int llc_mac_hdr_init(struct sk_buff *skb, unsigned char *sa, unsigned char *da);
+
+#endif /* LLC_OUTPUT_H */
diff --git a/net/llc/llc_pdu.c b/net/llc/llc_pdu.c
new file mode 100644
index 000000000000..a28ce525d201
--- /dev/null
+++ b/net/llc/llc_pdu.c
@@ -0,0 +1,372 @@
+/*
+ * llc_pdu.c - access to PDU internals
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/netdevice.h>
+#include <net/llc_pdu.h>
+
+static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
+static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
+
+void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
+{
+ llc_pdu_un_hdr(skb)->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;
+ struct llc_pdu_sn *pdu;
+
+ llc_pdu_decode_pdu_type(skb, &pdu_type);
+ pdu = llc_pdu_sn_hdr(skb);
+
+ switch (pdu_type) {
+ case LLC_PDU_TYPE_I:
+ case LLC_PDU_TYPE_S:
+ pdu->ctrl_2 = (pdu->ctrl_2 & 0xFE) | bit_value;
+ break;
+ case LLC_PDU_TYPE_U:
+ pdu->ctrl_1 |= (pdu->ctrl_1 & 0xEF) | (bit_value << 4);
+ break;
+ }
+}
+
+/**
+ * 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.
+ */
+void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
+{
+ u8 pdu_type;
+ struct llc_pdu_sn *pdu;
+
+ llc_pdu_decode_pdu_type(skb, &pdu_type);
+ pdu = llc_pdu_sn_hdr(skb);
+
+ 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;
+ }
+}
+
+/**
+ * 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.
+ */
+void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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;
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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;
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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;
+}
+
+/**
+ * llc_pdu_init_as_frmr_rsp - builds FRMR response PDU
+ * @skb: 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.
+ */
+void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
+ u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
+{
+ struct llc_frmr_info *frmr_info;
+ u8 prev_pf = 0;
+ u8 *ctrl;
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 = (struct llc_frmr_info *)&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);
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_pdu_init_as_rnr_rsp - builds RNR response pdu
+ * @skb: 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.
+ */
+void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
+{
+ struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
+
+ 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 */
+}
+
+/**
+ * llc_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.
+ */
+void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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;
+}
+
+/**
+ * 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 void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
+{
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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;
+}
+
+/**
+ * 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(struct llc_pdu_sn *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_proc.c b/net/llc/llc_proc.c
new file mode 100644
index 000000000000..36e8db3fa1a2
--- /dev/null
+++ b/net/llc/llc_proc.c
@@ -0,0 +1,267 @@
+/*
+ * proc_llc.c - proc interface for LLC
+ *
+ * Copyright (c) 2001 by Jay Schulist <jschlst@samba.org>
+ * 2002-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/errno.h>
+#include <linux/seq_file.h>
+#include <net/sock.h>
+#include <net/llc.h>
+#include <net/llc_c_ac.h>
+#include <net/llc_c_ev.h>
+#include <net/llc_c_st.h>
+#include <net/llc_conn.h>
+
+static void llc_ui_format_mac(struct seq_file *seq, unsigned char *mac)
+{
+ seq_printf(seq, "%02X:%02X:%02X:%02X:%02X:%02X",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+}
+
+static struct sock *llc_get_sk_idx(loff_t pos)
+{
+ struct list_head *sap_entry;
+ struct llc_sap *sap;
+ struct hlist_node *node;
+ struct sock *sk = NULL;
+
+ list_for_each(sap_entry, &llc_sap_list) {
+ sap = list_entry(sap_entry, struct llc_sap, node);
+
+ read_lock_bh(&sap->sk_list.lock);
+ sk_for_each(sk, node, &sap->sk_list.list) {
+ if (!pos)
+ goto found;
+ --pos;
+ }
+ read_unlock_bh(&sap->sk_list.lock);
+ }
+ sk = NULL;
+found:
+ return sk;
+}
+
+static void *llc_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ loff_t l = *pos;
+
+ read_lock_bh(&llc_sap_list_lock);
+ return l ? llc_get_sk_idx(--l) : SEQ_START_TOKEN;
+}
+
+static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ struct sock* sk, *next;
+ struct llc_sock *llc;
+ struct llc_sap *sap;
+
+ ++*pos;
+ if (v == SEQ_START_TOKEN) {
+ sk = llc_get_sk_idx(0);
+ goto out;
+ }
+ sk = v;
+ next = sk_next(sk);
+ if (next) {
+ sk = next;
+ goto out;
+ }
+ llc = llc_sk(sk);
+ sap = llc->sap;
+ read_unlock_bh(&sap->sk_list.lock);
+ sk = NULL;
+ for (;;) {
+ if (sap->node.next == &llc_sap_list)
+ break;
+ sap = list_entry(sap->node.next, struct llc_sap, node);
+ read_lock_bh(&sap->sk_list.lock);
+ if (!hlist_empty(&sap->sk_list.list)) {
+ sk = sk_head(&sap->sk_list.list);
+ break;
+ }
+ read_unlock_bh(&sap->sk_list.lock);
+ }
+out:
+ return sk;
+}
+
+static void llc_seq_stop(struct seq_file *seq, void *v)
+{
+ if (v && v != SEQ_START_TOKEN) {
+ struct sock *sk = v;
+ struct llc_sock *llc = llc_sk(sk);
+ struct llc_sap *sap = llc->sap;
+
+ read_unlock_bh(&sap->sk_list.lock);
+ }
+ read_unlock_bh(&llc_sap_list_lock);
+}
+
+static int llc_seq_socket_show(struct seq_file *seq, void *v)
+{
+ struct sock* sk;
+ struct llc_sock *llc;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(seq, "SKt Mc local_mac_sap remote_mac_sap "
+ " tx_queue rx_queue st uid link\n");
+ goto out;
+ }
+ sk = v;
+ llc = llc_sk(sk);
+
+ /* FIXME: check if the address is multicast */
+ seq_printf(seq, "%2X %2X ", sk->sk_type, 0);
+
+ if (llc->dev)
+ llc_ui_format_mac(seq, llc->dev->dev_addr);
+ else
+ seq_printf(seq, "00:00:00:00:00:00");
+ seq_printf(seq, "@%02X ", llc->sap->laddr.lsap);
+ llc_ui_format_mac(seq, llc->daddr.mac);
+ seq_printf(seq, "@%02X %8d %8d %2d %3d %4d\n", llc->daddr.lsap,
+ atomic_read(&sk->sk_wmem_alloc),
+ atomic_read(&sk->sk_rmem_alloc),
+ sk->sk_state,
+ sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1,
+ llc->link);
+out:
+ return 0;
+}
+
+static char *llc_conn_state_names[] = {
+ [LLC_CONN_STATE_ADM] = "adm",
+ [LLC_CONN_STATE_SETUP] = "setup",
+ [LLC_CONN_STATE_NORMAL] = "normal",
+ [LLC_CONN_STATE_BUSY] = "busy",
+ [LLC_CONN_STATE_REJ] = "rej",
+ [LLC_CONN_STATE_AWAIT] = "await",
+ [LLC_CONN_STATE_AWAIT_BUSY] = "await_busy",
+ [LLC_CONN_STATE_AWAIT_REJ] = "await_rej",
+ [LLC_CONN_STATE_D_CONN] = "d_conn",
+ [LLC_CONN_STATE_RESET] = "reset",
+ [LLC_CONN_STATE_ERROR] = "error",
+ [LLC_CONN_STATE_TEMP] = "temp",
+};
+
+static int llc_seq_core_show(struct seq_file *seq, void *v)
+{
+ struct sock* sk;
+ struct llc_sock *llc;
+
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(seq, "Connection list:\n"
+ "dsap state retr txw rxw pf ff sf df rs cs "
+ "tack tpfc trs tbs blog busr\n");
+ goto out;
+ }
+ sk = v;
+ llc = llc_sk(sk);
+
+ seq_printf(seq, " %02X %-10s %3d %3d %3d %2d %2d %2d %2d %2d %2d "
+ "%4d %4d %3d %3d %4d %4d\n",
+ llc->daddr.lsap, llc_conn_state_names[llc->state],
+ llc->retry_count, llc->k, llc->rw, llc->p_flag, llc->f_flag,
+ llc->s_flag, llc->data_flag, llc->remote_busy_flag,
+ llc->cause_flag, timer_pending(&llc->ack_timer.timer),
+ timer_pending(&llc->pf_cycle_timer.timer),
+ timer_pending(&llc->rej_sent_timer.timer),
+ timer_pending(&llc->busy_state_timer.timer),
+ !!sk->sk_backlog.tail, !!sock_owned_by_user(sk));
+out:
+ return 0;
+}
+
+static struct seq_operations llc_seq_socket_ops = {
+ .start = llc_seq_start,
+ .next = llc_seq_next,
+ .stop = llc_seq_stop,
+ .show = llc_seq_socket_show,
+};
+
+static struct seq_operations llc_seq_core_ops = {
+ .start = llc_seq_start,
+ .next = llc_seq_next,
+ .stop = llc_seq_stop,
+ .show = llc_seq_core_show,
+};
+
+static int llc_seq_socket_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &llc_seq_socket_ops);
+}
+
+static int llc_seq_core_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &llc_seq_core_ops);
+}
+
+static struct file_operations llc_seq_socket_fops = {
+ .owner = THIS_MODULE,
+ .open = llc_seq_socket_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations llc_seq_core_fops = {
+ .owner = THIS_MODULE,
+ .open = llc_seq_core_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct proc_dir_entry *llc_proc_dir;
+
+int __init llc_proc_init(void)
+{
+ int rc = -ENOMEM;
+ struct proc_dir_entry *p;
+
+ llc_proc_dir = proc_mkdir("llc", proc_net);
+ if (!llc_proc_dir)
+ goto out;
+ llc_proc_dir->owner = THIS_MODULE;
+
+ p = create_proc_entry("socket", S_IRUGO, llc_proc_dir);
+ if (!p)
+ goto out_socket;
+
+ p->proc_fops = &llc_seq_socket_fops;
+
+ p = create_proc_entry("core", S_IRUGO, llc_proc_dir);
+ if (!p)
+ goto out_core;
+
+ p->proc_fops = &llc_seq_core_fops;
+
+ rc = 0;
+out:
+ return rc;
+out_core:
+ remove_proc_entry("socket", llc_proc_dir);
+out_socket:
+ remove_proc_entry("llc", proc_net);
+ goto out;
+}
+
+void llc_proc_exit(void)
+{
+ remove_proc_entry("socket", llc_proc_dir);
+ remove_proc_entry("core", llc_proc_dir);
+ remove_proc_entry("llc", proc_net);
+}
diff --git a/net/llc/llc_s_ac.c b/net/llc/llc_s_ac.c
new file mode 100644
index 000000000000..ed8ba7de6122
--- /dev/null
+++ b/net/llc/llc_s_ac.c
@@ -0,0 +1,205 @@
+/*
+ * 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-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <linux/netdevice.h>
+#include <net/llc.h>
+#include <net/llc_pdu.h>
+#include <net/llc_s_ac.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_sap.h>
+#include "llc_output.h"
+
+/**
+ * llc_sap_action_unit_data_ind - forward UI PDU to network layer
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ llc_sap_rtn_pdu(sap, skb);
+ return 0;
+}
+
+/**
+ * llc_sap_action_send_ui - sends UI PDU resp to UNITDATA REQ to MAC layer
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ int rc;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
+ ev->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_ui_cmd(skb);
+ rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
+ if (!rc)
+ rc = dev_queue_xmit(skb);
+ return rc;
+}
+
+/**
+ * llc_sap_action_send_xid_c - send XID PDU as response to XID REQ
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ int rc;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
+ ev->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_xid_cmd(skb, LLC_XID_NULL_CLASS_2, 0);
+ rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
+ if (!rc)
+ rc = dev_queue_xmit(skb);
+ return rc;
+}
+
+/**
+ * llc_sap_action_send_xid_r - send XID PDU resp to MAC for received XID
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff *nskb;
+
+ llc_pdu_decode_sa(skb, mac_da);
+ llc_pdu_decode_da(skb, mac_sa);
+ llc_pdu_decode_ssap(skb, &dsap);
+ nskb = llc_alloc_frame();
+ if (!nskb)
+ goto out;
+ nskb->dev = skb->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
+ LLC_PDU_RSP);
+ llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 0);
+ rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
+ if (!rc)
+ rc = dev_queue_xmit(nskb);
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_action_send_test_c - send TEST PDU to MAC in resp to TEST REQ
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ int rc;
+
+ llc_pdu_header_init(skb, LLC_PDU_TYPE_U, ev->saddr.lsap,
+ ev->daddr.lsap, LLC_PDU_CMD);
+ llc_pdu_init_as_test_cmd(skb);
+ rc = llc_mac_hdr_init(skb, ev->saddr.mac, ev->daddr.mac);
+ if (!rc)
+ rc = dev_queue_xmit(skb);
+ return rc;
+}
+
+int llc_sap_action_send_test_r(struct llc_sap *sap, struct sk_buff *skb)
+{
+ u8 mac_da[ETH_ALEN], mac_sa[ETH_ALEN], dsap;
+ struct sk_buff *nskb;
+ int rc = 1;
+
+ llc_pdu_decode_sa(skb, mac_da);
+ llc_pdu_decode_da(skb, mac_sa);
+ llc_pdu_decode_ssap(skb, &dsap);
+ nskb = llc_alloc_frame();
+ if (!nskb)
+ goto out;
+ nskb->dev = skb->dev;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, sap->laddr.lsap, dsap,
+ LLC_PDU_RSP);
+ llc_pdu_init_as_test_rsp(nskb, skb);
+ rc = llc_mac_hdr_init(nskb, mac_sa, mac_da);
+ if (!rc)
+ rc = dev_queue_xmit(nskb);
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_action_report_status - report data link status to layer mgmt
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ return 0;
+}
+
+/**
+ * llc_sap_action_xid_ind - send XID PDU resp to net layer via XID IND
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ llc_sap_rtn_pdu(sap, skb);
+ return 0;
+}
+
+/**
+ * llc_sap_action_test_ind - send TEST PDU to net layer via TEST IND
+ * @sap: SAP
+ * @skb: 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 sk_buff *skb)
+{
+ llc_sap_rtn_pdu(sap, skb);
+ return 0;
+}
diff --git a/net/llc/llc_s_ev.c b/net/llc/llc_s_ev.c
new file mode 100644
index 000000000000..a74d2a1d6581
--- /dev/null
+++ b/net/llc/llc_s_ev.c
@@ -0,0 +1,115 @@
+/*
+ * 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-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
+ ev->prim_type == LLC_SAP_EV_ACTIVATION_REQ ? 0 : 1;
+}
+
+int llc_sap_ev_rx_ui(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ return ev->type == LLC_SAP_EV_TYPE_PRIM &&
+ ev->prim == LLC_DATAUNIT_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+
+}
+
+int llc_sap_ev_xid_req(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ return ev->type == LLC_SAP_EV_TYPE_PRIM &&
+ ev->prim == LLC_XID_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_sap_ev_rx_xid_c(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ return ev->type == LLC_SAP_EV_TYPE_PRIM &&
+ ev->prim == LLC_TEST_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+int llc_sap_ev_rx_test_c(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ return ev->type == LLC_SAP_EV_TYPE_SIMPLE &&
+ ev->prim_type == 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..6a43201aa32e
--- /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-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/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_end;
+
+/* 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_end,
+};
+
+/* 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_end,
+};
+
+/* SAP state transition table */
+struct llc_sap_state llc_sap_state_table[LLC_NR_SAP_STATES] = {
+ [LLC_SAP_STATE_INACTIVE - 1] = {
+ .curr_state = LLC_SAP_STATE_INACTIVE,
+ .transitions = llc_sap_inactive_state_transitions,
+ },
+ [LLC_SAP_STATE_ACTIVE - 1] = {
+ .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..965c94eb4bbc
--- /dev/null
+++ b/net/llc/llc_sap.c
@@ -0,0 +1,316 @@
+/*
+ * llc_sap.c - driver routines for SAP component.
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+
+#include <net/llc.h>
+#include <net/llc_if.h>
+#include <net/llc_conn.h>
+#include <net/llc_pdu.h>
+#include <net/llc_sap.h>
+#include <net/llc_s_ac.h>
+#include <net/llc_s_ev.h>
+#include <net/llc_s_st.h>
+#include <net/sock.h>
+#include <linux/tcp.h>
+#include <linux/llc.h>
+
+/**
+ * llc_alloc_frame - allocates sk_buff for frame
+ *
+ * Allocates an sk_buff for frame and initializes sk_buff fields.
+ * Returns allocated skb or %NULL when out of memory.
+ */
+struct sk_buff *llc_alloc_frame(void)
+{
+ struct sk_buff *skb = alloc_skb(128, GFP_ATOMIC);
+
+ if (skb) {
+ skb_reserve(skb, 50);
+ skb->nh.raw = skb->h.raw = skb->data;
+ skb->protocol = htons(ETH_P_802_2);
+ skb->dev = dev_base->next;
+ skb->mac.raw = skb->head;
+ }
+ return skb;
+}
+
+void llc_save_primitive(struct sk_buff* skb, u8 prim)
+{
+ struct sockaddr_llc *addr = llc_ui_skb_cb(skb);
+
+ /* save primitive for use by the user. */
+ addr->sllc_family = skb->sk->sk_family;
+ addr->sllc_arphrd = skb->dev->type;
+ addr->sllc_test = prim == LLC_TEST_PRIM;
+ addr->sllc_xid = prim == LLC_XID_PRIM;
+ addr->sllc_ua = prim == LLC_DATAUNIT_PRIM;
+ llc_pdu_decode_sa(skb, addr->sllc_mac);
+ llc_pdu_decode_ssap(skb, &addr->sllc_sap);
+}
+
+/**
+ * llc_sap_rtn_pdu - Informs upper layer on rx of an UI, XID or TEST pdu.
+ * @sap: pointer to SAP
+ * @skb: received pdu
+ */
+void llc_sap_rtn_pdu(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ switch (LLC_U_PDU_RSP(pdu)) {
+ case LLC_1_PDU_CMD_TEST:
+ ev->prim = LLC_TEST_PRIM; break;
+ case LLC_1_PDU_CMD_XID:
+ ev->prim = LLC_XID_PRIM; break;
+ case LLC_1_PDU_CMD_UI:
+ ev->prim = LLC_DATAUNIT_PRIM; break;
+ }
+ ev->ind_cfm_flag = LLC_IND;
+}
+
+/**
+ * llc_find_sap_trans - finds transition for event
+ * @sap: pointer to SAP
+ * @skb: 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 sk_buff* skb)
+{
+ 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, skb)) {
+ rc = next_trans[i]; /* got event match; return it */
+ 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
+ * @skb: 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 sk_buff *skb)
+{
+ int rc = 0;
+ llc_sap_action_t *next_action = trans->ev_actions;
+
+ for (; next_action && *next_action; next_action++)
+ if ((*next_action)(sap, skb))
+ rc = 1;
+ return rc;
+}
+
+/**
+ * llc_sap_next_state - finds transition, execs actions & change SAP state
+ * @sap: pointer to SAP
+ * @skb: 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 sk_buff *skb)
+{
+ int rc = 1;
+ struct llc_sap_state_trans *trans;
+
+ if (sap->state > LLC_NR_SAP_STATES)
+ goto out;
+ trans = llc_find_sap_trans(sap, skb);
+ if (!trans)
+ goto out;
+ /*
+ * 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, skb);
+ if (rc)
+ goto out;
+ /*
+ * Transition SAP to next state if all actions execute successfully
+ */
+ sap->state = trans->next_state;
+out:
+ return rc;
+}
+
+/**
+ * llc_sap_state_process - sends event to SAP state machine
+ * @sap: sap to use
+ * @skb: pointer to occurred event
+ *
+ * After executing actions of the event, upper layer will be indicated
+ * if needed(on receiving an UI frame). sk can be null for the
+ * datalink_proto case.
+ */
+static void llc_sap_state_process(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ /*
+ * We have to hold the skb, because llc_sap_next_state
+ * will kfree it in the sending path and we need to
+ * look at the skb->cb, where we encode llc_sap_state_ev.
+ */
+ skb_get(skb);
+ ev->ind_cfm_flag = 0;
+ llc_sap_next_state(sap, skb);
+ if (ev->ind_cfm_flag == LLC_IND) {
+ if (skb->sk->sk_state == TCP_LISTEN)
+ kfree_skb(skb);
+ else {
+ llc_save_primitive(skb, ev->prim);
+
+ /* queue skb to the user. */
+ if (sock_queue_rcv_skb(skb->sk, skb))
+ kfree_skb(skb);
+ }
+ }
+ kfree_skb(skb);
+}
+
+/**
+ * llc_build_and_send_test_pkt - TEST interface for upper layers.
+ * @sap: sap to use
+ * @skb: packet to send
+ * @dmac: destination mac address
+ * @dsap: destination sap
+ *
+ * This function is called when upper layer wants to send a TEST pdu.
+ * Returns 0 for success, 1 otherwise.
+ */
+void llc_build_and_send_test_pkt(struct llc_sap *sap,
+ struct sk_buff *skb, u8 *dmac, u8 dsap)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ ev->saddr.lsap = sap->laddr.lsap;
+ ev->daddr.lsap = dsap;
+ memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
+ memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
+
+ ev->type = LLC_SAP_EV_TYPE_PRIM;
+ ev->prim = LLC_TEST_PRIM;
+ ev->prim_type = LLC_PRIM_TYPE_REQ;
+ llc_sap_state_process(sap, skb);
+}
+
+/**
+ * llc_build_and_send_xid_pkt - XID interface for upper layers
+ * @sap: sap to use
+ * @skb: packet to send
+ * @dmac: destination mac address
+ * @dsap: destination sap
+ *
+ * This function is called when upper layer wants to send a XID pdu.
+ * Returns 0 for success, 1 otherwise.
+ */
+void llc_build_and_send_xid_pkt(struct llc_sap *sap, struct sk_buff *skb,
+ u8 *dmac, u8 dsap)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ ev->saddr.lsap = sap->laddr.lsap;
+ ev->daddr.lsap = dsap;
+ memcpy(ev->saddr.mac, skb->dev->dev_addr, IFHWADDRLEN);
+ memcpy(ev->daddr.mac, dmac, IFHWADDRLEN);
+
+ ev->type = LLC_SAP_EV_TYPE_PRIM;
+ ev->prim = LLC_XID_PRIM;
+ ev->prim_type = LLC_PRIM_TYPE_REQ;
+ llc_sap_state_process(sap, skb);
+}
+
+/**
+ * llc_sap_rcv - sends received pdus to the sap state machine
+ * @sap: current sap component structure.
+ * @skb: received frame.
+ *
+ * Sends received pdus to the sap state machine.
+ */
+static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_sap_state_ev *ev = llc_sap_ev(skb);
+
+ ev->type = LLC_SAP_EV_TYPE_PDU;
+ ev->reason = 0;
+ llc_sap_state_process(sap, skb);
+}
+
+/**
+ * llc_lookup_dgram - Finds dgram socket for the local sap/mac
+ * @sap: SAP
+ * @laddr: address of local LLC (MAC + SAP)
+ *
+ * Search socket list of the SAP and finds connection using the local
+ * mac, and local sap. Returns pointer for socket found, %NULL otherwise.
+ */
+static struct sock *llc_lookup_dgram(struct llc_sap *sap,
+ struct llc_addr *laddr)
+{
+ struct sock *rc;
+ struct hlist_node *node;
+
+ read_lock_bh(&sap->sk_list.lock);
+ sk_for_each(rc, node, &sap->sk_list.list) {
+ struct llc_sock *llc = llc_sk(rc);
+
+ if (rc->sk_type == SOCK_DGRAM &&
+ llc->laddr.lsap == laddr->lsap &&
+ llc_mac_match(llc->laddr.mac, laddr->mac)) {
+ sock_hold(rc);
+ goto found;
+ }
+ }
+ rc = NULL;
+found:
+ read_unlock_bh(&sap->sk_list.lock);
+ return rc;
+}
+
+void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
+{
+ struct llc_addr laddr;
+ struct sock *sk;
+
+ llc_pdu_decode_da(skb, laddr.mac);
+ llc_pdu_decode_dsap(skb, &laddr.lsap);
+
+ sk = llc_lookup_dgram(sap, &laddr);
+ if (sk) {
+ skb->sk = sk;
+ llc_sap_rcv(sap, skb);
+ sock_put(sk);
+ } else
+ kfree_skb(skb);
+}
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c
new file mode 100644
index 000000000000..8fe48a24bad5
--- /dev/null
+++ b/net/llc/llc_station.c
@@ -0,0 +1,713 @@
+/*
+ * llc_station.c - station component of LLC
+ *
+ * Copyright (c) 1997 by Procom Technology, Inc.
+ * 2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * This program can be redistributed or modified under the terms of the
+ * GNU General Public License as published by the Free Software Foundation.
+ * This program is distributed without any warranty or implied warranty
+ * of merchantability or fitness for a particular purpose.
+ *
+ * See the GNU General Public License for more details.
+ */
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <net/llc.h>
+#include <net/llc_sap.h>
+#include <net/llc_conn.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_pdu.h>
+
+/**
+ * struct llc_station - LLC station component
+ *
+ * SAP and connection resource manager, one per adapter.
+ *
+ * @state - state of station
+ * @xid_r_count - XID response PDU counter
+ * @mac_sa - MAC source address
+ * @sap_list - list of related SAPs
+ * @ev_q - events entering state mach.
+ * @mac_pdu_q - PDUs ready to send to MAC
+ */
+struct llc_station {
+ u8 state;
+ u8 xid_r_count;
+ struct timer_list ack_timer;
+ u8 retry_count;
+ u8 maximum_retry;
+ struct {
+ struct sk_buff_head list;
+ spinlock_t lock;
+ } ev_q;
+ struct sk_buff_head mac_pdu_q;
+};
+
+/* Types of events (possible values in 'ev->type') */
+#define LLC_STATION_EV_TYPE_SIMPLE 1
+#define LLC_STATION_EV_TYPE_CONDITION 2
+#define LLC_STATION_EV_TYPE_PRIM 3
+#define LLC_STATION_EV_TYPE_PDU 4 /* command/response PDU */
+#define LLC_STATION_EV_TYPE_ACK_TMR 5
+#define LLC_STATION_EV_TYPE_RPT_STATUS 6
+
+/* Events */
+#define LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK 1
+#define LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK 2
+#define LLC_STATION_EV_ACK_TMR_EXP_LT_RETRY_CNT_MAX_RETRY 3
+#define LLC_STATION_EV_ACK_TMR_EXP_EQ_RETRY_CNT_MAX_RETRY 4
+#define LLC_STATION_EV_RX_NULL_DSAP_XID_C 5
+#define LLC_STATION_EV_RX_NULL_DSAP_0_XID_R_XID_R_CNT_EQ 6
+#define LLC_STATION_EV_RX_NULL_DSAP_1_XID_R_XID_R_CNT_EQ 7
+#define LLC_STATION_EV_RX_NULL_DSAP_TEST_C 8
+#define LLC_STATION_EV_DISABLE_REQ 9
+
+struct llc_station_state_ev {
+ u8 type;
+ u8 prim;
+ u8 prim_type;
+ u8 reason;
+ struct list_head node; /* node in station->ev_q.list */
+};
+
+static __inline__ struct llc_station_state_ev *
+ llc_station_ev(struct sk_buff *skb)
+{
+ return (struct llc_station_state_ev *)skb->cb;
+}
+
+typedef int (*llc_station_ev_t)(struct sk_buff *skb);
+
+#define LLC_STATION_STATE_DOWN 1 /* initial state */
+#define LLC_STATION_STATE_DUP_ADDR_CHK 2
+#define LLC_STATION_STATE_UP 3
+
+#define LLC_NBR_STATION_STATES 3 /* size of state table */
+
+typedef int (*llc_station_action_t)(struct sk_buff *skb);
+
+/* Station component state table structure */
+struct llc_station_state_trans {
+ llc_station_ev_t ev;
+ u8 next_state;
+ llc_station_action_t *ev_actions;
+};
+
+struct llc_station_state {
+ u8 curr_state;
+ struct llc_station_state_trans **transitions;
+};
+
+static struct llc_station llc_main_station;
+
+static int llc_stat_ev_enable_with_dup_addr_check(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
+ ev->prim_type ==
+ LLC_STATION_EV_ENABLE_WITH_DUP_ADDR_CHECK ? 0 : 1;
+}
+
+static int llc_stat_ev_enable_without_dup_addr_check(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ return ev->type == LLC_STATION_EV_TYPE_SIMPLE &&
+ ev->prim_type ==
+ LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK ? 0 : 1;
+}
+
+static int llc_stat_ev_ack_tmr_exp_lt_retry_cnt_max_retry(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
+ llc_main_station.retry_count <
+ llc_main_station.maximum_retry ? 0 : 1;
+}
+
+static int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ return ev->type == LLC_STATION_EV_TYPE_ACK_TMR &&
+ llc_main_station.retry_count ==
+ llc_main_station.maximum_retry ? 0 : 1;
+}
+
+static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 */
+}
+
+static int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 */
+ !llc_main_station.xid_r_count ? 0 : 1;
+}
+
+static int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 */
+ llc_main_station.xid_r_count == 1 ? 0 : 1;
+}
+
+static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+ struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
+
+ 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 */
+}
+
+static int llc_stat_ev_disable_req(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ return ev->type == LLC_STATION_EV_TYPE_PRIM &&
+ ev->prim == LLC_DISABLE_PRIM &&
+ ev->prim_type == LLC_PRIM_TYPE_REQ ? 0 : 1;
+}
+
+/**
+ * llc_station_send_pdu - queues PDU to send
+ * @skb: Address of the PDU
+ *
+ * Queues a PDU to send to the MAC layer.
+ */
+static void llc_station_send_pdu(struct sk_buff *skb)
+{
+ skb_queue_tail(&llc_main_station.mac_pdu_q, skb);
+ while ((skb = skb_dequeue(&llc_main_station.mac_pdu_q)) != NULL)
+ if (dev_queue_xmit(skb))
+ break;
+}
+
+static int llc_station_ac_start_ack_timer(struct sk_buff *skb)
+{
+ mod_timer(&llc_main_station.ack_timer, jiffies + LLC_ACK_TIME * HZ);
+ return 0;
+}
+
+static int llc_station_ac_set_retry_cnt_0(struct sk_buff *skb)
+{
+ llc_main_station.retry_count = 0;
+ return 0;
+}
+
+static int llc_station_ac_inc_retry_cnt_by_1(struct sk_buff *skb)
+{
+ llc_main_station.retry_count++;
+ return 0;
+}
+
+static int llc_station_ac_set_xid_r_cnt_0(struct sk_buff *skb)
+{
+ llc_main_station.xid_r_count = 0;
+ return 0;
+}
+
+static int llc_station_ac_inc_xid_r_cnt_by_1(struct sk_buff *skb)
+{
+ llc_main_station.xid_r_count++;
+ return 0;
+}
+
+static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb)
+{
+ int rc = 1;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (!nskb)
+ goto out;
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, 0, LLC_PDU_CMD);
+ llc_pdu_init_as_xid_cmd(nskb, LLC_XID_NULL_CLASS_2, 127);
+ rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, llc_station_mac_sa);
+ if (rc)
+ goto free;
+ llc_station_send_pdu(nskb);
+out:
+ return rc;
+free:
+ kfree_skb(skb);
+ goto out;
+}
+
+static int llc_station_ac_send_xid_r(struct sk_buff *skb)
+{
+ u8 mac_da[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff* nskb = llc_alloc_frame();
+
+ if (!nskb)
+ goto out;
+ rc = 0;
+ nskb->dev = skb->dev;
+ llc_pdu_decode_sa(skb, mac_da);
+ llc_pdu_decode_ssap(skb, &dsap);
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
+ llc_pdu_init_as_xid_rsp(nskb, LLC_XID_NULL_CLASS_2, 127);
+ rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
+ if (rc)
+ goto free;
+ llc_station_send_pdu(nskb);
+out:
+ return rc;
+free:
+ kfree_skb(skb);
+ goto out;
+}
+
+static int llc_station_ac_send_test_r(struct sk_buff *skb)
+{
+ u8 mac_da[ETH_ALEN], dsap;
+ int rc = 1;
+ struct sk_buff *nskb = llc_alloc_frame();
+
+ if (!nskb)
+ goto out;
+ rc = 0;
+ nskb->dev = skb->dev;
+ llc_pdu_decode_sa(skb, mac_da);
+ llc_pdu_decode_ssap(skb, &dsap);
+ llc_pdu_header_init(nskb, LLC_PDU_TYPE_U, 0, dsap, LLC_PDU_RSP);
+ llc_pdu_init_as_test_rsp(nskb, skb);
+ rc = llc_mac_hdr_init(nskb, llc_station_mac_sa, mac_da);
+ if (rc)
+ goto free;
+ llc_station_send_pdu(nskb);
+out:
+ return rc;
+free:
+ kfree_skb(skb);
+ goto out;
+}
+
+static int llc_station_ac_report_status(struct sk_buff *skb)
+{
+ return 0;
+}
+
+/* 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_end;
+
+/* 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_end,
+};
+
+/* 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_end,
+};
+
+/* 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_end,
+};
+
+static struct llc_station_state
+ llc_station_state_table[LLC_NBR_STATION_STATES] = {
+ [LLC_STATION_STATE_DOWN - 1] = {
+ .curr_state = LLC_STATION_STATE_DOWN,
+ .transitions = llc_stat_dwn_state_trans,
+ },
+ [LLC_STATION_STATE_DUP_ADDR_CHK - 1] = {
+ .curr_state = LLC_STATION_STATE_DUP_ADDR_CHK,
+ .transitions = llc_stat_dupaddr_state_trans,
+ },
+ [LLC_STATION_STATE_UP - 1] = {
+ .curr_state = LLC_STATION_STATE_UP,
+ .transitions = llc_stat_up_state_trans,
+ },
+};
+
+/**
+ * llc_exec_station_trans_actions - executes actions for transition
+ * @trans: Address of the transition
+ * @skb: 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_state_trans *trans,
+ struct sk_buff *skb)
+{
+ u16 rc = 0;
+ llc_station_action_t *next_action = trans->ev_actions;
+
+ for (; next_action && *next_action; next_action++)
+ if ((*next_action)(skb))
+ rc = 1;
+ return rc;
+}
+
+/**
+ * llc_find_station_trans - finds transition for this event
+ * @skb: 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 sk_buff *skb)
+{
+ 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[llc_main_station.state - 1];
+
+ for (next_trans = curr_state->transitions; next_trans[i]->ev; i++)
+ if (!next_trans[i]->ev(skb)) {
+ rc = next_trans[i];
+ break;
+ }
+ return rc;
+}
+
+/**
+ * llc_station_free_ev - frees an event
+ * @skb: Address of the event
+ *
+ * Frees an event.
+ */
+static void llc_station_free_ev(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ if (ev->type == LLC_STATION_EV_TYPE_PDU)
+ kfree_skb(skb);
+}
+
+/**
+ * llc_station_next_state - processes event and goes to the next state
+ * @skb: 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 sk_buff *skb)
+{
+ u16 rc = 1;
+ struct llc_station_state_trans *trans;
+
+ if (llc_main_station.state > LLC_NBR_STATION_STATES)
+ goto out;
+ trans = llc_find_station_trans(skb);
+ 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(trans, skb);
+ if (!rc)
+ /* transition station to next state if all actions
+ * execute successfully; done; wait for next event
+ */
+ llc_main_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(skb);
+ return rc;
+}
+
+/**
+ * llc_station_service_events - service events in the queue
+ *
+ * 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 llc_main_station.ev_q.lock.
+ */
+static void llc_station_service_events(void)
+{
+ struct sk_buff *skb;
+
+ while ((skb = skb_dequeue(&llc_main_station.ev_q.list)) != NULL)
+ llc_station_next_state(skb);
+}
+
+/**
+ * llc_station_state_process: queue event and try to process queue.
+ * @skb: 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.
+ */
+static void llc_station_state_process(struct sk_buff *skb)
+{
+ spin_lock_bh(&llc_main_station.ev_q.lock);
+ skb_queue_tail(&llc_main_station.ev_q.list, skb);
+ llc_station_service_events();
+ spin_unlock_bh(&llc_main_station.ev_q.lock);
+}
+
+static void llc_station_ack_tmr_cb(unsigned long timeout_data)
+{
+ struct sk_buff *skb = alloc_skb(0, GFP_ATOMIC);
+
+ if (skb) {
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ ev->type = LLC_STATION_EV_TYPE_ACK_TMR;
+ llc_station_state_process(skb);
+ }
+}
+
+/*
+ * llc_station_rcv - send received pdu to the station state machine
+ * @skb: received frame.
+ *
+ * Sends data unit to station state machine.
+ */
+static void llc_station_rcv(struct sk_buff *skb)
+{
+ struct llc_station_state_ev *ev = llc_station_ev(skb);
+
+ ev->type = LLC_STATION_EV_TYPE_PDU;
+ ev->reason = 0;
+ llc_station_state_process(skb);
+}
+
+int __init llc_station_init(void)
+{
+ u16 rc = -ENOBUFS;
+ struct sk_buff *skb;
+ struct llc_station_state_ev *ev;
+
+ skb_queue_head_init(&llc_main_station.mac_pdu_q);
+ skb_queue_head_init(&llc_main_station.ev_q.list);
+ spin_lock_init(&llc_main_station.ev_q.lock);
+ init_timer(&llc_main_station.ack_timer);
+ llc_main_station.ack_timer.data = (unsigned long)&llc_main_station;
+ llc_main_station.ack_timer.function = llc_station_ack_tmr_cb;
+
+ skb = alloc_skb(0, GFP_ATOMIC);
+ if (!skb)
+ goto out;
+ rc = 0;
+ llc_set_station_handler(llc_station_rcv);
+ ev = llc_station_ev(skb);
+ memset(ev, 0, sizeof(*ev));
+ llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
+ llc_main_station.maximum_retry = 1;
+ llc_main_station.state = LLC_STATION_STATE_DOWN;
+ ev->type = LLC_STATION_EV_TYPE_SIMPLE;
+ ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
+ rc = llc_station_next_state(skb);
+out:
+ return rc;
+}
+
+void __exit llc_station_exit(void)
+{
+ llc_set_station_handler(NULL);
+}