Commit 42bdf87f authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/BAK-net-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents 757a6bee 6bdf0a41
......@@ -24,15 +24,13 @@ struct sockaddr_ipx
#define IPX_DLTITF 0
#define IPX_CRTITF 1
typedef struct ipx_route_definition
{
struct ipx_route_definition {
__u32 ipx_network;
__u32 ipx_router_network;
unsigned char ipx_router_node[IPX_NODE_LEN];
} ipx_route_definition;
};
typedef struct ipx_interface_definition
{
struct ipx_interface_definition {
__u32 ipx_network;
unsigned char ipx_device[16];
unsigned char ipx_dlink_type;
......@@ -47,13 +45,12 @@ typedef struct ipx_interface_definition
#define IPX_PRIMARY 1
#define IPX_INTERNAL 2
unsigned char ipx_node[IPX_NODE_LEN];
} ipx_interface_definition;
};
typedef struct ipx_config_data
{
struct ipx_config_data {
unsigned char ipxcfg_auto_select_primary;
unsigned char ipxcfg_auto_create_interfaces;
} ipx_config_data;
};
/*
* OLD Route Definition for backward compatibility.
......@@ -77,13 +74,4 @@ struct ipx_route_def
#define SIOCAIPXPRISLT (SIOCPROTOPRIVATE+1)
#define SIOCIPXCFGDATA (SIOCPROTOPRIVATE+2)
#define SIOCIPXNCPCONN (SIOCPROTOPRIVATE+3)
#ifdef __KERNEL__
#include <linux/skbuff.h>
extern int ipxrtr_route_skb(struct sk_buff *);
extern int ipx_if_offset(unsigned long ipx_net_number);
extern void ipx_remove_socket(struct sock *sk);
#endif /* def __KERNEL__ */
#endif /* def _IPX_H_ */
......@@ -182,7 +182,6 @@ struct sk_buff {
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct spxhdr *spxh;
unsigned char *raw;
} h;
......@@ -190,7 +189,6 @@ struct sk_buff {
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
struct ipxhdr *ipxh;
unsigned char *raw;
} nh;
......
......@@ -14,12 +14,11 @@
#include <net/datalink.h>
#include <linux/ipx.h>
typedef struct
{
struct ipx_address {
__u32 net;
__u8 node[IPX_NODE_LEN];
__u16 sock;
} ipx_address;
};
#define ipx_broadcast_node "\377\377\377\377\377\377"
#define ipx_this_node "\0\0\0\0\0\0"
......@@ -39,11 +38,16 @@ struct ipxhdr
#define IPX_TYPE_SPX 0x05 /* SPX protocol */
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast */
ipx_address ipx_dest __attribute__ ((packed));
ipx_address ipx_source __attribute__ ((packed));
struct ipx_address ipx_dest __attribute__ ((packed));
struct ipx_address ipx_source __attribute__ ((packed));
};
typedef struct ipx_interface {
static __inline__ struct ipxhdr *ipx_hdr(struct sk_buff *skb)
{
return (struct ipxhdr *)skb->h.raw;
}
struct ipx_interface {
/* IPX address */
__u32 if_netnum;
unsigned char if_node[IPX_NODE_LEN];
......@@ -65,16 +69,16 @@ typedef struct ipx_interface {
unsigned char if_primary;
struct ipx_interface *if_next;
} ipx_interface;
};
typedef struct ipx_route {
struct ipx_route {
__u32 ir_net;
ipx_interface *ir_intrfc;
struct ipx_interface *ir_intrfc;
unsigned char ir_routed;
unsigned char ir_router_node[IPX_NODE_LEN];
struct ipx_route *ir_next;
struct ipx_route *ir_next;
atomic_t refcnt;
} ipx_route;
};
#ifdef __KERNEL__
struct ipx_cb {
......@@ -88,8 +92,8 @@ struct ipx_cb {
};
struct ipx_opt {
ipx_address dest_addr;
ipx_interface *intrfc;
struct ipx_address dest_addr;
struct ipx_interface *intrfc;
unsigned short port;
#ifdef CONFIG_IPX_INTERN
unsigned char node[IPX_NODE_LEN];
......@@ -106,7 +110,4 @@ struct ipx_opt {
#define IPX_MIN_EPHEMERAL_SOCKET 0x4000
#define IPX_MAX_EPHEMERAL_SOCKET 0x7fff
extern int ipx_register_spx(struct proto_ops **, struct net_proto_family *);
extern int ipx_unregister_spx(void);
#endif /* def _NET_INET_IPX_H_ */
#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 @@
(info->ind_bits = ( (info->ind_bits & 0xEF) | (((u8) ind) & 0x10)))
/* Sequence-numbered PDU format (4 bytes in length) */
typedef struct llc_pdu_sn {
struct llc_pdu_sn {
u8 dsap;
u8 ssap;
u8 ctrl_1;
u8 ctrl_2;
} llc_pdu_sn_t;
};
/* Un-numbered PDU format (3 bytes in length) */
typedef struct llc_pdu_un {
struct llc_pdu_un {
u8 dsap;
u8 ssap;
u8 ctrl_1;
} llc_pdu_un_t;
};
/* 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 type; /* different if NULL/non-NULL LSAP */
u8 rw; /* sender receive window */
} llc_xid_info_t;
};
/* 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 */
u8 curr_ssv; /* current send state variable val */
u8 curr_rsv; /* current receive state variable */
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_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,
u8 rx_window);
extern int llc_pdu_init_as_test_rsp(struct sk_buff *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);
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);
......
#ifndef __NET_SPX_H
#define __NET_SPX_H
#include <net/ipx.h>
struct spxhdr
{ __u8 cctl;
__u8 dtype;
#define SPX_DTYPE_ECONN 0xFE /* Finished */
#define SPX_DTYPE_ECACK 0xFF /* Ok */
__u16 sconn; /* Connection ID */
__u16 dconn; /* Connection ID */
__u16 sequence;
__u16 ackseq;
__u16 allocseq;
};
struct ipxspxhdr
{ struct ipxhdr ipx;
struct spxhdr spx;
};
#define SPX_SYS_PKT_LEN (sizeof(struct ipxspxhdr))
#ifdef __KERNEL__
struct spx_opt
{ int state;
int sndbuf;
int retries; /* Number of WD retries */
int retransmits; /* Number of retransmits */
int max_retries;
int wd_interval;
void *owner;
__u16 dest_connid; /* Net order */
__u16 source_connid; /* Net order */
__u16 sequence; /* Host order - our current pkt # */
__u16 alloc; /* Host order - max seq we can rcv now */
__u16 rmt_ack; /* Host order - last pkt ACKd by remote */
__u16 rmt_seq;
__u16 acknowledge;
__u16 rmt_alloc; /* Host order - max seq remote can handle now */
ipx_address dest_addr;
ipx_address source_addr;
struct timer_list watchdog; /* Idle watch */
struct timer_list retransmit; /* Retransmit timer */
struct sk_buff_head rcv_queue;
struct sk_buff_head transmit_queue;
struct sk_buff_head retransmit_queue;
};
#define spx_sk(__sk) ((struct spx_opt *)(((struct sock *)(__sk)) + 1))
/* Packet connectino control defines */
#define CCTL_SPXII_XHD 0x01 /* SPX2 extended header */
#define CCTL_SPX_UNKNOWN 0x02 /* Unknown (unused ??) */
#define CCTL_SPXII_NEG 0x04 /* Negotiate size */
#define CCTL_SPXII 0x08 /* Set for SPX2 */
#define CCTL_EOM 0x10 /* End of message marker */
#define CCTL_URG 0x20 /* Urgent marker in SPP (not used in SPX?) */
#define CCTL_ACK 0x40 /* Send me an ACK */
#define CCTL_CTL 0x80 /* Control message */
#define CCTL_SYS CCTL_CTL /* Spec uses CCTL_SYS */
/* Connection state defines */
#define SPX_CLOSED 7
#define SPX_CONNECTING 8
#define SPX_CONNECTED 9
/* Packet transmit types - Internal */
#define DATA 0 /* Data */
#define ACK 1 /* Data ACK */
#define WDACK 2 /* WD ACK */
#define CONACK 3 /* Connection Request ACK */
#define CONREQ 4 /* Connection Request */
#define WDREQ 5 /* WD Request */
#define DISCON 6 /* Informed Disconnect */
#define DISACK 7 /* Informed Disconnect ACK */
#define RETRAN 8 /* Int. Retransmit of packet */
#define TQUEUE 9 /* Int. Transmit of a queued packet */
/*
* These are good canidates for IOcontrol calls
*/
/* Watchdog defines */
#define VERIFY_TIMEOUT 3 * HZ
#define ABORT_TIMEOUT 30 * HZ
/* Packet retransmit defines */
#define RETRY_COUNT 10
#define RETRY_TIME 1 * HZ
#define MAX_RETRY_DELAY 5 * HZ
#endif /* __KERNEL__ */
#endif /* def __NET_SPX_H */
......@@ -2,15 +2,14 @@
# 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
# Check the p8022 selections against net/core/Makefile.
obj-$(CONFIG_SYSCTL) += sysctl_net_802.o
obj-$(CONFIG_LLC) += p8022.o psnap.o llc_sendpdu.o llc_utility.o \
cl2llc.o llc_macinit.o
obj-$(CONFIG_TR) += p8022.o psnap.o tr.o
obj-$(CONFIG_LLC) += p8022.o psnap.o
obj-$(CONFIG_TR) += p8022.o psnap.o tr.o sysctl_net_802.o
obj-$(CONFIG_NET_FC) += fc.o
obj-$(CONFIG_FDDI) += fddi.o
obj-$(CONFIG_HIPPI) += hippi.o
......@@ -18,25 +17,3 @@ obj-$(CONFIG_IPX) += p8022.o psnap.o
obj-$(CONFIG_ATALK) += p8022.o psnap.o
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 @@
#include <linux/sysctl.h>
#include <linux/config.h>
ctl_table e802_table[] = {
{0}
};
#ifdef CONFIG_TR
extern int sysctl_tr_rif_timeout;
ctl_table tr_table[] = {
{NET_TR_RIF_TIMEOUT, "rif_timeout", &sysctl_tr_rif_timeout, sizeof(int),
0644, NULL, &proc_dointvec},
{0}
struct ctl_table tr_table[] = {
{
.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
module will be called lapb.o. If unsure, say N.
CONFIG_LLC
This is a Logical Link Layer protocol used for X.25 connections over
Ethernet, using ordinary Ethernet cards.
This is a Logical Link Layer protocol used for Appletalk, IPX and in
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
The Frame Diverter allows you to divert packets from the
......
......@@ -523,8 +523,18 @@ static int ip_build_xmit_slow(struct sock *sk,
/*
* Get the memory we require with some space left for alignment.
*/
skb = sock_alloc_send_skb(sk, fraglen+hh_len+15, flags&MSG_DONTWAIT, &err);
if (!(flags & MSG_DONTWAIT) || nfrags == 0) {
skb = sock_alloc_send_skb(sk, fraglen + hh_len + 15,
(flags & MSG_DONTWAIT), &err);
} else {
/* On a non-blocking write, we check for send buffer
* usage on the first fragment only.
*/
skb = sock_wmalloc(sk, fraglen + hh_len + 15, 1,
sk->allocation);
if (!skb)
err = -ENOBUFS;
}
if (skb == NULL)
goto error;
......
......@@ -23,25 +23,3 @@ CONFIG_IPX_INTERN
If you don't know what you are doing, say N.
CONFIG_SPX
* Orphaned entry retained 20 April 2001 by Petr Vandrovec *
* If you read this note from the configurator, please contact *
* the Configure.help maintainers. *
The Sequenced Packet eXchange protocol is a transport layer protocol
built on top of IPX. It is used in Novell NetWare systems for
client-server applications and is similar to TCP (which runs on top
of IP).
Note that Novell NetWare file sharing does not use SPX; it uses a
protocol called NCP, for which separate Linux support is available
("NCP file system support" below for the client side, and the user
space programs lwared or mars_nwe for the server side).
Say Y here if you have use for SPX; read the IPX-HOWTO at
<http://www.linuxdoc.org/docs.html#howto> for details.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module will be called af_spx.o. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>.
......@@ -3,6 +3,3 @@
#
bool ' IPX: Full internal IPX network' CONFIG_IPX_INTERN
#if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
# dep_tristate ' IPX: SPX networking (EXPERIMENTAL)' CONFIG_SPX $CONFIG_IPX
#fi
......@@ -8,7 +8,6 @@ obj-$(CONFIG_IPX) += ipx.o
ipx-y := af_ipx.o
ipx-$(CONFIG_SYSCTL) += sysctl_net_ipx.o
ipx-$(CONFIG_SPX) += af_spx.o
ipx-objs := $(ipx-y)
include $(TOPDIR)/Rules.make
This diff is collapsed.
This diff is collapsed.
......@@ -17,21 +17,36 @@
/* From af_ipx.c */
extern int sysctl_ipx_pprop_broadcasting;
ctl_table ipx_table[] = {
{ NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting",
&sysctl_ipx_pprop_broadcasting, sizeof(int), 0644, NULL,
&proc_dointvec },
{ 0 }
static struct ctl_table ipx_table[] = {
{
.ctl_name = NET_IPX_PPROP_BROADCASTING,
.procname = "ipx_pprop_broadcasting",
.data = &sysctl_ipx_pprop_broadcasting,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec,
},
{ 0 },
};
static ctl_table ipx_dir_table[] = {
{ NET_IPX, "ipx", NULL, 0, 0555, ipx_table },
{ 0 }
static struct ctl_table ipx_dir_table[] = {
{
.ctl_name = NET_IPX,
.procname = "ipx",
.mode = 0555,
.child = ipx_table,
},
{ 0 },
};
static ctl_table ipx_root_table[] = {
{ CTL_NET, "net", NULL, 0, 0555, ipx_dir_table },
{ 0 }
static struct ctl_table ipx_root_table[] = {
{
.ctl_name = CTL_NET,
.procname = "net",
.mode = 0555,
.child = ipx_dir_table,
},
{ 0 },
};
static struct ctl_table_header *ipx_table_header;
......
This diff is collapsed.
This diff is collapsed.
......@@ -2808,20 +2808,20 @@ static struct llc_conn_state_trans *llc_reject_state_transitions[] = {
[36] = &llc_reject_state_trans_8a,
[37] = &llc_reject_state_trans_8b,
[38] = &llc_reject_state_trans_9,
[40] = &llc_reject_state_trans_10a,
[41] = &llc_reject_state_trans_10b,
[42] = &llc_reject_state_trans_10c,
[43] = &llc_reject_state_trans_11,
[44] = &llc_reject_state_trans_12a,
[45] = &llc_reject_state_trans_12b,
[46] = &llc_reject_state_trans_12c,
[47] = &llc_reject_state_trans_13,
[48] = &llc_reject_state_trans_14a,
[49] = &llc_reject_state_trans_14b,
[50] = &llc_reject_state_trans_15a,
[51] = &llc_reject_state_trans_15b,
[52] = &llc_reject_state_trans_16,
[53] = &llc_common_state_trans_n,
[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_n,
};
/* LLC_CONN_STATE_AWAIT transitions */
......
......@@ -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)
{
struct sk_buff *skb;
llc_pdu_sn_t *pdu;
struct llc_pdu_sn *pdu;
u16 nbr_unack_pdus;
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)
* appropriate PDUs, fix them up, and put them on mac_pdu_q.
*/
while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) {
pdu = (llc_pdu_sn_t *)skb->nh.raw;
pdu = (struct llc_pdu_sn *)skb->nh.raw;
llc_pdu_set_cmd_rsp(skb, LLC_PDU_CMD);
llc_pdu_set_pf_bit(skb, first_p_bit);
skb_queue_tail(&sk->write_queue, skb);
......@@ -201,7 +201,7 @@ out:;
void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit)
{
struct sk_buff *skb;
llc_pdu_sn_t *pdu;
struct llc_pdu_sn *pdu;
u16 nbr_unack_pdus;
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)
* appropriate PDUs, fix them up, and put them on mac_pdu_q
*/
while ((skb = skb_dequeue(&llc_sk(sk)->pdu_unack_q)) != NULL) {
pdu = (llc_pdu_sn_t *)skb->nh.raw;
pdu = (struct llc_pdu_sn *)skb->nh.raw;
llc_pdu_set_cmd_rsp(skb, LLC_PDU_RSP);
llc_pdu_set_pf_bit(skb, first_f_bit);
skb_queue_tail(&sk->write_queue, skb);
......@@ -240,14 +240,14 @@ int llc_conn_remove_acked_pdus(struct sock *sk, u8 nr, u16 *how_many_unacked)
{
int pdu_pos, i;
struct sk_buff *skb;
llc_pdu_sn_t *pdu;
struct llc_pdu_sn *pdu;
int nbr_acked = 0;
int q_len = skb_queue_len(&llc_sk(sk)->pdu_unack_q);
if (!q_len)
goto out;
skb = skb_peek(&llc_sk(sk)->pdu_unack_q);
pdu = (llc_pdu_sn_t *)skb->nh.raw;
pdu = (struct llc_pdu_sn *)skb->nh.raw;
/* finding position of last acked pdu in queue */
pdu_pos = ((int)LLC_2_SEQ_NBR_MODULO + (int)nr -
......@@ -275,7 +275,7 @@ static void llc_conn_send_pdus(struct sock *sk)
struct sk_buff *skb;
while ((skb = skb_dequeue(&sk->write_queue)) != NULL) {
llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)skb->nh.raw;
struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)skb->nh.raw;
if (!LLC_PDU_TYPE_IS_I(pdu) &&
!(skb->dev->flags & IFF_LOOPBACK))
......@@ -297,7 +297,8 @@ void llc_conn_free_ev(struct llc_conn_state_ev *ev)
{
if (ev->type == LLC_CONN_EV_TYPE_PDU) {
/* free the frame that binded to this event */
llc_pdu_sn_t *pdu = (llc_pdu_sn_t *)ev->data.pdu.skb->nh.raw;
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)
kfree_skb(ev->data.pdu.skb);
......@@ -488,7 +489,6 @@ void __init llc_build_offset_table(void)
struct llc_conn_state *curr_state;
int state, ev_type, next_offset;
memset(llc_offset_table, 0, sizeof(llc_offset_table));
for (state = 0; state < NBR_CONN_STATES; state++) {
curr_state = &llc_conn_state_table[state];
next_offset = 0;
......
......@@ -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,
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 &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */
......@@ -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,
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 &&
!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,
int llc_stat_ev_rx_null_dsap_1_xid_r_xid_r_cnt_eq(struct llc_station *station,
struct llc_station_state_ev *ev)
{
llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
return ev->type == LLC_STATION_EV_TYPE_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,
int llc_stat_ev_rx_null_dsap_test_c(struct llc_station *station,
struct llc_station_state_ev *ev)
{
llc_pdu_un_t *pdu = (llc_pdu_un_t *)ev->data.pdu.skb->nh.raw;
struct llc_pdu_un *pdu = (struct llc_pdu_un *)ev->data.pdu.skb->nh.raw;
return ev->type == LLC_STATION_EV_TYPE_PDU &&
!LLC_PDU_IS_CMD(pdu) && /* command PDU */
......
......@@ -77,8 +77,8 @@ static llc_prim_call_t llc_resp_prim[LLC_NBR_PRIMITIVES] = {
* @sap: pointer to allocated SAP (output argument).
*
* Interface function to upper layer. each one who wants to get a SAP
* (for example NetBEUI) should call this function. Returns 0 for
* success, 1 for failure.
* (for example NetBEUI) should call this function. Returns the opened
* SAP for success, NULL for failure.
*/
struct llc_sap *llc_sap_open(llc_prim_call_t nw_indicate,
llc_prim_call_t nw_confirm, u8 lsap)
......
This diff is collapsed.
This diff is collapsed.
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