Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
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