Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
14d8ce70
Commit
14d8ce70
authored
Jun 04, 2005
by
Committed by
Jeff Garzik
Jun 04, 2005
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of /spare/repo/netdev-2.6 branch hdlc
parents
79121839
b3dd65f9
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
216 additions
and
175 deletions
+216
-175
Documentation/networking/generic-hdlc.txt
Documentation/networking/generic-hdlc.txt
+26
-25
drivers/net/wan/hdlc_fr.c
drivers/net/wan/hdlc_fr.c
+176
-144
drivers/net/wan/hdlc_generic.c
drivers/net/wan/hdlc_generic.c
+11
-5
include/linux/hdlc.h
include/linux/hdlc.h
+3
-1
No files found.
Documentation/networking/generic-hdlc.txt
View file @
14d8ce70
Generic HDLC layer
Krzysztof Halasa <khc@pm.waw.pl>
January, 2003
Generic HDLC layer currently supports:
- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
Normal (routed) and Ethernet-bridged (Ethernet device emulation)
interfaces can share a single PVC.
- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
- Cisco HDLC,
- PPP (uses syncppp.c),
- X.25 (uses X.25 routines).
There are hardware drivers for the following cards:
- C101 by Moxa Technologies Co., Ltd.
- RISCom/N2 by SDL Communications Inc.
- and others, some not in the official kernel.
1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
- Normal (routed) and Ethernet-bridged (Ethernet device emulation)
interfaces can share a single PVC.
- ARP support (no InARP support in the kernel - there is an
experimental InARP user-space daemon available on:
http://www.kernel.org/pub/linux/utils/net/hdlc/).
2. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
3. Cisco HDLC.
4. PPP (uses syncppp.c).
5. X.25 (uses X.25 routines).
Generic HDLC is a protocol driver only - it needs a low-level driver
for your particular hardware.
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
...
...
@@ -24,7 +24,7 @@ with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
Make sure the hdlc.o and the hardware driver are loaded. It should
create a number of "hdlc" (hdlc0 etc) network devices, one for each
WAN port. You'll need the "sethdlc" utility, get it from:
http://
hq.pm.waw.pl
/hdlc/
http://
www.kernel.org/pub/linux/utils/net
/hdlc/
Compile sethdlc.c utility:
gcc -O2 -Wall -o sethdlc sethdlc.c
...
...
@@ -52,12 +52,12 @@ Setting interface:
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
if the card has software-selectable interfaces
loopback - activate hardware loopback (for testing only)
* clock ext -
external clock (uses DTE RX and TX clock)
* clock int -
internal clock (provides clock signal on DCE clock output)
* clock txint -
TX internal, RX external (provides TX clock on DCE output)
* clock txfromrx -
TX clock derived from RX clock (TX clock on DCE output)
* rate - sets clock rate in bps (
not required for external clock or
for txfromrx)
* clock ext -
both RX clock and TX clock external
* clock int -
both RX clock and TX clock internal
* clock txint -
RX clock external, TX clock internal
* clock txfromrx -
RX clock external, TX clock derived from RX clock
* rate - sets clock rate in bps (
for "int" or "txint" clock only)
Setting protocol:
...
...
@@ -79,7 +79,7 @@ Setting protocol:
* x25 - sets X.25 mode
* fr - Frame Relay mode
lmi ansi / ccitt / none - LMI (link management) type
lmi ansi / ccitt /
cisco /
none - LMI (link management) type
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
It has nothing to do with clocks!
t391 - link integrity verification polling timer (in seconds) - user
...
...
@@ -119,13 +119,14 @@ or
If you have a problem with N2
or C101 card, you can issue the "private"
command to see port's packet descriptor rings (in kernel logs):
If you have a problem with N2
, C101 or PLX200SYN card, you can issue the
"private"
command to see port's packet descriptor rings (in kernel logs):
sethdlc hdlc0 private
The hardware driver has to be build with
CONFIG_HDLC_
DEBUG_RINGS.
The hardware driver has to be build with
#define
DEBUG_RINGS.
Attaching this info to bug reports would be helpful. Anyway, let me know
if you have problems using this.
For patches and other info look at http://hq.pm.waw.pl/hdlc/
For patches and other info look at:
<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
drivers/net/wan/hdlc_fr.c
View file @
14d8ce70
...
...
@@ -2,7 +2,7 @@
* Generic HDLC support routines for Linux
* Frame Relay support
*
* Copyright (C) 1999 - 200
3
Krzysztof Halasa <khc@pm.waw.pl>
* Copyright (C) 1999 - 200
5
Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
...
...
@@ -27,6 +27,10 @@
active = open and "link reliable"
exist = new = not used
CCITT LMI: ITU-T Q.933 Annex A
ANSI LMI: ANSI T1.617 Annex D
CISCO LMI: the original, aka "Gang of Four" LMI
*/
#include <linux/module.h>
...
...
@@ -49,45 +53,41 @@
#undef DEBUG_ECN
#undef DEBUG_LINK
#define MAXLEN_LMISTAT 20
/* max size of status enquiry frame */
#define PVC_STATE_NEW 0x01
#define PVC_STATE_ACTIVE 0x02
#define PVC_STATE_FECN 0x08
/* FECN condition */
#define PVC_STATE_BECN 0x10
/* BECN condition */
#define FR_UI 0x03
#define FR_PAD 0x00
#define NLPID_IP 0xCC
#define NLPID_IPV6 0x8E
#define NLPID_SNAP 0x80
#define NLPID_PAD 0x00
#define NLPID_Q933 0x08
#define LMI_DLCI 0
/* LMI DLCI */
#define LMI_PROTO 0x08
#define LMI_CALLREF 0x00
/* Call Reference */
#define LMI_ANSI_LOCKSHIFT 0x95
/* ANSI lockshift */
#define LMI_REPTYPE 1
/* report type */
#define LMI_CCITT_REPTYPE 0x51
#define LMI_ALIVE 3
/* keep alive */
#define LMI_CCITT_ALIVE 0x53
#define LMI_PVCSTAT 7
/* pvc status */
#define LMI_CCITT_PVCSTAT 0x57
#define LMI_FULLREP 0
/* full report */
#define LMI_INTEGRITY 1
/* link integrity report */
#define LMI_SINGLE 2
/* single pvc report */
#define FR_UI 0x03
#define FR_PAD 0x00
#define NLPID_IP 0xCC
#define NLPID_IPV6 0x8E
#define NLPID_SNAP 0x80
#define NLPID_PAD 0x00
#define NLPID_CCITT_ANSI_LMI 0x08
#define NLPID_CISCO_LMI 0x09
#define LMI_CCITT_ANSI_DLCI 0
/* LMI DLCI */
#define LMI_CISCO_DLCI 1023
#define LMI_CALLREF 0x00
/* Call Reference */
#define LMI_ANSI_LOCKSHIFT 0x95
/* ANSI locking shift */
#define LMI_ANSI_CISCO_REPTYPE 0x01
/* report type */
#define LMI_CCITT_REPTYPE 0x51
#define LMI_ANSI_CISCO_ALIVE 0x03
/* keep alive */
#define LMI_CCITT_ALIVE 0x53
#define LMI_ANSI_CISCO_PVCSTAT 0x07
/* PVC status */
#define LMI_CCITT_PVCSTAT 0x57
#define LMI_FULLREP 0x00
/* full report */
#define LMI_INTEGRITY 0x01
/* link integrity report */
#define LMI_SINGLE 0x02
/* single PVC report */
#define LMI_STATUS_ENQUIRY 0x75
#define LMI_STATUS 0x7D
/* reply */
#define LMI_REPT_LEN 1
/* report type element length */
#define LMI_INTEG_LEN 2
/* link integrity element length */
#define LMI_
LENGTH 13
/* standard LMI frame length
*/
#define LMI_ANSI_LENGTH
14
#define LMI_
CCITT_CISCO_LENGTH 13
/* LMI frame lengths
*/
#define LMI_ANSI_LENGTH
14
typedef
struct
{
...
...
@@ -223,51 +223,34 @@ static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
}
static
inline
u16
status_to_dlci
(
u8
*
status
,
int
*
active
,
int
*
new
)
{
*
new
=
(
status
[
2
]
&
0x08
)
?
1
:
0
;
*
active
=
(
status
[
2
]
&
0x02
)
?
1
:
0
;
return
((
status
[
0
]
&
0x3F
)
<<
4
)
|
((
status
[
1
]
&
0x78
)
>>
3
);
}
static
inline
void
dlci_to_status
(
u16
dlci
,
u8
*
status
,
int
active
,
int
new
)
{
status
[
0
]
=
(
dlci
>>
4
)
&
0x3F
;
status
[
1
]
=
((
dlci
<<
3
)
&
0x78
)
|
0x80
;
status
[
2
]
=
0x80
;
if
(
new
)
status
[
2
]
|=
0x08
;
else
if
(
active
)
status
[
2
]
|=
0x02
;
}
static
int
fr_hard_header
(
struct
sk_buff
**
skb_p
,
u16
dlci
)
{
u16
head_len
;
struct
sk_buff
*
skb
=
*
skb_p
;
switch
(
skb
->
protocol
)
{
case
__constant_ntohs
(
ETH_P_IP
):
case
__constant_ntohs
(
NLPID_CCITT_ANSI_LMI
):
head_len
=
4
;
skb_push
(
skb
,
head_len
);
skb
->
data
[
3
]
=
NLPID_
IP
;
skb
->
data
[
3
]
=
NLPID_
CCITT_ANSI_LMI
;
break
;
case
__constant_ntohs
(
ETH_P_IPV6
):
case
__constant_ntohs
(
NLPID_CISCO_LMI
):
head_len
=
4
;
skb_push
(
skb
,
head_len
);
skb
->
data
[
3
]
=
NLPID_
IPV6
;
skb
->
data
[
3
]
=
NLPID_
CISCO_LMI
;
break
;
case
__constant_ntohs
(
LMI_PROTO
):
case
__constant_ntohs
(
ETH_P_IP
):
head_len
=
4
;
skb_push
(
skb
,
head_len
);
skb
->
data
[
3
]
=
NLPID_IP
;
break
;
case
__constant_ntohs
(
ETH_P_IPV6
):
head_len
=
4
;
skb_push
(
skb
,
head_len
);
skb
->
data
[
3
]
=
LMI_PROTO
;
skb
->
data
[
3
]
=
NLPID_IPV6
;
break
;
case
__constant_ntohs
(
ETH_P_802_3
):
...
...
@@ -461,13 +444,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
hdlc_device
*
hdlc
=
dev_to_hdlc
(
dev
);
struct
sk_buff
*
skb
;
pvc_device
*
pvc
=
hdlc
->
state
.
fr
.
first_pvc
;
int
len
=
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_ANSI
)
?
LMI_ANSI_LENGTH
:
LMI_LENGTH
;
int
stat_len
=
3
;
int
lmi
=
hdlc
->
state
.
fr
.
settings
.
lmi
;
int
dce
=
hdlc
->
state
.
fr
.
settings
.
dce
;
int
len
=
lmi
==
LMI_ANSI
?
LMI_ANSI_LENGTH
:
LMI_CCITT_CISCO_LENGTH
;
int
stat_len
=
(
lmi
==
LMI_CISCO
)
?
6
:
3
;
u8
*
data
;
int
i
=
0
;
if
(
hdlc
->
state
.
fr
.
settings
.
dce
&&
fullrep
)
{
if
(
dce
&&
fullrep
)
{
len
+=
hdlc
->
state
.
fr
.
dce_pvc_count
*
(
2
+
stat_len
);
if
(
len
>
HDLC_MAX_MRU
)
{
printk
(
KERN_WARNING
"%s: Too many PVCs while sending "
...
...
@@ -484,29 +468,31 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
}
memset
(
skb
->
data
,
0
,
len
);
skb_reserve
(
skb
,
4
);
skb
->
protocol
=
__constant_htons
(
LMI_PROTO
);
fr_hard_header
(
&
skb
,
LMI_DLCI
);
if
(
lmi
==
LMI_CISCO
)
{
skb
->
protocol
=
__constant_htons
(
NLPID_CISCO_LMI
);
fr_hard_header
(
&
skb
,
LMI_CISCO_DLCI
);
}
else
{
skb
->
protocol
=
__constant_htons
(
NLPID_CCITT_ANSI_LMI
);
fr_hard_header
(
&
skb
,
LMI_CCITT_ANSI_DLCI
);
}
data
=
skb
->
tail
;
data
[
i
++
]
=
LMI_CALLREF
;
data
[
i
++
]
=
hdlc
->
state
.
fr
.
settings
.
dce
?
LMI_STATUS
:
LMI_STATUS_ENQUIRY
;
if
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_ANSI
)
data
[
i
++
]
=
dce
?
LMI_STATUS
:
LMI_STATUS_ENQUIRY
;
if
(
lmi
==
LMI_ANSI
)
data
[
i
++
]
=
LMI_ANSI_LOCKSHIFT
;
data
[
i
++
]
=
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
)
?
LMI_CCITT_REPTYPE
:
LMI
_REPTYPE
;
data
[
i
++
]
=
lmi
==
LMI_CCITT
?
LMI_CCITT_REPTYPE
:
LMI_ANSI_CISCO
_REPTYPE
;
data
[
i
++
]
=
LMI_REPT_LEN
;
data
[
i
++
]
=
fullrep
?
LMI_FULLREP
:
LMI_INTEGRITY
;
data
[
i
++
]
=
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
)
?
LMI_CCITT_ALIVE
:
LMI_ALIVE
;
data
[
i
++
]
=
lmi
==
LMI_CCITT
?
LMI_CCITT_ALIVE
:
LMI_ANSI_CISCO_ALIVE
;
data
[
i
++
]
=
LMI_INTEG_LEN
;
data
[
i
++
]
=
hdlc
->
state
.
fr
.
txseq
=
fr_lmi_nextseq
(
hdlc
->
state
.
fr
.
txseq
);
data
[
i
++
]
=
hdlc
->
state
.
fr
.
rxseq
;
if
(
hdlc
->
state
.
fr
.
settings
.
dce
&&
fullrep
)
{
if
(
dce
&&
fullrep
)
{
while
(
pvc
)
{
data
[
i
++
]
=
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
)
?
LMI_CCITT_PVCSTAT
:
LMI
_PVCSTAT
;
data
[
i
++
]
=
lmi
==
LMI_CCITT
?
LMI_CCITT_PVCSTAT
:
LMI_ANSI_CISCO
_PVCSTAT
;
data
[
i
++
]
=
stat_len
;
/* LMI start/restart */
...
...
@@ -523,8 +509,20 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
fr_log_dlci_active
(
pvc
);
}
dlci_to_status
(
pvc
->
dlci
,
data
+
i
,
pvc
->
state
.
active
,
pvc
->
state
.
new
);
if
(
lmi
==
LMI_CISCO
)
{
data
[
i
]
=
pvc
->
dlci
>>
8
;
data
[
i
+
1
]
=
pvc
->
dlci
&
0xFF
;
}
else
{
data
[
i
]
=
(
pvc
->
dlci
>>
4
)
&
0x3F
;
data
[
i
+
1
]
=
((
pvc
->
dlci
<<
3
)
&
0x78
)
|
0x80
;
data
[
i
+
2
]
=
0x80
;
}
if
(
pvc
->
state
.
new
)
data
[
i
+
2
]
|=
0x08
;
else
if
(
pvc
->
state
.
active
)
data
[
i
+
2
]
|=
0x02
;
i
+=
stat_len
;
pvc
=
pvc
->
next
;
}
...
...
@@ -569,6 +567,8 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
pvc_carrier
(
0
,
pvc
);
pvc
->
state
.
exist
=
pvc
->
state
.
active
=
0
;
pvc
->
state
.
new
=
0
;
if
(
!
hdlc
->
state
.
fr
.
settings
.
dce
)
pvc
->
state
.
bandwidth
=
0
;
pvc
=
pvc
->
next
;
}
}
...
...
@@ -583,11 +583,12 @@ static void fr_timer(unsigned long arg)
int
i
,
cnt
=
0
,
reliable
;
u32
list
;
if
(
hdlc
->
state
.
fr
.
settings
.
dce
)
if
(
hdlc
->
state
.
fr
.
settings
.
dce
)
{
reliable
=
hdlc
->
state
.
fr
.
request
&&
time_before
(
jiffies
,
hdlc
->
state
.
fr
.
last_poll
+
hdlc
->
state
.
fr
.
settings
.
t392
*
HZ
);
else
{
hdlc
->
state
.
fr
.
request
=
0
;
}
else
{
hdlc
->
state
.
fr
.
last_errors
<<=
1
;
/* Shift the list */
if
(
hdlc
->
state
.
fr
.
request
)
{
if
(
hdlc
->
state
.
fr
.
reliable
)
...
...
@@ -634,65 +635,88 @@ static void fr_timer(unsigned long arg)
static
int
fr_lmi_recv
(
struct
net_device
*
dev
,
struct
sk_buff
*
skb
)
{
hdlc_device
*
hdlc
=
dev_to_hdlc
(
dev
);
int
stat_len
;
pvc_device
*
pvc
;
int
reptype
=
-
1
,
error
,
no_ram
;
u8
rxseq
,
txseq
;
int
i
;
int
lmi
=
hdlc
->
state
.
fr
.
settings
.
lmi
;
int
dce
=
hdlc
->
state
.
fr
.
settings
.
dce
;
int
stat_len
=
(
lmi
==
LMI_CISCO
)
?
6
:
3
,
reptype
,
error
,
no_ram
,
i
;
if
(
skb
->
len
<
(
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_ANSI
)
?
LMI_ANSI_LENGTH
:
LMI
_LENGTH
))
{
if
(
skb
->
len
<
(
lmi
==
LMI_ANSI
?
LMI_ANSI_LENGTH
:
LMI_CCITT_CISCO
_LENGTH
))
{
printk
(
KERN_INFO
"%s: Short LMI frame
\n
"
,
dev
->
name
);
return
1
;
}
if
(
skb
->
data
[
5
]
!=
(
!
hdlc
->
state
.
fr
.
settings
.
dce
?
LMI_STATUS
:
LMI_STATUS_ENQUIRY
))
{
printk
(
KERN_INFO
"%s: LMI msgtype=%x, Not LMI status %s
\n
"
,
dev
->
name
,
skb
->
data
[
2
],
hdlc
->
state
.
fr
.
settings
.
dce
?
"enquiry"
:
"reply"
);
if
(
skb
->
data
[
3
]
!=
(
lmi
==
LMI_CISCO
?
NLPID_CISCO_LMI
:
NLPID_CCITT_ANSI_LMI
))
{
printk
(
KERN_INFO
"%s: Received non-LMI frame with LMI"
" DLCI
\n
"
,
dev
->
name
);
return
1
;
}
if
(
skb
->
data
[
4
]
!=
LMI_CALLREF
)
{
printk
(
KERN_INFO
"%s: Invalid LMI Call reference (0x%02X)
\n
"
,
dev
->
name
,
skb
->
data
[
4
]);
return
1
;
}
if
(
skb
->
data
[
5
]
!=
(
dce
?
LMI_STATUS_ENQUIRY
:
LMI_STATUS
))
{
printk
(
KERN_INFO
"%s: Invalid LMI Message type (0x%02X)
\n
"
,
dev
->
name
,
skb
->
data
[
5
]);
return
1
;
}
i
=
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_ANSI
)
?
7
:
6
;
if
(
lmi
==
LMI_ANSI
)
{
if
(
skb
->
data
[
6
]
!=
LMI_ANSI_LOCKSHIFT
)
{
printk
(
KERN_INFO
"%s: Not ANSI locking shift in LMI"
" message (0x%02X)
\n
"
,
dev
->
name
,
skb
->
data
[
6
]);
return
1
;
}
i
=
7
;
}
else
i
=
6
;
if
(
skb
->
data
[
i
]
!=
((
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
)
?
LMI_CCITT_REPTYPE
:
LMI_REPTYPE
))
{
printk
(
KERN_INFO
"%s: Not a report type=%x
\n
"
,
if
(
skb
->
data
[
i
]
!=
(
lmi
==
LMI_CCITT
?
LMI_CCITT_REPTYPE
:
LMI_ANSI_CISCO_REPTYPE
))
{
printk
(
KERN_INFO
"%s: Not an LMI Report type IE (0x%02X)
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
return
1
;
}
i
++
;
i
++
;
/* Skip length field */
if
(
skb
->
data
[
++
i
]
!=
LMI_REPT_LEN
)
{
printk
(
KERN_INFO
"%s: Invalid LMI Report type IE length"
" (%u)
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
return
1
;
}
reptype
=
skb
->
data
[
i
++
];
reptype
=
skb
->
data
[
++
i
];
if
(
reptype
!=
LMI_INTEGRITY
&&
reptype
!=
LMI_FULLREP
)
{
printk
(
KERN_INFO
"%s: Unsupported LMI Report type (0x%02X)
\n
"
,
dev
->
name
,
reptype
);
return
1
;
}
if
(
skb
->
data
[
i
]
!=
((
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
)
?
LMI_CCITT_ALIVE
:
LMI_ALIVE
))
{
printk
(
KERN_INFO
"%s: Unsupported status element=%x
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
if
(
skb
->
data
[
++
i
]
!=
(
lmi
==
LMI_CCITT
?
LMI_CCITT_ALIVE
:
LMI_ANSI_CISCO_ALIVE
))
{
printk
(
KERN_INFO
"%s: Not an LMI Link integrity verification"
" IE (0x%02X)
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
return
1
;
}
i
++
;
i
++
;
/* Skip length field */
if
(
skb
->
data
[
++
i
]
!=
LMI_INTEG_LEN
)
{
printk
(
KERN_INFO
"%s: Invalid LMI Link integrity verification"
" IE length (%u)
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
return
1
;
}
i
++
;
hdlc
->
state
.
fr
.
rxseq
=
skb
->
data
[
i
++
];
/* TX sequence from peer */
rxseq
=
skb
->
data
[
i
++
];
/* Should confirm our sequence */
txseq
=
hdlc
->
state
.
fr
.
txseq
;
if
(
hdlc
->
state
.
fr
.
settings
.
dce
)
{
if
(
reptype
!=
LMI_FULLREP
&&
reptype
!=
LMI_INTEGRITY
)
{
printk
(
KERN_INFO
"%s: Unsupported report type=%x
\n
"
,
dev
->
name
,
reptype
);
return
1
;
}
if
(
dce
)
hdlc
->
state
.
fr
.
last_poll
=
jiffies
;
}
error
=
0
;
if
(
!
hdlc
->
state
.
fr
.
reliable
)
...
...
@@ -703,7 +727,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
error
=
1
;
}
if
(
hdlc
->
state
.
fr
.
settings
.
dce
)
{
if
(
dce
)
{
if
(
hdlc
->
state
.
fr
.
fullrep_sent
&&
!
error
)
{
/* Stop sending full report - the last one has been confirmed by DTE */
hdlc
->
state
.
fr
.
fullrep_sent
=
0
;
...
...
@@ -725,6 +749,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
hdlc
->
state
.
fr
.
dce_changed
=
0
;
}
hdlc
->
state
.
fr
.
request
=
1
;
/* got request */
fr_lmi_send
(
dev
,
reptype
==
LMI_FULLREP
?
1
:
0
);
return
0
;
}
...
...
@@ -739,7 +764,6 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if
(
reptype
!=
LMI_FULLREP
)
return
0
;
stat_len
=
3
;
pvc
=
hdlc
->
state
.
fr
.
first_pvc
;
while
(
pvc
)
{
...
...
@@ -750,24 +774,35 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
no_ram
=
0
;
while
(
skb
->
len
>=
i
+
2
+
stat_len
)
{
u16
dlci
;
u32
bw
;
unsigned
int
active
,
new
;
if
(
skb
->
data
[
i
]
!=
(
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
)
?
LMI_CCITT_PVCSTAT
:
LMI
_PVCSTAT
))
{
printk
(
KERN_
WARNING
"%s: Invalid PVCSTAT ID: %x
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
if
(
skb
->
data
[
i
]
!=
(
lmi
==
LMI_CCITT
?
LMI_CCITT_PVCSTAT
:
LMI_ANSI_CISCO
_PVCSTAT
))
{
printk
(
KERN_
INFO
"%s: Not an LMI PVC status IE"
" (0x%02X)
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
return
1
;
}
i
++
;
if
(
skb
->
data
[
i
]
!=
stat_len
)
{
printk
(
KERN_
WARNING
"%s: Invalid PVCSTAT length: %x
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
if
(
skb
->
data
[
++
i
]
!=
stat_len
)
{
printk
(
KERN_
INFO
"%s: Invalid LMI PVC status IE length"
" (%u)
\n
"
,
dev
->
name
,
skb
->
data
[
i
]);
return
1
;
}
i
++
;
dlci
=
status_to_dlci
(
skb
->
data
+
i
,
&
active
,
&
new
);
new
=
!!
(
skb
->
data
[
i
+
2
]
&
0x08
);
active
=
!!
(
skb
->
data
[
i
+
2
]
&
0x02
);
if
(
lmi
==
LMI_CISCO
)
{
dlci
=
(
skb
->
data
[
i
]
<<
8
)
|
skb
->
data
[
i
+
1
];
bw
=
(
skb
->
data
[
i
+
3
]
<<
16
)
|
(
skb
->
data
[
i
+
4
]
<<
8
)
|
(
skb
->
data
[
i
+
5
]);
}
else
{
dlci
=
((
skb
->
data
[
i
]
&
0x3F
)
<<
4
)
|
((
skb
->
data
[
i
+
1
]
&
0x78
)
>>
3
);
bw
=
0
;
}
pvc
=
add_pvc
(
dev
,
dlci
);
...
...
@@ -783,9 +818,11 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc
->
state
.
deleted
=
0
;
if
(
active
!=
pvc
->
state
.
active
||
new
!=
pvc
->
state
.
new
||
bw
!=
pvc
->
state
.
bandwidth
||
!
pvc
->
state
.
exist
)
{
pvc
->
state
.
new
=
new
;
pvc
->
state
.
active
=
active
;
pvc
->
state
.
bandwidth
=
bw
;
pvc_carrier
(
active
,
pvc
);
fr_log_dlci_active
(
pvc
);
}
...
...
@@ -801,6 +838,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc_carrier
(
0
,
pvc
);
pvc
->
state
.
active
=
pvc
->
state
.
new
=
0
;
pvc
->
state
.
exist
=
0
;
pvc
->
state
.
bandwidth
=
0
;
fr_log_dlci_active
(
pvc
);
}
pvc
=
pvc
->
next
;
...
...
@@ -829,22 +867,15 @@ static int fr_rx(struct sk_buff *skb)
dlci
=
q922_to_dlci
(
skb
->
data
);
if
(
dlci
==
LMI_DLCI
)
{
if
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_NONE
)
goto
rx_error
;
/* LMI packet with no LMI? */
if
(
data
[
3
]
==
LMI_PROTO
)
{
if
(
fr_lmi_recv
(
ndev
,
skb
))
goto
rx_error
;
else
{
dev_kfree_skb_any
(
skb
);
return
NET_RX_SUCCESS
;
}
}
printk
(
KERN_INFO
"%s: Received non-LMI frame with LMI DLCI
\n
"
,
ndev
->
name
);
goto
rx_error
;
if
((
dlci
==
LMI_CCITT_ANSI_DLCI
&&
(
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_ANSI
||
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CCITT
))
||
(
dlci
==
LMI_CISCO_DLCI
&&
hdlc
->
state
.
fr
.
settings
.
lmi
==
LMI_CISCO
))
{
if
(
fr_lmi_recv
(
ndev
,
skb
))
goto
rx_error
;
dev_kfree_skb_any
(
skb
);
return
NET_RX_SUCCESS
;
}
pvc
=
find_pvc
(
hdlc
,
dlci
);
...
...
@@ -1170,7 +1201,8 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
if
((
new_settings
.
lmi
!=
LMI_NONE
&&
new_settings
.
lmi
!=
LMI_ANSI
&&
new_settings
.
lmi
!=
LMI_CCITT
)
||
new_settings
.
lmi
!=
LMI_CCITT
&&
new_settings
.
lmi
!=
LMI_CISCO
)
||
new_settings
.
t391
<
1
||
new_settings
.
t392
<
2
||
new_settings
.
n391
<
1
||
...
...
drivers/net/wan/hdlc_generic.c
View file @
14d8ce70
/*
* Generic HDLC support routines for Linux
*
* Copyright (C) 1999 - 200
3
Krzysztof Halasa <khc@pm.waw.pl>
* Copyright (C) 1999 - 200
5
Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
...
...
@@ -38,7 +38,7 @@
#include <linux/hdlc.h>
static
const
char
*
version
=
"HDLC support module revision 1.1
7
"
;
static
const
char
*
version
=
"HDLC support module revision 1.1
8
"
;
#undef DEBUG_LINK
...
...
@@ -126,10 +126,13 @@ void hdlc_set_carrier(int on, struct net_device *dev)
if
(
!
hdlc
->
open
)
goto
carrier_exit
;
if
(
hdlc
->
carrier
)
if
(
hdlc
->
carrier
)
{
printk
(
KERN_INFO
"%s: Carrier detected
\n
"
,
dev
->
name
);
__hdlc_set_carrier_on
(
dev
);
else
}
else
{
printk
(
KERN_INFO
"%s: Carrier lost
\n
"
,
dev
->
name
);
__hdlc_set_carrier_off
(
dev
);
}
carrier_exit:
spin_unlock_irqrestore
(
&
hdlc
->
state_lock
,
flags
);
...
...
@@ -157,8 +160,11 @@ int hdlc_open(struct net_device *dev)
spin_lock_irq
(
&
hdlc
->
state_lock
);
if
(
hdlc
->
carrier
)
if
(
hdlc
->
carrier
)
{
printk
(
KERN_INFO
"%s: Carrier detected
\n
"
,
dev
->
name
);
__hdlc_set_carrier_on
(
dev
);
}
else
printk
(
KERN_INFO
"%s: No carrier
\n
"
,
dev
->
name
);
hdlc
->
open
=
1
;
...
...
include/linux/hdlc.h
View file @
14d8ce70
/*
* Generic HDLC support routines for Linux
*
* Copyright (C) 1999-200
3
Krzysztof Halasa <khc@pm.waw.pl>
* Copyright (C) 1999-200
5
Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
...
...
@@ -41,6 +41,7 @@
#define LMI_NONE 1
/* No LMI, all PVCs are static */
#define LMI_ANSI 2
/* ANSI Annex D */
#define LMI_CCITT 3
/* ITU-T Annex A */
#define LMI_CISCO 4
/* The "original" LMI, aka Gang of Four */
#define HDLC_MAX_MTU 1500
/* Ethernet 1500 bytes */
#define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4)
/* for ETH+VLAN over FR */
...
...
@@ -89,6 +90,7 @@ typedef struct pvc_device_struct {
unsigned
int
deleted
:
1
;
unsigned
int
fecn
:
1
;
unsigned
int
becn
:
1
;
unsigned
int
bandwidth
;
/* Cisco LMI reporting only */
}
state
;
}
pvc_device
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment