Fix bug in LLC state tables, remove old LLC stack, etc

Additional changes:
. remove last typedefs (for structs) in new LLC stack
. use C99 labeled elements in sysctl_net_802.c and sysctl_net.c
parent d52a86be
#include <linux/skbuff.h>
#define LLC_MODULE
typedef struct llc_struct llc;
typedef struct llc_struct *llcptr;
/*
* LLC private data area structure.
*/
struct llc_struct
{
char eye[4]; /* To recognize llc area in dump */
int retry_count; /* LLC link state variables */
unsigned char name[9]; /* name of this llc instance */
unsigned char s_flag;
unsigned char p_flag;
unsigned char f_flag;
unsigned char data_flag;
unsigned char cause_flag;
unsigned char vs; /* Send state variable */
unsigned char vr; /* Receive state variable */
unsigned char remote_busy;
unsigned char state; /* Current state of type2 llc procedure */
int n1; /* Maximum number of bytes in I pdu 7.8.2 */
int n2; /* Naximum number of retransmissions 7.8.2 */
unsigned char k; /* Transmit window size 7.8.4, tw in IBM doc*/
unsigned char rw; /* Receive window size */
struct
{
/*
* FRMR_RSP info field structure: 5.4.2.3.5 p55
*/
unsigned char cntl1;
unsigned char cntl2;
unsigned char vs;
unsigned char vr_cr;
unsigned char xxyz;
} frmr_info_fld;
/*
* Timers in 7.8.1 page 78
*/
#define P_TIMER 0
#define REJ_TIMER 1
#define ACK_TIMER 2
#define BUSY_TIMER 3
unsigned long timer_expire_time[4];
unsigned char timer_state[4]; /* The state of each timer */
#define TIMER_IDLE 0
#define TIMER_RUNNING 1
#define TIMER_EXPIRED 2
unsigned long timer_interval[4];
struct timer_list tl[4];
/*
* Client entry point, called by the LLC.
*/
void (*llc_event)(struct llc_struct *);
/*
* Mux and Demux variables
*/
char * client_data; /* Pointer to clients context */
unsigned char local_sap;
unsigned char remote_sap ;
char remote_mac[MAX_ADDR_LEN]; /* MAC address of remote session partner */
struct net_device *dev; /* Device we are attached to */
unsigned char llc_mode; /* See doc 7.1 on p70 */
#define MODE_ADM 1
#define MODE_ABM 2
int llc_callbacks; /* Pending callbacks */
#define LLC_CONN_INDICATION 1 /* We have to ensure the names don't */
#define LLC_CONN_CONFIRM 2 /* mix up with the 802 state table */
#define LLC_DATA_INDIC 4
#define LLC_DISC_INDICATION 8
#define LLC_RESET_INDIC_LOC 16
#define LLC_RESET_INDIC_REM 32
#define LLC_RST_CONFIRM 64
#define LLC_FRMR_RECV 128
#define LLC_FRMR_SENT 256
#define LLC_REMOTE_BUSY 512
#define LLC_REMOTE_NOTBUSY 1024
#define LLC_TEST_INDICATION 2048
#define LLC_XID_INDICATION 4096
#define LLC_UI_DATA 8192
struct sk_buff *inc_skb; /* Saved data buffer for indications */
struct sk_buff_head rtq; /* Retransmit queue */
struct sk_buff_head atq; /* Await transit queue */
unsigned char xid_count;
struct llc_struct *nextllc; /* ptr to next llc struct in proto chain */
};
#define ADD_TO_RTQ(skb) skb_queue_tail(&lp->rtq,skb)
#define ADD_TO_ATQ(skb) skb_queue_tail(&lp->atq,skb)
void llc_cancel_timers(llcptr lp);
int llc_decode_frametype(frameptr fr);
llcptr llc_find(void);
int llc_free_acknowledged_skbs(llcptr lp, unsigned char ack);
void llc_handle_xid_indication( char *chsp, short int ll, char *xid_data);
void llc_interpret_pseudo_code(llcptr lp, int pc_label, struct sk_buff *skb, char type);
void llc_add_to_queue(struct sk_buff *skb, struct sk_buff **f, struct sk_buff **b);
void llc_process_otype2_frame(llcptr lp, struct sk_buff *skb, char type);
struct sk_buff *llc_pull_from_atq(llcptr lp);
int llc_resend_ipdu(llcptr lp, unsigned char ack_nr, unsigned char type, char p);
void llc_sendpdu(llcptr lp, char type, char pf, int data_len, char *pdu_data);
void llc_sendipdu(llcptr lp, char type, char pf, struct sk_buff *skb);
void llc_start_timer(llcptr lp, int t);
void llc_stop_timer(llcptr lp, int t);
void llc_timer_expired(llcptr lp, int t);
int llc_validate_seq_nos(llcptr lp, frameptr fr);
int llc_data_request(llcptr lp, struct sk_buff *skb);
void llc_unit_data_request(llcptr lp, int ll, char * data);
void llc_disconnect_request(llcptr lp);
void llc_connect_request(llcptr lp);
void llc_xid_request(llcptr lp, char opt, int data_len, char *pdu_data);
void llc_test_request(llcptr lp, int data_len, char *pdu_data);
int register_cl2llc_client(llcptr llc, const char *device, void (*ops)(llcptr), u8 *rmac, u8 ssap, u8 dsap);
void unregister_cl2llc_client(llcptr lp);
int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb );
...@@ -191,34 +191,34 @@ ...@@ -191,34 +191,34 @@
(info->ind_bits = ( (info->ind_bits & 0xEF) | (((u8) ind) & 0x10))) (info->ind_bits = ( (info->ind_bits & 0xEF) | (((u8) ind) & 0x10)))
/* Sequence-numbered PDU format (4 bytes in length) */ /* Sequence-numbered PDU format (4 bytes in length) */
typedef struct llc_pdu_sn { struct llc_pdu_sn {
u8 dsap; u8 dsap;
u8 ssap; u8 ssap;
u8 ctrl_1; u8 ctrl_1;
u8 ctrl_2; u8 ctrl_2;
} llc_pdu_sn_t; };
/* Un-numbered PDU format (3 bytes in length) */ /* Un-numbered PDU format (3 bytes in length) */
typedef struct llc_pdu_un { struct llc_pdu_un {
u8 dsap; u8 dsap;
u8 ssap; u8 ssap;
u8 ctrl_1; u8 ctrl_1;
} llc_pdu_un_t; };
/* LLC Type 1 XID command/response information fields format */ /* LLC Type 1 XID command/response information fields format */
typedef struct llc_xid_info { struct llc_xid_info {
u8 fmt_id; /* always 0x18 for LLC */ u8 fmt_id; /* always 0x18 for LLC */
u8 type; /* different if NULL/non-NULL LSAP */ u8 type; /* different if NULL/non-NULL LSAP */
u8 rw; /* sender receive window */ u8 rw; /* sender receive window */
} llc_xid_info_t; };
/* LLC Type 2 FRMR response information field format */ /* LLC Type 2 FRMR response information field format */
typedef struct llc_frmr_info { struct llc_frmr_info {
u16 rej_pdu_ctrl; /* bits 1-8 if U-PDU */ u16 rej_pdu_ctrl; /* bits 1-8 if U-PDU */
u8 curr_ssv; /* current send state variable val */ u8 curr_ssv; /* current send state variable val */
u8 curr_rsv; /* current receive state variable */ u8 curr_rsv; /* current receive state variable */
u8 ind_bits; /* indicator bits set with macro */ u8 ind_bits; /* indicator bits set with macro */
} llc_frmr_info_t; };
extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type); extern void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 type);
extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value); extern void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value);
...@@ -246,7 +246,8 @@ extern int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported, ...@@ -246,7 +246,8 @@ extern int llc_pdu_init_as_xid_rsp(struct sk_buff *skb, u8 svcs_supported,
u8 rx_window); u8 rx_window);
extern int llc_pdu_init_as_test_rsp(struct sk_buff *skb, extern int llc_pdu_init_as_test_rsp(struct sk_buff *skb,
struct sk_buff *ev_skb); struct sk_buff *ev_skb);
extern int llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, llc_pdu_sn_t *prev_pdu, extern int 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); u8 f_bit, u8 vs, u8 vr, u8 vzyxw);
extern int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); extern int llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
extern int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr); extern int llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr);
......
...@@ -2,15 +2,14 @@ ...@@ -2,15 +2,14 @@
# Makefile for the Linux 802.x protocol layers. # Makefile for the Linux 802.x protocol layers.
# #
export-objs := llc_macinit.o p8022.o psnap.o export-objs := p8022.o psnap.o tr.o
obj-y := p8023.o obj-y := p8023.o
# Check the p8022 selections against net/core/Makefile. # Check the p8022 selections against net/core/Makefile.
obj-$(CONFIG_SYSCTL) += sysctl_net_802.o obj-$(CONFIG_SYSCTL) += sysctl_net_802.o
obj-$(CONFIG_LLC) += p8022.o psnap.o llc_sendpdu.o llc_utility.o \ obj-$(CONFIG_LLC) += p8022.o psnap.o
cl2llc.o llc_macinit.o obj-$(CONFIG_TR) += p8022.o psnap.o tr.o sysctl_net_802.o
obj-$(CONFIG_TR) += p8022.o psnap.o tr.o
obj-$(CONFIG_NET_FC) += fc.o obj-$(CONFIG_NET_FC) += fc.o
obj-$(CONFIG_FDDI) += fddi.o obj-$(CONFIG_FDDI) += fddi.o
obj-$(CONFIG_HIPPI) += hippi.o obj-$(CONFIG_HIPPI) += hippi.o
...@@ -18,25 +17,3 @@ obj-$(CONFIG_IPX) += p8022.o psnap.o ...@@ -18,25 +17,3 @@ obj-$(CONFIG_IPX) += p8022.o psnap.o
obj-$(CONFIG_ATALK) += p8022.o psnap.o obj-$(CONFIG_ATALK) += p8022.o psnap.o
include $(TOPDIR)/Rules.make include $(TOPDIR)/Rules.make
# Dependencies on generated files need to be listed explicitly
$(obj)/cl2llc.o: $(obj)/transit/pdutr.h $(obj)/transit/timertr.h \
$(obj)/pseudo/pseudocode.h
# Generated files
$(obj)/transit/pdutr.h: $(src)/transit/pdutr.pre $(src)/transit/compile.awk
awk -f $(src)/transit/compile.awk $< >$@
$(obj)/transit/timertr.h: $(src)/transit/timertr.pre $(src)/transit/compile.awk
awk -f $(src)/transit/compile.awk $< >$@
$(obj)/pseudo/pseudocode.h: $(src)/pseudo/pseudocode \
$(src)/pseudo/opcd2num.sed \
$(src)/pseudo/compile.awk
sed -f $(src)/pseudo/opcd2num.sed $< | \
awk -f $(src)/pseudo/compile.awk >$@
$(obj)/cl2llc.c: $(src)/cl2llc.pre $(src)/pseudo/opcd2num.sed
sed -f $(src)/pseudo/opcd2num.sed $< >$@
Remaining Problems:
1. Serialization of access to variables in the llc structure
by mac_data_indicate(), timer expired functions, and data_request() .
There is not serialization of any kind right now.
While testing, I have not seen any problems that stem from this lack of
serialization, but it wories me...
2. The code is currently able to handle one connection only,
there is more work in register_cl2llc_client() to make a chain
of llc structures and in mac_data_indicate() to find back
the llc structure addressed by an incoming frame.
According to IEEE, connections are identified by (remote mac + local mac
+ dsap + ssap). dsap and ssap do not seem important: existing applications
always use the same dsap/ssap. Its probably sufficient to index on
the remote mac only.
3. There is no test to see if the transmit window is full in data_request()
as described in the doc p73, "7.5.1 Sending I PDUs" 3th alinea.
The pdus presented to data_request() could probably go on the
awaiting-transmit-queue (atq). The real difficulty is coding a test
to see if the transmit window is used up and to send the queue
when space in the window becomes available.
As I have no network layer that can generate a continous flow of pdus it is
difficult to simulate a remote busy condition and hence to test the code
to handle it.
4. A simple flow control algorithm, steering the size of the transmit
window would be nice to have.
This diff is collapsed.
/*
* NET An implementation of the IEEE 802.2 LLC protocol for the
* LINUX operating system. LLC is implemented as a set of
* state machines and callbacks for higher networking layers.
*
* Code for initialization, termination, registration and
* MAC layer glue.
*
* Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Changes
* Alan Cox : Chainsawed to Linux format
* Added llc_ to names
* Started restructuring handlers
*
* Horst von Brand : Add #include <linux/string.h>
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/unistd.h>
#include <linux/string.h>
#include <linux/netdevice.h>
#include <linux/init.h>
#include <net/p8022.h>
#include <asm/byteorder.h>
#include <net/llc_frame.h>
#include <net/llc.h>
/*
* All incoming frames pass thru mac_data_indicate().
* On entry the llc structure related to the frame is passed as parameter.
* The received sk_buffs with pdus other than I_CMD and I_RSP
* are freed by mac_data_indicate() after processing,
* the I pdu buffers are freed by the cl2llc client when it no longer needs
* the skb.
*/
int llc_mac_data_indicate(llcptr lp, struct sk_buff *skb)
{
int ll; /* logical length == 802.3 length field */
unsigned char p_flag;
unsigned char type;
frameptr fr;
int free=1;
lp->inc_skb=NULL;
/*
* Truncate buffer to true 802.3 length
* [FIXME: move to 802.2 demux]
*/
ll = *(skb->data -2) * 256 + *(skb->data -1);
skb_trim( skb, ll );
fr = (frameptr) skb->data;
type = llc_decode_frametype( fr );
if (type <= FRMR_RSP)
{
/*
* PDU is of the type 2 set
*/
if ((lp->llc_mode == MODE_ABM)||(type == SABME_CMD))
llc_process_otype2_frame(lp, skb, type);
}
else
{
/*
* PDU belongs to type 1 set
*/
p_flag = fr->u_hdr.u_pflag;
switch(type)
{
case TEST_CMD:
llc_sendpdu(lp, TEST_RSP, 0,ll -3,
fr->u_hdr.u_info);
break;
case TEST_RSP:
lp->llc_callbacks|=LLC_TEST_INDICATION;
lp->inc_skb=skb;
free=0;
break;
case XID_CMD:
/*
* Basic format XID is handled by LLC itself
* Doc 5.4.1.1.2 p 48/49
*/
if ((ll == 6)&&(fr->u_hdr.u_info[0] == 0x81))
{
lp->k = fr->u_hdr.u_info[2];
llc_sendpdu(lp, XID_RSP,
fr->u_hdr.u_pflag, ll -3,
fr->u_hdr.u_info);
}
break;
case XID_RSP:
if( ll == 6 && fr->u_hdr.u_info[0] == 0x81 )
{
lp->k = fr->u_hdr.u_info[2];
}
lp->llc_callbacks|=LLC_XID_INDICATION;
lp->inc_skb=skb;
free=0;
break;
case UI_CMD:
lp->llc_callbacks|=LLC_UI_DATA;
skb_pull(skb,3);
lp->inc_skb=skb;
free=0;
break;
default:;
/*
* All other type 1 pdus ignored for now
*/
}
}
if (free&&(!(IS_IFRAME(fr))))
{
/*
* No auto free for I pdus
*/
skb->sk = NULL;
kfree_skb(skb);
}
if(lp->llc_callbacks)
{
if ( lp->llc_event != NULL ) lp->llc_event(lp);
lp->llc_callbacks=0;
}
return 0;
}
/*
* Create an LLC client. As it is the job of the caller to clean up
* LLC's on device down, the device list must be locked before this call.
*/
int register_cl2llc_client(llcptr lp, const char *device, void (*event)(llcptr), u8 *rmac, u8 ssap, u8 dsap)
{
char eye_init[] = "LLC\0";
memset(lp, 0, sizeof(*lp));
lp->dev = __dev_get_by_name(device);
if(lp->dev == NULL)
return -ENODEV;
memcpy(lp->eye, eye_init, sizeof(lp->eye));
lp->rw = 1;
lp->k = 127;
lp->n1 = 1490;
lp->n2 = 10;
lp->timer_interval[P_TIMER] = HZ; /* 1 sec */
lp->timer_interval[REJ_TIMER] = HZ/8;
lp->timer_interval[ACK_TIMER] = HZ/8;
lp->timer_interval[BUSY_TIMER] = HZ*2;
lp->local_sap = ssap;
lp->llc_event = event;
memcpy(lp->remote_mac, rmac, sizeof(lp->remote_mac));
lp->state = 0;
lp->llc_mode = MODE_ADM;
lp->remote_sap = dsap;
skb_queue_head_init(&lp->atq);
skb_queue_head_init(&lp->rtq);
MOD_INC_USE_COUNT;
return 0;
}
void unregister_cl2llc_client(llcptr lp)
{
llc_cancel_timers(lp);
MOD_DEC_USE_COUNT;
kfree(lp);
}
EXPORT_SYMBOL(register_cl2llc_client);
EXPORT_SYMBOL(unregister_cl2llc_client);
EXPORT_SYMBOL(llc_data_request);
EXPORT_SYMBOL(llc_unit_data_request);
EXPORT_SYMBOL(llc_test_request);
EXPORT_SYMBOL(llc_xid_request);
EXPORT_SYMBOL(llc_mac_data_indicate);
EXPORT_SYMBOL(llc_cancel_timers);
#define ALL_TYPES_8022 0
static int __init llc_init(void)
{
printk(KERN_NOTICE "IEEE 802.2 LLC for Linux 2.1 (c) 1996 Tim Alpaerts\n");
return 0;
}
module_init(llc_init);
/*
* NET An implementation of the IEEE 802.2 LLC protocol for the
* LINUX operating system. LLC is implemented as a set of
* state machines and callbacks for higher networking layers.
*
* llc_sendpdu(), llc_sendipdu(), resend() + queue handling code
*
* Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Changes
* Alan Cox : Chainsawed into Linux format, style
* Added llc_ to function names
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/p8022.h>
#include <linux/stat.h>
#include <asm/byteorder.h>
#include <net/llc_frame.h>
#include <net/llc.h>
static unsigned char cntl_byte_encode[] =
{
0x00, /* I_CMD */
0x01, /* RR_CMD */
0x05, /* RNR_CMD */
0x09, /* REJ_CMD */
0x43, /* DISC_CMD */
0x7F, /* SABME_CMD */
0x00, /* I_RSP */
0x01, /* RR_RSP */
0x05, /* RNR_RSP */
0x09, /* REJ_RSP */
0x63, /* UA_RSP */
0x0F, /* DM_RSP */
0x87, /* FRMR_RSP */
0xFF, /* BAD_FRAME */
0x03, /* UI_CMD */
0xBF, /* XID_CMD */
0xE3, /* TEST_CMD */
0xBF, /* XID_RSP */
0xE3 /* TEST_RSP */
};
static unsigned char fr_length_encode[] =
{
0x04, /* I_CMD */
0x04, /* RR_CMD */
0x04, /* RNR_CMD */
0x04, /* REJ_CMD */
0x03, /* DISC_CMD */
0x03, /* SABME_CMD */
0x04, /* I_RSP */
0x04, /* RR_RSP */
0x04, /* RNR_RSP */
0x04, /* REJ_RSP */
0x03, /* UA_RSP */
0x03, /* DM_RSP */
0x03, /* FRMR_RSP */
0x00, /* BAD_FRAME */
0x03, /* UI_CMD */
0x03, /* XID_CMD */
0x03, /* TEST_CMD */
0x03, /* XID_RSP */
0x03 /* TEST_RSP */
};
static unsigned char cr_bit_encode[] = {
0x00, /* I_CMD */
0x00, /* RR_CMD */
0x00, /* RNR_CMD */
0x00, /* REJ_CMD */
0x00, /* DISC_CMD */
0x00, /* SABME_CMD */
0x01, /* I_RSP */
0x01, /* RR_RSP */
0x01, /* RNR_RSP */
0x01, /* REJ_RSP */
0x01, /* UA_RSP */
0x01, /* DM_RSP */
0x01, /* FRMR_RSP */
0x00, /* BAD_FRAME */
0x00, /* UI_CMD */
0x00, /* XID_CMD */
0x00, /* TEST_CMD */
0x01, /* XID_RSP */
0x01 /* TEST_RSP */
};
/*
* Sendpdu() constructs an output frame in a new skb and
* gives it to the MAC layer for transmission.
* This function is not used to send I pdus.
* No queues are updated here, nothing is saved for retransmission.
*
* Parameter pf controls both the poll/final bit and dsap
* fields in the output pdu.
* The dsap trick was needed to implement XID_CMD send with
* zero dsap field as described in doc 6.6 item 1 of enum.
*/
void llc_sendpdu(llcptr lp, char type, char pf, int data_len, char *pdu_data)
{
frameptr fr; /* ptr to output pdu buffer */
unsigned short int fl; /* frame length == 802.3 "length" value */
struct sk_buff *skb;
fl = data_len + fr_length_encode[(int)type];
skb = alloc_skb(16 + fl, GFP_ATOMIC);
if (skb != NULL)
{
skb->dev = lp->dev;
skb_reserve(skb, 16);
fr = (frameptr) skb_put(skb, fl);
memset(fr, 0, fl);
/*
* Construct 802.2 header
*/
if (pf & 0x02)
fr->pdu_hdr.dsap = 0;
else
fr->pdu_hdr.dsap = lp->remote_sap;
fr->pdu_hdr.ssap = lp->local_sap + cr_bit_encode[(int)type];
fr->pdu_cntl.byte1 = cntl_byte_encode[(int)type];
/*
* Fill in pflag and seq nbrs:
*/
if (IS_SFRAME(fr))
{
/* case S-frames */
if (pf & 0x01)
fr->i_hdr.i_pflag = 1;
fr->i_hdr.nr = lp->vr;
}
else
{
/* case U frames */
if (pf & 0x01)
fr->u_hdr.u_pflag = 1;
}
if (data_len > 0)
{ /* append data if any */
if (IS_UFRAME(fr))
{
memcpy(fr->u_hdr.u_info, pdu_data, data_len);
}
else
{
memcpy(fr->i_hdr.is_info, pdu_data, data_len);
}
}
lp->dev->hard_header(skb, lp->dev, ETH_P_802_3,
lp->remote_mac, NULL, fl);
skb->dev=lp->dev;
dev_queue_xmit(skb);
}
else
printk(KERN_DEBUG "cl2llc: skb_alloc() in llc_sendpdu() failed\n");
}
void llc_xid_request(llcptr lp, char opt, int ll, char * data)
{
llc_sendpdu(lp, XID_CMD, opt, ll, data);
}
void llc_test_request(llcptr lp, int ll, char * data)
{
llc_sendpdu(lp, TEST_CMD, 0, ll, data);
}
void llc_unit_data_request(llcptr lp, int ll, char * data)
{
llc_sendpdu(lp, UI_CMD, 0, ll, data);
}
/*
* llc_sendipdu() Completes an I pdu in an existing skb and gives it
* to the MAC layer for transmission.
* Parameter "type" must be either I_CMD or I_RSP.
* The skb is not freed after xmit, it is kept in case a retransmission
* is requested. If needed it can be picked up again from the rtq.
*/
void llc_sendipdu(llcptr lp, char type, char pf, struct sk_buff *skb)
{
frameptr fr; /* ptr to output pdu buffer */
struct sk_buff *tmp;
fr = (frameptr) skb->data;
fr->pdu_hdr.dsap = lp->remote_sap;
fr->pdu_hdr.ssap = lp->local_sap + cr_bit_encode[(int)type];
fr->pdu_cntl.byte1 = cntl_byte_encode[(int)type];
if (pf)
fr->i_hdr.i_pflag = 1; /* p/f and seq numbers */
fr->i_hdr.nr = lp->vr;
fr->i_hdr.ns = lp->vs;
lp->vs++;
if (lp->vs > 127)
lp->vs = 0;
lp->dev->hard_header(skb, lp->dev, ETH_P_802_3,
lp->remote_mac, NULL, skb->len);
ADD_TO_RTQ(skb); /* add skb to the retransmit queue */
tmp=skb_clone(skb, GFP_ATOMIC);
if(tmp!=NULL)
{
tmp->dev=lp->dev;
dev_queue_xmit(tmp);
}
}
/*
* Resend_ipdu() will resend the pdus in the retransmit queue (rtq)
* the return value is the number of pdus resend.
* ack_nr is N(R) of 1st pdu to resent.
* Type is I_CMD or I_RSP for 1st pdu resent.
* p is p/f flag 0 or 1 for 1st pdu resent.
* All subsequent pdus will be sent as I_CMDs with p/f set to 0
*/
int llc_resend_ipdu(llcptr lp, unsigned char ack_nr, unsigned char type, char p)
{
struct sk_buff *skb,*tmp;
int resend_count;
frameptr fr;
unsigned long flags;
resend_count = 0;
save_flags(flags);
cli();
skb = skb_peek(&lp->rtq);
while(skb && skb != (struct sk_buff *)&lp->rtq)
{
fr = (frameptr) (skb->data + lp->dev->hard_header_len);
if (resend_count == 0)
{
/*
* Resending 1st pdu:
*/
if (p)
fr->i_hdr.i_pflag = 1;
else
fr->i_hdr.i_pflag = 0;
if (type == I_CMD)
fr->pdu_hdr.ssap = fr->pdu_hdr.ssap & 0xfe;
else
fr->pdu_hdr.ssap = fr->pdu_hdr.ssap | 0x01;
}
else
{
/*
* Resending pdu 2...n
*/
fr->pdu_hdr.ssap = fr->pdu_hdr.ssap & 0xfe;
fr->i_hdr.i_pflag = 0;
}
fr->i_hdr.nr = lp->vr;
fr->i_hdr.ns = lp->vs;
lp->vs++;
if (lp->vs > 127)
lp->vs = 0;
tmp=skb_clone(skb, GFP_ATOMIC);
if(tmp!=NULL)
{
tmp->dev = lp->dev;
dev_queue_xmit(skb);
}
resend_count++;
skb = skb->next;
}
restore_flags(flags);
return resend_count;
}
/* ************** internal queue management code ****************** */
/*
* Remove one skb from the front of the awaiting transmit queue
* (this is the skb longest on the queue) and return a pointer to
* that skb.
*/
struct sk_buff *llc_pull_from_atq(llcptr lp)
{
return skb_dequeue(&lp->atq);
}
/*
* Free_acknowledged_skbs(), remove from retransmit queue (rtq)
* and free all skbs with an N(S) chronologicaly before 'pdu_ack'.
* The return value is the number of pdus acknowledged.
*/
int llc_free_acknowledged_skbs(llcptr lp, unsigned char pdu_ack)
{
struct sk_buff *pp;
frameptr fr;
int ack_count;
unsigned char ack; /* N(S) of most recently ack'ed pdu */
unsigned char ns_save;
unsigned long flags;
if (pdu_ack > 0)
ack = pdu_ack -1;
else
ack = 127;
ack_count = 0;
save_flags(flags);
cli();
pp = skb_dequeue(&lp->rtq);
while (pp != NULL)
{
/*
* Locate skb with N(S) == ack
*/
/*
* BUG: FIXME - use skb->h.*
*/
fr = (frameptr) (pp->data + lp->dev->hard_header_len);
ns_save = fr->i_hdr.ns;
kfree_skb(pp);
ack_count++;
if (ns_save == ack)
break;
pp = skb_dequeue(&lp->rtq);
}
restore_flags(flags);
return ack_count;
}
/*
* NET An implementation of the IEEE 802.2 LLC protocol for the
* LINUX operating system. LLC is implemented as a set of
* state machines and callbacks for higher networking layers.
*
* Small utilities, Linux timer handling.
*
* Written by Tim Alpaerts, Tim_Alpaerts@toyota-motor-europe.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Changes
* Alan Cox : Chainsawed into Linux form.
* Added llc_ function name prefixes.
* Fixed bug in stop/start timer.
* Added llc_cancel_timers for closing
* down an llc
*/
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <net/llc_frame.h>
#include <net/llc.h>
int llc_decode_frametype(frameptr fr)
{
if (IS_UFRAME(fr))
{ /* unnumbered cmd/rsp */
switch(fr->u_mm.mm & 0x3B)
{
case 0x1B:
return(SABME_CMD);
break;
case 0x10:
return(DISC_CMD);
break;
case 0x18:
return(UA_RSP);
break;
case 0x03:
return(DM_RSP);
break;
case 0x21:
return(FRMR_RSP);
break;
case 0x00:
return(UI_CMD);
break;
case 0x2B:
if (IS_RSP(fr))
return(XID_RSP);
else
return(XID_CMD);
break;
case 0x38:
if (IS_RSP(fr))
return(TEST_RSP);
else
return(TEST_CMD);
break;
default:
return(BAD_FRAME);
}
}
else if (IS_SFRAME(fr))
{ /* supervisory cmd/rsp */
switch(fr->s_hdr.ss)
{
case 0x00:
if (IS_RSP(fr))
return(RR_RSP);
else
return(RR_CMD);
break;
case 0x02:
if (IS_RSP(fr))
return(REJ_RSP);
else
return(REJ_CMD);
break;
case 0x01:
if (IS_RSP(fr))
return(RNR_RSP);
else
return(RNR_CMD);
break;
default:
return(BAD_FRAME);
}
}
else
{ /* information xfer */
if (IS_RSP(fr))
return(I_RSP);
else
return(I_CMD);
}
}
/*
* Validate_seq_nos will check N(S) and N(R) to see if they are
* invalid or unexpected.
* "unexpected" is explained on p44 Send State Variable.
* The return value is:
* 4 * invalid N(R) +
* 2 * invalid N(S) +
* 1 * unexpected N(S)
*/
int llc_validate_seq_nos(llcptr lp, frameptr fr)
{
int res;
/*
* A U-frame is always good
*/
if (IS_UFRAME(fr))
return(0);
/*
* For S- and I-frames check N(R):
*/
if (fr->i_hdr.nr == lp->vs)
{ /* if N(R) = V(S) */
res = 0; /* N(R) is good */
}
else
{ /* lp->k = transmit window size */
if (lp->vs >= lp->k)
{ /* if window not wrapped around 127 */
if ((fr->i_hdr.nr < lp->vs) &&
(fr->i_hdr.nr > (lp->vs - lp->k)))
res = 0;
else
res = 4; /* N(R) invalid */
}
else
{ /* window wraps around 127 */
if ((fr->i_hdr.nr < lp->vs) ||
(fr->i_hdr.nr > (128 + lp->vs - lp->k)))
res = 0;
else
res = 4; /* N(R) invalid */
}
}
/*
* For an I-frame, must check N(S) also:
*/
if (IS_IFRAME(fr))
{
if (fr->i_hdr.ns == lp->vr)
return res; /* N(S) good */
if (lp->vr >= lp->rw)
{
/* if receive window not wrapped */
if ((fr->i_hdr.ns < lp->vr) &&
(fr->i_hdr.ns > (lp->vr - lp->k)))
res = res +1; /* N(S) unexpected */
else
res = res +2; /* N(S) invalid */
}
else
{
/* Window wraps around 127 */
if ((fr->i_hdr.ns < lp->vr) ||
(fr->i_hdr.ns > (128 + lp->vr - lp->k)))
res = res +1; /* N(S) unexpected */
else
res = res +2; /* N(S) invalid */
}
}
return(res);
}
/* **************** timer management routines ********************* */
static void llc_p_timer_expired(unsigned long ulp)
{
llc_timer_expired((llcptr) ulp, P_TIMER);
}
static void llc_rej_timer_expired(unsigned long ulp)
{
llc_timer_expired((llcptr) ulp, REJ_TIMER);
}
static void llc_ack_timer_expired(unsigned long ulp)
{
llc_timer_expired((llcptr) ulp, ACK_TIMER);
}
static void llc_busy_timer_expired(unsigned long ulp)
{
llc_timer_expired((llcptr) ulp, BUSY_TIMER);
}
/* exp_fcn is an array holding the 4 entry points of the
timer expiry routines above.
It is required to keep start_timer() generic.
Thank you cdecl.
*/
static void (* exp_fcn[])(unsigned long) =
{
llc_p_timer_expired,
llc_rej_timer_expired,
llc_ack_timer_expired,
llc_busy_timer_expired
};
void llc_start_timer(llcptr lp, int t)
{
if (lp->timer_state[t] == TIMER_IDLE)
{
lp->tl[t].expires = jiffies + lp->timer_interval[t];
lp->tl[t].data = (unsigned long) lp;
lp->tl[t].function = exp_fcn[t];
add_timer(&lp->tl[t]);
lp->timer_state[t] = TIMER_RUNNING;
}
}
void llc_stop_timer(llcptr lp, int t)
{
if (lp->timer_state[t] == TIMER_RUNNING)
{
del_timer(&lp->tl[t]);
lp->timer_state[t] = TIMER_IDLE;
}
}
void llc_cancel_timers(llcptr lp)
{
llc_stop_timer(lp, P_TIMER);
llc_stop_timer(lp, REJ_TIMER);
llc_stop_timer(lp, ACK_TIMER);
llc_stop_timer(lp, BUSY_TIMER);
}
# usage: awk -f actionnm.awk pseudocode.h
#
BEGIN { "date" | getline
today = $0
printf("\n/* this file generated on %s */\n", today )
printf("\nstatic char *action_names[] = { \n " )
opl = 0
}
/^#define/ {
if ( opl > 3 ) {
printf("\n ")
opl = 0
}
opl = opl +1
t = sprintf("\"%s\"", $2 )
printf("%-15s ,", t )
# printf("%-10s", $2 )
}
END {
if ( opl > 3 ) {
printf("\n ")
}
printf("\t 0\n};\n\n")
}
# usage: cat pseudocode | sed -f act2num | awk -f compile.awk
#
#
BEGIN { "date" | getline
today = $0
printf("\n/* this file generated on %s */\n", today )
printf("\nstatic char pseudo_code [ ] = { \n" )
opl = 0 # op codes on the current line
opc = 0 # opcode counter
fpi = 0 # fill pointer for idx array
}
/^;/ { } # line starting with semicolon is comment
/^[A-Z]/ { # start of a new action
emit( 0 )
idx[ ++fpi ] = opc
name[ fpi ] = $1
emit( $2 )
}
/^[\t ]/ {
emit( $1 )
}
END {
if ( opl > 8 ) {
printf("\n")
}
printf("\t 0\n};\n\n")
printf("static short int pseudo_code_idx [ ] ={\n")
opl = 0
emit( 0 )
for( ii = 1; ii <= fpi; ii++ )
emit( idx[ ii ] )
if ( opl > 8 ) {
printf("\n")
}
printf("\t 0\n};\n\n")
printf("#define %-10s \t %3d \n", "NOP", 0 )
for( ii = 1; ii <= fpi; ii++ )
printf("#define %-10s \t %3d \n", name[ ii ], ii )
printf("\n")
}
function emit( opcode ){ # Niclaus Wirth
if ( opl > 8 ) {
printf("\n")
opl = 0
}
opl = opl +1
printf("\t%4d,", opcode )
opc++
}
s/NOP/0/
s/DUMMY_6/6/
s/DUMMY_8/8/
s/IF_F=1_CLEAR_REMOTE_BUSY/9/
s/CLEAR_REMOTE_BUSY/1/
s/CONNECT_CONFIRM/3/
s/DISCONNECT_INDICATION/5/
s/CONNECT_INDICATION/2/
s/IF_DATA_FLAG_=0_THEN_DATA_FLAG:=1/55/
s/DATA_FLAG:=0/53/
s/DATA_FLAG:=1/54/
s/DATA_FLAG:=2/52/
s/DATA_INDICATION/4/
s/F_FLAG:=P/65/
s/IF_DATA_FLAG=2_STOP_REJ_TIMER/10/
s/OPTIONAL_SEND_RNR_XXX(X=0)/30/
s/P_FLAG:=0/56/
s/P_FLAG:=P/57/
s/RE-SEND_FRMR_RSP(F=0)/14/
s/RE-SEND_FRMR_RSP(F=P)/15/
s/RE-SEND_I_CMD(P=1)_OR_SEND_RR/18/
s/RE-SEND_I_CMD(P=1)/17/
s/RE-SEND_I_RSP(F=1)/22/
s/RE-SEND_I_XXX(X=0)_OR_SEND_RR/21/
s/RE-SEND_I_XXX(X=0)/20/
s/REMOTE_BUSY:=0/58/
s/REPORT_STATUS(FRMR_RECEIVED)/66/
s/REPORT_STATUS(FRMR_SENT)/67/
s/REPORT_STATUS(REMOTE_BUSY)/68/
s/REPORT_STATUS(REMOTE_NOT_BUSY)/69/
s/RESET_CONFIRM/7/
s/RESET_INDICATION(LOCAL)/70/
s/RESET_INDICATION(REMOTE)/71/
s/RETRY_COUNT:=RETRY_COUNT+1/60/
s/RETRY_COUNT:=0/59/
s/SEND_ACKNOWLEDGE_CMD(P=1)/32/
s/SEND_ACKNOWLEDGE_RSP(F=1)/34/
s/SEND_ACKNOWLEDGE_XXX(X=0)/36/
s/SEND_DISC_CMD(P=X)/11/
s/SEND_DM_RSP(F=X)/12/
s/SEND_FRMR_RSP(F=X)/13/
s/SEND_I_CMD(P=1)/16/
s/SEND_I_XXX(X=0)/19/
s/SEND_REJ_CMD(P=1)/23/
s/SEND_REJ_RSP(F=1)/24/
s/SEND_REJ_XXX(X=0)/25/
s/SEND_RNR_CMD(F=1)/26/
s/SEND_RNR_RSP(F=1)/27/
s/SEND_RNR_XXX(X=0)/28/
s/SEND_RR_CMD(P=1)/31/
s/SEND_RR_RSP(F=1)/33/
s/SEND_RR_XXX(X=0)/35/
s/SEND_SABME_CMD(P=X)/37/
s/SEND_UA_RSP(F=X)/38/
s/SET_REMOTE_BUSY/29/
s/START_ACK_TIMER_IF_NOT_RUNNING/44/
s/START_ACK_TIMER/42/
s/START_P_TIMER/41/
s/START_REJ_TIMER/43/
s/STOP_ACK_TIMER/45/
s/STOP_ALL_TIMERS/48/
s/STOP_OTHER_TIMERS/49/
s/STOP_P_TIMER/46/
s/STOP_REJ_TIMER/47/
s/S_FLAG:=0/39/
s/S_FLAG:=1/40/
s/UPDATE_N(R)_RECEIVED/50/
s/UPDATE_P_FLAG/51/
s/V(R):=0/61/
s/V(R):=V(R)+1/62/
s/V(S):=0/63/
s/V(S):=N(R)/64/
0 NOP
1 CLEAR_REMOTE_BUSY
2 CONNECT_INDICATION
3 CONNECT_CONFIRM
4 DATA_INDICATION
5 DISCONNECT_INDICATION
6 DUMMY_6
7 RESET_CONFIRM
8 DUMMY_8
9 IF_F=1_CLEAR_REMOTE_BUSY
10 IF_DATA_FLAG=2_STOP_REJ_TIMER
11 SEND_DISC_CMD(P=X)
12 SEND_DM_RSP(F=X)
13 SEND_FRMR_RSP(F=X)
14 RE-SEND_FRMR_RSP(F=0)
15 RE-SEND_FRMR_RSP(F=P)
16 SEND_I_CMD(P=1)
17 RE-SEND_I_CMD(P=1)
18 RE-SEND_I_CMD(P=1)_OR_SEND_RR
19 SEND_I_XXX(X=0)
20 RE-SEND_I_XXX(X=0)
21 RE-SEND_I_XXX(X=0)_OR_SEND_RR
22 RE-SEND_I_RSP(F=1)
23 SEND_REJ_CMD(P=1)
24 SEND_REJ_RSP(F=1)
25 SEND_REJ_XXX(X=0)
26 SEND_RNR_CMD(F=1)
27 SEND_RNR_RSP(F=1)
28 SEND_RNR_XXX(X=0)
29 SET_REMOTE_BUSY
30 OPTIONAL_SEND_RNR_XXX(X=0)
31 SEND_RR_CMD(P=1)
32 SEND_ACKNOWLEDGE_CMD(P=1)
33 SEND_RR_RSP(F=1)
34 SEND_ACKNOWLEDGE_RSP(F=1)
35 SEND_RR_XXX(X=0)
36 SEND_ACKNOWLEDGE_XXX(X=0)
37 SEND_SABME_CMD(P=X)
38 SEND_UA_RSP(F=X)
39 S_FLAG:=0
40 S_FLAG:=1
41 START_P_TIMER
42 START_ACK_TIMER
43 START_REJ_TIMER
44 START_ACK_TIMER_IF_NOT_RUNNING
45 STOP_ACK_TIMER
46 STOP_P_TIMER
47 STOP_REJ_TIMER
48 STOP_ALL_TIMERS
49 STOP_OTHER_TIMERS
50 UPDATE_N(R)_RECEIVED
51 UPDATE_P_FLAG
52 DATA_FLAG:=2
53 DATA_FLAG:=0
54 DATA_FLAG:=1
55 IF_DATA_FLAG_=0_THEN_DATA_FLAG:=1
56 P_FLAG:=0
57 P_FLAG:=P
58 REMOTE_BUSY:=0
59 RETRY_COUNT:=0
60 RETRY_COUNT:=RETRY_COUNT+1
61 V(R):=0
62 V(R):=V(R)+1
63 V(S):=0
64 V(S):=N(R)
65 F_FLAG:=P
66 REPORT_STATUS(FRMR_RECEIVED)
67 REPORT_STATUS(FRMR_SENT)
68 REPORT_STATUS(REMOTE_BUSY)
69 REPORT_STATUS(REMOTE_NOT_BUSY)
70 RESET_INDICATION(LOCAL)
71 RESET_INDICATION(REMOTE)
static char *opcode_names[] = {
"NOP", "CLEAR_REMOTE_BUSY", "CONNECT_INDICATION", "CONNECT_CONFIRM", "DATA_INDICATION",
"DISCONNECT_INDICATION", "DUMMY_6", "RESET_CONFIRM", "DUMMY_8",
"IF_F=1_CLEAR_REMOTE_BUSY", "IF_DATA_FLAG=2_STOP_REJ_TIMER", "SEND_DISC_CMD(P=X)",
"SEND_DM_RSP(F=X)", "SEND_FRMR_RSP(F=X)", "RE-SEND_FRMR_RSP(F=0)",
"RE-SEND_FRMR_RSP(F=P)", "SEND_I_CMD(P=1)", "RE-SEND_I_CMD(P=1)",
"RE-SEND_I_CMD(P=1)_OR_SEND_RR", "SEND_I_XXX(X=0)", "RE-SEND_I_XXX(X=0)",
"RE-SEND_I_XXX(X=0)_OR_SEND_RR", "RE-SEND_I_RSP(F=1)", "SEND_REJ_CMD(P=1)",
"SEND_REJ_RSP(F=1)", "SEND_REJ_XXX(X=0)", "SEND_RNR_CMD(F=1)", "SEND_RNR_RSP(F=1)",
"SEND_RNR_XXX(X=0)", "SET_REMOTE_BUSY", "OPTIONAL_SEND_RNR_XXX(X=0)",
"SEND_RR_CMD(P=1)", "SEND_ACKNOWLEDGE_CMD(P=1)", "SEND_RR_RSP(F=1)",
"SEND_ACKNOWLEDGE_RSP(F=1)", "SEND_RR_XXX(X=0)", "SEND_ACKNOWLEDGE_XXX(X=0)",
"SEND_SABME_CMD(P=X)", "SEND_UA_RSP(F=X)", "S_FLAG:=0", "S_FLAG:=1", "START_P_TIMER",
"START_ACK_TIMER", "START_REJ_TIMER", "START_ACK_TIMER_IF_NOT_RUNNING",
"STOP_ACK_TIMER", "STOP_P_TIMER", "STOP_REJ_TIMER", "STOP_ALL_TIMERS",
"STOP_OTHER_TIMERS", "UPDATE_N(R)_RECEIVED", "UPDATE_P_FLAG", "DATA_FLAG:=2",
"DATA_FLAG:=0", "DATA_FLAG:=1", "IF_DATA_FLAG_=0_THEN_DATA_FLAG:=1", "P_FLAG:=0",
"P_FLAG:=P", "REMOTE_BUSY:=0", "RETRY_COUNT:=0", "RETRY_COUNT:=RETRY_COUNT+1",
"V(R):=0", "V(R):=V(R)+1", "V(S):=0", "V(S):=N(R)", "F_FLAG:=P",
"REPORT_STATUS(FRMR_RECEIVED)", "REPORT_STATUS(FRMR_SENT)",
"REPORT_STATUS(REMOTE_BUSY)", "REPORT_STATUS(REMOTE_NOT_BUSY)",
"RESET_INDICATION(LOCAL)", "RESET_INDICATION(REMOTE)"
};
This diff is collapsed.
...@@ -14,15 +14,16 @@ ...@@ -14,15 +14,16 @@
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <linux/config.h> #include <linux/config.h>
ctl_table e802_table[] = {
{0}
};
#ifdef CONFIG_TR
extern int sysctl_tr_rif_timeout; extern int sysctl_tr_rif_timeout;
ctl_table tr_table[] = {
{NET_TR_RIF_TIMEOUT, "rif_timeout", &sysctl_tr_rif_timeout, sizeof(int), struct ctl_table tr_table[] = {
0644, NULL, &proc_dointvec}, {
{0} .ctl_name = NET_TR_RIF_TIMEOUT,
.procname = "rif_timeout",
.data = &sysctl_tr_rif_timeout,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},
{ 0 },
}; };
#endif
# to run: awk -f transit.awk transit.p0
#
BEGIN { "date" | getline
enable_index = 1
today = $0
printf("\n/* this file was generated on %s */\n", today )
not_firstone = 0 # flag to avoid empty entry in 1st table
fpe = 0 # entry tbl array fill pointer
fpeo = 0 # entry tbl offset list fill pointer
fpdef = 0 # define list fill pointer
}
### /^;/ { } # line starting with a semicolon is comment
/^[A-Z]/ { # table name
if ( $1 == "TABLE" ) {
tbl = $2 # get table name
newtbl( tbl )
}
else if ( $1 == "COMPILE" ) {
array_name = $2
if ( $3 == "NOINDEX" ) { enable_index = 0 }
}
else { # table entry
ec = ec +1
n = split( $0, fld, " " )
action = fld[ n-1 ]
newstate = fld[ n ]
store( action, newstate )
ecct = ecct +1
}
}
END { store( action, newstate )
if ( enable_index ) {
printf( "\n/* index name #defines: */\n\n",
ec, ecct )
for( ii = 1; ii <= fpeo; ii++ ){
printf( "#define %-12s %3d\n", define[ ii ], ii -1 )
}
}
printf( "\n\n/* size of transition table is %d bytes */\n",
fpe )
if ( enable_index ) {
printf( "\nstatic short int %s_offset [ ] ={", array_name )
for( ii = 1; ii <= fpeo; ii++ ){
if ( (ii % 10) == 1 ) printf("\n ")
printf( " %4d", entry_offset[ ii ] )
if ( ii < fpeo ) printf( "," )
}
printf(" };\n")
}
printf( "\nstatic char %s_entry [ ] = {", array_name )
for( ii = 1; ii <= fpe; ii++ ){
if ( (ii % 6) == 1 ) printf("\n ")
printf( " %-14s", entry[ ii ] )
if ( ii < fpe ) printf( "," )
}
printf(" };\n")
}
function store( act, ns ){
# printf( "%s %s\n", act, ns )
entry[ ++fpe ] = act
entry[ ++fpe ] = ns
}
function newtbl( tbl ){
if ( not_firstone ) {
store( action, newstate )
}
not_firstone = 1
entry_offset[ ++fpeo ] = fpe # entry tbl offset list
define[ ++fpdef ] = tbl # state name to define
}
This diff is collapsed.
This diff is collapsed.
...@@ -266,8 +266,13 @@ CONFIG_LAPB ...@@ -266,8 +266,13 @@ CONFIG_LAPB
module will be called lapb.o. If unsure, say N. module will be called lapb.o. If unsure, say N.
CONFIG_LLC CONFIG_LLC
This is a Logical Link Layer protocol used for X.25 connections over This is a Logical Link Layer protocol used for Appletalk, IPX and in
Ethernet, using ordinary Ethernet cards. the future by NetBEUI and by the linux-sna project. It originally
came from Procom Inc. that released the code for 2.0.36 and was
ported to 2.{4,5}. Select this if you want to have support for
those protocols or if you want to have the sockets interface for
LLC.
CONFIG_NET_DIVERT CONFIG_NET_DIVERT
The Frame Diverter allows you to divert packets from the The Frame Diverter allows you to divert packets from the
......
...@@ -46,12 +46,13 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -46,12 +46,13 @@ int llc_conn_ac_clear_remote_busy(struct sock *sk, struct llc_conn_state_ev *ev)
if (llc->remote_busy_flag) { if (llc->remote_busy_flag) {
u8 nr; u8 nr;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu =
(struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
llc->remote_busy_flag = 0; llc->remote_busy_flag = 0;
del_timer(&llc->busy_state_timer.timer); del_timer(&llc->busy_state_timer.timer);
llc->busy_state_timer.running = 0; llc->busy_state_timer.running = 0;
nr = LLC_I_GET_NR(rx_pdu); nr = LLC_I_GET_NR(pdu);
llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
} }
return 0; return 0;
...@@ -147,16 +148,17 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -147,16 +148,17 @@ int llc_conn_ac_disc_ind(struct sock *sk, struct llc_conn_state_ev *ev)
struct llc_prim_if_block *prim = &llc_ind_prim; struct llc_prim_if_block *prim = &llc_ind_prim;
if (ev->type == LLC_CONN_EV_TYPE_PDU) { if (ev->type == LLC_CONN_EV_TYPE_PDU) {
llc_pdu_un_t *rx_pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu =
(struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
if (!LLC_PDU_IS_RSP(rx_pdu) && if (!LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(rx_pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(rx_pdu) == LLC_2_PDU_RSP_DM) { LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_DM) {
reason = LLC_DISC_REASON_RX_DM_RSP_PDU; reason = LLC_DISC_REASON_RX_DM_RSP_PDU;
rc = 0; rc = 0;
} else if (!LLC_PDU_IS_CMD(rx_pdu) && } else if (!LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(rx_pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(rx_pdu) == LLC_2_PDU_CMD_DISC) { LLC_U_PDU_CMD(pdu) == LLC_2_PDU_CMD_DISC) {
reason = LLC_DISC_REASON_RX_DISC_CMD_PDU; reason = LLC_DISC_REASON_RX_DISC_CMD_PDU;
rc = 0; rc = 0;
} }
...@@ -200,21 +202,21 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -200,21 +202,21 @@ int llc_conn_ac_rst_ind(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
u8 reason = 0; u8 reason = 0;
int rc = 1; int rc = 1;
llc_pdu_un_t *rx_pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
union llc_u_prim_data *prim_data = llc_ind_prim.data; union llc_u_prim_data *prim_data = llc_ind_prim.data;
struct llc_prim_if_block *prim = &llc_ind_prim; struct llc_prim_if_block *prim = &llc_ind_prim;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
switch (ev->type) { switch (ev->type) {
case LLC_CONN_EV_TYPE_PDU: case LLC_CONN_EV_TYPE_PDU:
if (!LLC_PDU_IS_RSP(rx_pdu) && if (!LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_U(rx_pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_RSP(rx_pdu) == LLC_2_PDU_RSP_FRMR) { LLC_U_PDU_RSP(pdu) == LLC_2_PDU_RSP_FRMR) {
reason = LLC_RESET_REASON_LOCAL; reason = LLC_RESET_REASON_LOCAL;
rc = 0; rc = 0;
} else if (!LLC_PDU_IS_CMD(rx_pdu) && } else if (!LLC_PDU_IS_CMD(pdu) &&
!LLC_PDU_TYPE_IS_U(rx_pdu) && !LLC_PDU_TYPE_IS_U(pdu) &&
LLC_U_PDU_CMD(rx_pdu) == LLC_U_PDU_CMD(pdu) ==
LLC_2_PDU_CMD_SABME) { LLC_2_PDU_CMD_SABME) {
reason = LLC_RESET_REASON_REMOTE; reason = LLC_RESET_REASON_REMOTE;
rc = 0; rc = 0;
...@@ -270,11 +272,11 @@ int llc_conn_ac_report_status(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -270,11 +272,11 @@ int llc_conn_ac_report_status(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk, int llc_conn_ac_clear_remote_busy_if_f_eq_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
if (!LLC_PDU_IS_RSP(rx_pdu) && if (!LLC_PDU_IS_RSP(pdu) &&
!LLC_PDU_TYPE_IS_I(rx_pdu) && !LLC_PDU_TYPE_IS_I(pdu) &&
!LLC_I_PF_IS_1(rx_pdu) && llc_sk(sk)->ack_pf) !LLC_I_PF_IS_1(pdu) && llc_sk(sk)->ack_pf)
llc_conn_ac_clear_remote_busy(sk, ev); llc_conn_ac_clear_remote_busy(sk, ev);
return 0; return 0;
} }
...@@ -386,11 +388,11 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, ...@@ -386,11 +388,11 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk,
u8 f_bit; u8 f_bit;
int rc = 1; int rc = 1;
struct sk_buff *skb, *ev_skb = ev->data.pdu.skb; struct sk_buff *skb, *ev_skb = ev->data.pdu.skb;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev_skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev_skb->nh.raw;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
llc->rx_pdu_hdr = (u32)*((u32 *)rx_pdu); llc->rx_pdu_hdr = *((u32 *)pdu);
if (!LLC_PDU_IS_CMD(rx_pdu)) if (!LLC_PDU_IS_CMD(pdu))
llc_pdu_decode_pf_bit(ev_skb, &f_bit); llc_pdu_decode_pf_bit(ev_skb, &f_bit);
else else
f_bit = 0; f_bit = 0;
...@@ -401,7 +403,7 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk, ...@@ -401,7 +403,7 @@ int llc_conn_ac_send_frmr_rsp_f_set_x(struct sock *sk,
skb->dev = llc->dev; skb->dev = llc->dev;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS, llc_pdu_init_as_frmr_rsp(skb, pdu, f_bit, llc->vS,
llc->vR, INCORRECT); llc->vR, INCORRECT);
lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
rc = 0; rc = 0;
...@@ -420,12 +422,12 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk, ...@@ -420,12 +422,12 @@ int llc_conn_ac_resend_frmr_rsp_f_set_0(struct sock *sk,
u8 f_bit = 0; u8 f_bit = 0;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)&llc->rx_pdu_hdr; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr;
skb->dev = llc->dev; skb->dev = llc->dev;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS, llc_pdu_init_as_frmr_rsp(skb, pdu, f_bit, llc->vS,
llc->vR, INCORRECT); llc->vR, INCORRECT);
lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
rc = 0; rc = 0;
...@@ -446,12 +448,13 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk, ...@@ -446,12 +448,13 @@ int llc_conn_ac_resend_frmr_rsp_f_set_p(struct sock *sk,
if (skb) { if (skb) {
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
struct llc_sap *sap = llc->sap; struct llc_sap *sap = llc->sap;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu =
(struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
skb->dev = llc->dev; skb->dev = llc->dev;
llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap, llc_pdu_header_init(skb, LLC_PDU_TYPE_U, sap->laddr.lsap,
llc->daddr.lsap, LLC_PDU_RSP); llc->daddr.lsap, LLC_PDU_RSP);
llc_pdu_init_as_frmr_rsp(skb, rx_pdu, f_bit, llc->vS, llc_pdu_init_as_frmr_rsp(skb, pdu, f_bit, llc->vS,
llc->vR, INCORRECT); llc->vR, INCORRECT);
lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac); lan_hdrs_init(skb, llc->dev->dev_addr, llc->daddr.mac);
rc = 0; rc = 0;
...@@ -497,9 +500,8 @@ int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, ...@@ -497,9 +500,8 @@ int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk,
int llc_conn_ac_resend_i_cmd_p_set_1(struct sock *sk, int llc_conn_ac_resend_i_cmd_p_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
u8 nr = LLC_I_GET_NR(pdu);
u8 nr = LLC_I_GET_NR(rx_pdu);
llc_conn_resend_i_pdu_as_cmd(sk, nr, 1); llc_conn_resend_i_pdu_as_cmd(sk, nr, 1);
return 0; return 0;
...@@ -508,9 +510,8 @@ int llc_conn_ac_resend_i_cmd_p_set_1(struct sock *sk, ...@@ -508,9 +510,8 @@ int llc_conn_ac_resend_i_cmd_p_set_1(struct sock *sk,
int llc_conn_ac_resend_i_cmd_p_set_1_or_send_rr(struct sock *sk, int llc_conn_ac_resend_i_cmd_p_set_1_or_send_rr(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
u8 nr = LLC_I_GET_NR(pdu);
u8 nr = LLC_I_GET_NR(rx_pdu);
int rc = llc_conn_ac_send_rr_cmd_p_set_1(sk, ev); int rc = llc_conn_ac_send_rr_cmd_p_set_1(sk, ev);
if (!rc) if (!rc)
...@@ -538,8 +539,8 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, ...@@ -538,8 +539,8 @@ int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk,
int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk, int llc_conn_ac_resend_i_xxx_x_set_0(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
u8 nr = LLC_I_GET_NR(rx_pdu); u8 nr = LLC_I_GET_NR(pdu);
llc_conn_resend_i_pdu_as_cmd(sk, nr, 0); llc_conn_resend_i_pdu_as_cmd(sk, nr, 0);
return 0; return 0;
...@@ -550,7 +551,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, ...@@ -550,7 +551,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
{ {
u8 nr; u8 nr;
u8 f_bit = 0; u8 f_bit = 0;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
int rc = 1; int rc = 1;
struct sk_buff *skb = llc_alloc_frame(); struct sk_buff *skb = llc_alloc_frame();
...@@ -567,7 +568,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, ...@@ -567,7 +568,7 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
llc_conn_send_pdu(sk, skb); llc_conn_send_pdu(sk, skb);
} }
if (rc) { if (rc) {
nr = LLC_I_GET_NR(rx_pdu); nr = LLC_I_GET_NR(pdu);
rc = 0; rc = 0;
llc_conn_resend_i_pdu_as_cmd(sk, nr, f_bit); llc_conn_resend_i_pdu_as_cmd(sk, nr, f_bit);
} }
...@@ -577,8 +578,8 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk, ...@@ -577,8 +578,8 @@ int llc_conn_ac_resend_i_xxx_x_set_0_or_send_rr(struct sock *sk,
int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk, int llc_conn_ac_resend_i_rsp_f_set_1(struct sock *sk,
struct llc_conn_state_ev *ev) struct llc_conn_state_ev *ev)
{ {
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
u8 nr = LLC_I_GET_NR(rx_pdu); u8 nr = LLC_I_GET_NR(pdu);
llc_conn_resend_i_pdu_as_rsp(sk, nr, 1); llc_conn_resend_i_pdu_as_rsp(sk, nr, 1);
return 0; return 0;
...@@ -1336,10 +1337,10 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -1336,10 +1337,10 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct llc_conn_state_ev *ev)
u16 unacked = 0; u16 unacked = 0;
u8 fbit; u8 fbit;
struct sk_buff *skb = ev->data.pdu.skb; struct sk_buff *skb = ev->data.pdu.skb;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw;
struct llc_opt *llc = llc_sk(sk); struct llc_opt *llc = llc_sk(sk);
llc->last_nr = PDU_SUPV_GET_Nr(rx_pdu); llc->last_nr = PDU_SUPV_GET_Nr(pdu);
acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked); acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked);
/* On loopback we don't queue I frames in unack_pdu_q queue. */ /* On loopback we don't queue I frames in unack_pdu_q queue. */
if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) { if (acked > 0 || (llc->dev->flags & IFF_LOOPBACK)) {
...@@ -1375,10 +1376,10 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -1375,10 +1376,10 @@ int llc_conn_ac_upd_nr_received(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_upd_p_flag(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ac_upd_p_flag(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
struct sk_buff *skb = ev->data.pdu.skb; struct sk_buff *skb = ev->data.pdu.skb;
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw;
u8 f_bit; u8 f_bit;
if (!LLC_PDU_IS_RSP(rx_pdu) && if (!LLC_PDU_IS_RSP(pdu) &&
!llc_pdu_decode_pf_bit(skb, &f_bit) && f_bit) { !llc_pdu_decode_pf_bit(skb, &f_bit) && f_bit) {
llc_sk(sk)->p_flag = 0; llc_sk(sk)->p_flag = 0;
llc_conn_ac_stop_p_timer(sk, ev); llc_conn_ac_stop_p_timer(sk, ev);
...@@ -1556,8 +1557,8 @@ int llc_conn_ac_rst_vs(struct sock *sk, struct llc_conn_state_ev *ev) ...@@ -1556,8 +1557,8 @@ int llc_conn_ac_rst_vs(struct sock *sk, struct llc_conn_state_ev *ev)
int llc_conn_ac_upd_vs(struct sock *sk, struct llc_conn_state_ev *ev) int llc_conn_ac_upd_vs(struct sock *sk, struct llc_conn_state_ev *ev)
{ {
llc_pdu_sn_t *rx_pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
u8 nr = PDU_SUPV_GET_Nr(rx_pdu); u8 nr = PDU_SUPV_GET_Nr(pdu);
if (llc_circular_between(llc_sk(sk)->vS, nr, llc_sk(sk)->X)) if (llc_circular_between(llc_sk(sk)->vS, nr, llc_sk(sk)->X))
llc_conn_ac_set_vs_nr(sk, ev); llc_conn_ac_set_vs_nr(sk, ev);
......
This diff is collapsed.
...@@ -2808,20 +2808,20 @@ static struct llc_conn_state_trans *llc_reject_state_transitions[] = { ...@@ -2808,20 +2808,20 @@ static struct llc_conn_state_trans *llc_reject_state_transitions[] = {
[36] = &llc_reject_state_trans_8a, [36] = &llc_reject_state_trans_8a,
[37] = &llc_reject_state_trans_8b, [37] = &llc_reject_state_trans_8b,
[38] = &llc_reject_state_trans_9, [38] = &llc_reject_state_trans_9,
[40] = &llc_reject_state_trans_10a, [39] = &llc_reject_state_trans_10a,
[41] = &llc_reject_state_trans_10b, [40] = &llc_reject_state_trans_10b,
[42] = &llc_reject_state_trans_10c, [41] = &llc_reject_state_trans_10c,
[43] = &llc_reject_state_trans_11, [42] = &llc_reject_state_trans_11,
[44] = &llc_reject_state_trans_12a, [43] = &llc_reject_state_trans_12a,
[45] = &llc_reject_state_trans_12b, [44] = &llc_reject_state_trans_12b,
[46] = &llc_reject_state_trans_12c, [45] = &llc_reject_state_trans_12c,
[47] = &llc_reject_state_trans_13, [46] = &llc_reject_state_trans_13,
[48] = &llc_reject_state_trans_14a, [47] = &llc_reject_state_trans_14a,
[49] = &llc_reject_state_trans_14b, [48] = &llc_reject_state_trans_14b,
[50] = &llc_reject_state_trans_15a, [49] = &llc_reject_state_trans_15a,
[51] = &llc_reject_state_trans_15b, [50] = &llc_reject_state_trans_15b,
[52] = &llc_reject_state_trans_16, [51] = &llc_reject_state_trans_16,
[53] = &llc_common_state_trans_n, [52] = &llc_common_state_trans_n,
}; };
/* LLC_CONN_STATE_AWAIT transitions */ /* LLC_CONN_STATE_AWAIT transitions */
......
...@@ -162,7 +162,7 @@ void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb, ...@@ -162,7 +162,7 @@ void llc_conn_rtn_pdu(struct sock *sk, struct sk_buff *skb,
void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit) void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
{ {
struct sk_buff *skb; struct sk_buff *skb;
llc_pdu_sn_t *pdu; struct llc_pdu_sn *pdu;
u16 nbr_unack_pdus; u16 nbr_unack_pdus;
u8 howmany_resend = 0; u8 howmany_resend = 0;
...@@ -173,7 +173,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit) ...@@ -173,7 +173,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit)
* appropriate PDUs, fix them up, and put them on mac_pdu_q. * appropriate PDUs, fix them up, and put them on mac_pdu_q.
*/ */
while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) { while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) {
pdu = (llc_pdu_sn_t *)skb->nh.raw; pdu = (struct llc_pdu_sn *)skb->nh.raw;
llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD); llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD);
llc_pdu_set_pf_bit(skb, first_p_bit); llc_pdu_set_pf_bit(skb, first_p_bit);
skb_queue_tail(&sk->write_queue, skb); skb_queue_tail(&sk->write_queue, skb);
...@@ -201,7 +201,7 @@ out:; ...@@ -201,7 +201,7 @@ out:;
void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit) void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
{ {
struct sk_buff *skb; struct sk_buff *skb;
llc_pdu_sn_t *pdu; struct llc_pdu_sn *pdu;
u16 nbr_unack_pdus; u16 nbr_unack_pdus;
u8 howmany_resend = 0; u8 howmany_resend = 0;
...@@ -212,7 +212,7 @@ void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit) ...@@ -212,7 +212,7 @@ void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
* appropriate PDUs, fix them up, and put them on mac_pdu_q * appropriate PDUs, fix them up, and put them on mac_pdu_q
*/ */
while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) { while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) {
pdu = (llc_pdu_sn_t *)skb->nh.raw; pdu = (struct llc_pdu_sn *)skb->nh.raw;
llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP); llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP);
llc_pdu_set_pf_bit(skb, first_f_bit); llc_pdu_set_pf_bit(skb, first_f_bit);
skb_queue_tail(&sk->write_queue, skb); skb_queue_tail(&sk->write_queue, skb);
...@@ -240,14 +240,14 @@ int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked) ...@@ -240,14 +240,14 @@ int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked)
{ {
int pdu_pos, i; int pdu_pos, i;
struct sk_buff *skb; struct sk_buff *skb;
llc_pdu_sn_t *pdu; struct llc_pdu_sn *pdu;
int nbr_acked = 0; int nbr_acked = 0;
int q_len = skb_queue_len(&llc_sk(sk)->pdu_unack_q); int q_len = skb_queue_len(&llc_sk(sk)->pdu_unack_q);
if (!q_len) if (!q_len)
goto out; goto out;
skb = skb_peek(&llc_sk(sk)->pdu_unack_q); skb = skb_peek(&llc_sk(sk)->pdu_unack_q);
pdu = (llc_pdu_sn_t *)skb->nh.raw; pdu = (struct llc_pdu_sn *)skb->nh.raw;
/* finding position of last acked pdu in queue */ /* finding position of last acked pdu in queue */
pdu_pos = ((int)LLC_2_SEQ_NBR_MODULO + (int)nr - pdu_pos = ((int)LLC_2_SEQ_NBR_MODULO + (int)nr -
...@@ -275,7 +275,7 @@ static void llc_conn_send_pdus(struct sock *sk) ...@@ -275,7 +275,7 @@ static void llc_conn_send_pdus(struct sock *sk)
struct sk_buff *skb; struct sk_buff *skb;
while ((skb = skb_dequeue(&sk->write_queue)) != NULL) { while ((skb = skb_dequeue(&sk->write_queue)) != NULL) {
llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw;
if (!LLC_PDU_TYPE_IS_I(pdu) && if (!LLC_PDU_TYPE_IS_I(pdu) &&
!(skb->dev->flags & IFF_LOOPBACK)) !(skb->dev->flags & IFF_LOOPBACK))
...@@ -297,7 +297,8 @@ void llc_conn_free_ev(struct llc_conn_state_ev *ev) ...@@ -297,7 +297,8 @@ void llc_conn_free_ev(struct llc_conn_state_ev *ev)
{ {
if (ev->type == LLC_CONN_EV_TYPE_PDU) { if (ev->type == LLC_CONN_EV_TYPE_PDU) {
/* free the frame that binded to this event */ /* free the frame that binded to this event */
llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_sn *pdu =
(struct llc_pdu_sn *)ev->data.pdu.skb->nh.raw;
if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim) if (LLC_PDU_TYPE_IS_I(pdu) || !ev->flag || !ev->ind_prim)
kfree_skb(ev->data.pdu.skb); kfree_skb(ev->data.pdu.skb);
...@@ -488,7 +489,6 @@ void __init llc_build_offset_table(void) ...@@ -488,7 +489,6 @@ void __init llc_build_offset_table(void)
struct llc_conn_state *curr_state; struct llc_conn_state *curr_state;
int state, ev_type, next_offset; int state, ev_type, next_offset;
memset(llc_offset_table, 0, sizeof(llc_offset_table));
for (state = 0; state < NBR_CONN_STATES; state++) { for (state = 0; state < NBR_CONN_STATES; state++) {
curr_state = &llc_conn_state_table[state]; curr_state = &llc_conn_state_table[state];
next_offset = 0; next_offset = 0;
......
...@@ -56,7 +56,7 @@ int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station, ...@@ -56,7 +56,7 @@ int llc_stat_ev_ack_tmr_exp_eq_retry_cnt_max_retry(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
...@@ -68,7 +68,7 @@ int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station, ...@@ -68,7 +68,7 @@ int llc_stat_ev_rx_null_dsap_xid_c(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_RSP(pdu) && /* response PDU */ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
...@@ -81,7 +81,7 @@ int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station, ...@@ -81,7 +81,7 @@ int llc_stat_ev_rx_null_dsap_0_xid_r_xid_r_cnt_eq(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_RSP(pdu) && /* response PDU */ !LLC_PDU_IS_RSP(pdu) && /* response PDU */
...@@ -94,7 +94,7 @@ int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station, ...@@ -94,7 +94,7 @@ int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station, int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct llc_station_state_ev *ev) struct llc_station_state_ev *ev)
{ {
llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw; struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
return ev->type == LLC_STATION_EV_TYPE_PDU && return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */ !LLC_PDU_IS_CMD(pdu) && /* command PDU */
......
...@@ -77,8 +77,8 @@ static llc_prim_call_t llc_resp_prim[LLC_NBR_PRIMITIVES] = { ...@@ -77,8 +77,8 @@ static llc_prim_call_t llc_resp_prim[LLC_NBR_PRIMITIVES] = {
* @sap: pointer to allocated SAP (output argument). * @sap: pointer to allocated SAP (output argument).
* *
* Interface function to upper layer. each one who wants to get a SAP * Interface function to upper layer. each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns 0 for * (for example NetBEUI) should call this function. Returns the opened
* success, 1 for failure. * SAP for success, NULL for failure.
*/ */
struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate, struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate,
llc_prim_call_t nw_confirm, u8 lsap) llc_prim_call_t nw_confirm, u8 lsap)
......
...@@ -25,10 +25,8 @@ ...@@ -25,10 +25,8 @@
#include <net/llc_evnt.h> #include <net/llc_evnt.h>
#include <net/llc_c_ev.h> #include <net/llc_c_ev.h>
#include <net/llc_s_ev.h> #include <net/llc_s_ev.h>
#ifdef CONFIG_TR #include <linux/trdevice.h>
extern void tr_source_route(struct sk_buff *skb, struct trh_hdr *trh,
struct net_device *dev);
#endif
/* function prototypes */ /* function prototypes */
static void fix_up_incoming_skb(struct sk_buff *skb); static void fix_up_incoming_skb(struct sk_buff *skb);
...@@ -78,7 +76,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -78,7 +76,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt) struct packet_type *pt)
{ {
struct llc_sap *sap; struct llc_sap *sap;
llc_pdu_sn_t *pdu; struct llc_pdu_sn *pdu;
u8 dest; u8 dest;
/* When the interface is in promisc. mode, drop all the crap that it /* When the interface is in promisc. mode, drop all the crap that it
...@@ -92,7 +90,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -92,7 +90,7 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
if (!skb) if (!skb)
goto out; goto out;
fix_up_incoming_skb(skb); fix_up_incoming_skb(skb);
pdu = (llc_pdu_sn_t *)skb->nh.raw; pdu = (struct llc_pdu_sn *)skb->nh.raw;
if (!pdu->dsap) { /* NULL DSAP, refer to station */ if (!pdu->dsap) { /* NULL DSAP, refer to station */
llc_pdu_router(NULL, NULL, skb, 0); llc_pdu_router(NULL, NULL, skb, 0);
goto out; goto out;
...@@ -165,11 +163,12 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev, ...@@ -165,11 +163,12 @@ int mac_indicate(struct sk_buff *skb, struct net_device *dev,
static void fix_up_incoming_skb(struct sk_buff *skb) static void fix_up_incoming_skb(struct sk_buff *skb)
{ {
u8 llc_len = 2; u8 llc_len = 2;
llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->data; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->data;
if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U) if ((pdu->ctrl_1 & LLC_PDU_TYPE_MASK) == LLC_PDU_TYPE_U)
llc_len = 1; llc_len = 1;
llc_len += 2; llc_len += 2;
skb->h.raw += llc_len;
skb_pull(skb, llc_len); skb_pull(skb, llc_len);
if (skb->protocol == htons(ETH_P_802_2)) { if (skb->protocol == htons(ETH_P_802_2)) {
u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto, u16 pdulen = ((struct ethhdr *)skb->mac.raw)->h_proto,
...@@ -197,7 +196,7 @@ static void fix_up_incoming_skb(struct sk_buff *skb) ...@@ -197,7 +196,7 @@ static void fix_up_incoming_skb(struct sk_buff *skb)
int llc_pdu_router(struct llc_sap *sap, struct sock* sk, int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
struct sk_buff *skb, u8 type) struct sk_buff *skb, u8 type)
{ {
llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw; struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw;
int rc = 0; int rc = 0;
if (!pdu->dsap) { if (!pdu->dsap) {
...@@ -246,17 +245,15 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk, ...@@ -246,17 +245,15 @@ int llc_pdu_router(struct llc_sap *sap, struct sock* sk,
*/ */
u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da) u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da)
{ {
u8 *saddr;
u8 *daddr;
u16 rc = 0; u16 rc = 0;
switch (skb->dev->type) { switch (skb->dev->type) {
#ifdef CONFIG_TR #ifdef CONFIG_TR
case ARPHRD_IEEE802_TR: { case ARPHRD_IEEE802_TR: {
struct trh_hdr *trh = (struct trh_hdr *) struct trh_hdr *trh;
skb_push(skb, sizeof(*trh));
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
trh = (struct trh_hdr *)skb_push(skb, sizeof(*trh));
trh->ac = AC; trh->ac = AC;
trh->fc = LLC_FRAME; trh->fc = LLC_FRAME;
if (sa) if (sa)
...@@ -274,14 +271,13 @@ u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da) ...@@ -274,14 +271,13 @@ u16 lan_hdrs_init(struct sk_buff *skb, u8 *sa, u8 *da)
case ARPHRD_ETHER: case ARPHRD_ETHER:
case ARPHRD_LOOPBACK: { case ARPHRD_LOOPBACK: {
unsigned short len = skb->len; unsigned short len = skb->len;
struct ethhdr *eth;
skb->mac.raw = skb_push(skb, sizeof(struct ethhdr)); skb->mac.raw = skb_push(skb, sizeof(*eth));
memset(skb->mac.raw, 0, sizeof(struct ethhdr)); eth = (struct ethhdr *)skb->mac.raw;
((struct ethhdr *)skb->mac.raw)->h_proto = htons(len); eth->h_proto = htons(len);
daddr = ((struct ethhdr *)skb->mac.raw)->h_dest; memcpy(eth->h_dest, da, ETH_ALEN);
saddr = ((struct ethhdr *)skb->mac.raw)->h_source; memcpy(eth->h_source, sa, ETH_ALEN);
memcpy(daddr, da, ETH_ALEN);
memcpy(saddr, sa, ETH_ALEN);
break; break;
} }
default: default:
......
...@@ -600,23 +600,23 @@ static int __init llc_init(void) ...@@ -600,23 +600,23 @@ static int __init llc_init(void)
ev = kmalloc(sizeof(*ev), GFP_ATOMIC); ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev) if (!ev)
goto err; goto err;
llc_build_offset_table();
memset(ev, 0, sizeof(*ev)); memset(ev, 0, sizeof(*ev));
if(dev_base->next) if(dev_base->next)
memcpy(llc_main_station.mac_sa, dev_base->next->dev_addr, ETH_ALEN); memcpy(llc_main_station.mac_sa, dev_base->next->dev_addr, ETH_ALEN);
else else
memset(llc_main_station.mac_sa, 0, ETH_ALEN); memset(llc_main_station.mac_sa, 0, ETH_ALEN);
llc_main_station.ack_timer.expires = jiffies + 3 * HZ; llc_main_station.ack_timer.expires = jiffies + 3 * HZ;
/* initialize the station component */
llc_register_sap(0, mac_indicate);
llc_main_station.maximum_retry = 1; llc_main_station.maximum_retry = 1;
llc_main_station.state = LLC_STATION_STATE_DOWN; llc_main_station.state = LLC_STATION_STATE_DOWN;
ev->type = LLC_STATION_EV_TYPE_SIMPLE; ev->type = LLC_STATION_EV_TYPE_SIMPLE;
ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; ev->data.a.ev = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK;
rc = llc_station_next_state(&llc_main_station, ev); rc = llc_station_next_state(&llc_main_station, ev);
llc_build_offset_table();
llc_ind_prim.data = &llc_ind_data_prim; llc_ind_prim.data = &llc_ind_data_prim;
llc_cfm_prim.data = &llc_cfm_data_prim; llc_cfm_prim.data = &llc_cfm_data_prim;
proc_net_create("802.2", 0, llc_proc_get_info); proc_net_create("802.2", 0, llc_proc_get_info);
/* initialize the station component */
llc_register_sap(0, mac_indicate);
llc_ui_init(); llc_ui_init();
out: out:
return rc; return rc;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment