aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Halasa <khc@pm.waw.pl>2005-04-21 09:57:25 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-05-15 22:24:12 -0400
commitb3dd65f958354226275522b5a64157834bdc5415 (patch)
tree851d12ea34fb9e5e5eb439a774da5a6a862ca762
parent88d7bd8cb9eb8d64bf7997600b0d64f7834047c5 (diff)
[PATCH] Generic HDLC update
The attached patch updates generic HDLC to version 1.18. FR Cisco LMI production-tested. Please apply to Linux 2.6. Thanks. Changes: - doc updates - added Cisco LMI support to Frame-Relay code - cleaned hdlc_fr.c a bit, removed some orphaned #defines etc. - fixed a problem with non-functional LMI in FR DCE mode. - changed diagnostic messages to better conform to FR standards - all protocols: information about carrier changes (DCD line) is now printed to kernel logs. Signed-Off-By: Krzysztof Halasa <khc@pm.waw.pl>
-rw-r--r--Documentation/networking/generic-hdlc.txt51
-rw-r--r--drivers/net/wan/hdlc_fr.c320
-rw-r--r--drivers/net/wan/hdlc_generic.c16
-rw-r--r--include/linux/hdlc.h4
4 files changed, 216 insertions, 175 deletions
diff --git a/Documentation/networking/generic-hdlc.txt b/Documentation/networking/generic-hdlc.txt
index 7d1dc6b884f3..31bc8b759b75 100644
--- a/Documentation/networking/generic-hdlc.txt
+++ b/Documentation/networking/generic-hdlc.txt
@@ -1,21 +1,21 @@
1Generic HDLC layer 1Generic HDLC layer
2Krzysztof Halasa <khc@pm.waw.pl> 2Krzysztof Halasa <khc@pm.waw.pl>
3January, 2003
4 3
5 4
6Generic HDLC layer currently supports: 5Generic HDLC layer currently supports:
7- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP). 61. Frame Relay (ANSI, CCITT, Cisco and no LMI).
8 Normal (routed) and Ethernet-bridged (Ethernet device emulation) 7 - Normal (routed) and Ethernet-bridged (Ethernet device emulation)
9 interfaces can share a single PVC. 8 interfaces can share a single PVC.
10- raw HDLC - either IP (IPv4) interface or Ethernet device emulation. 9 - ARP support (no InARP support in the kernel - there is an
11- Cisco HDLC, 10 experimental InARP user-space daemon available on:
12- PPP (uses syncppp.c), 11 http://www.kernel.org/pub/linux/utils/net/hdlc/).
13- X.25 (uses X.25 routines). 122. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
14 133. Cisco HDLC.
15There are hardware drivers for the following cards: 144. PPP (uses syncppp.c).
16- C101 by Moxa Technologies Co., Ltd. 155. X.25 (uses X.25 routines).
17- RISCom/N2 by SDL Communications Inc. 16
18- and others, some not in the official kernel. 17Generic HDLC is a protocol driver only - it needs a low-level driver
18for your particular hardware.
19 19
20Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible 20Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
21with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging). 21with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
@@ -24,7 +24,7 @@ with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
24Make sure the hdlc.o and the hardware driver are loaded. It should 24Make sure the hdlc.o and the hardware driver are loaded. It should
25create a number of "hdlc" (hdlc0 etc) network devices, one for each 25create a number of "hdlc" (hdlc0 etc) network devices, one for each
26WAN port. You'll need the "sethdlc" utility, get it from: 26WAN port. You'll need the "sethdlc" utility, get it from:
27 http://hq.pm.waw.pl/hdlc/ 27 http://www.kernel.org/pub/linux/utils/net/hdlc/
28 28
29Compile sethdlc.c utility: 29Compile sethdlc.c utility:
30 gcc -O2 -Wall -o sethdlc sethdlc.c 30 gcc -O2 -Wall -o sethdlc sethdlc.c
@@ -52,12 +52,12 @@ Setting interface:
52* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port 52* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
53 if the card has software-selectable interfaces 53 if the card has software-selectable interfaces
54 loopback - activate hardware loopback (for testing only) 54 loopback - activate hardware loopback (for testing only)
55* clock ext - external clock (uses DTE RX and TX clock) 55* clock ext - both RX clock and TX clock external
56* clock int - internal clock (provides clock signal on DCE clock output) 56* clock int - both RX clock and TX clock internal
57* clock txint - TX internal, RX external (provides TX clock on DCE output) 57* clock txint - RX clock external, TX clock internal
58* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output) 58* clock txfromrx - RX clock external, TX clock derived from RX clock
59* rate - sets clock rate in bps (not required for external clock or 59* rate - sets clock rate in bps (for "int" or "txint" clock only)
60 for txfromrx) 60
61 61
62Setting protocol: 62Setting protocol:
63 63
@@ -79,7 +79,7 @@ Setting protocol:
79* x25 - sets X.25 mode 79* x25 - sets X.25 mode
80 80
81* fr - Frame Relay mode 81* fr - Frame Relay mode
82 lmi ansi / ccitt / none - LMI (link management) type 82 lmi ansi / ccitt / cisco / none - LMI (link management) type
83 dce - Frame Relay DCE (network) side LMI instead of default DTE (user). 83 dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
84 It has nothing to do with clocks! 84 It has nothing to do with clocks!
85 t391 - link integrity verification polling timer (in seconds) - user 85 t391 - link integrity verification polling timer (in seconds) - user
@@ -119,13 +119,14 @@ or
119 119
120 120
121 121
122If you have a problem with N2 or C101 card, you can issue the "private" 122If you have a problem with N2, C101 or PLX200SYN card, you can issue the
123command to see port's packet descriptor rings (in kernel logs): 123"private" command to see port's packet descriptor rings (in kernel logs):
124 124
125 sethdlc hdlc0 private 125 sethdlc hdlc0 private
126 126
127The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS. 127The hardware driver has to be build with #define DEBUG_RINGS.
128Attaching this info to bug reports would be helpful. Anyway, let me know 128Attaching this info to bug reports would be helpful. Anyway, let me know
129if you have problems using this. 129if you have problems using this.
130 130
131For patches and other info look at http://hq.pm.waw.pl/hdlc/ 131For patches and other info look at:
132<http://www.kernel.org/pub/linux/utils/net/hdlc/>.
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index 7f450b51a6cb..a5d6891c9d4c 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -2,7 +2,7 @@
2 * Generic HDLC support routines for Linux 2 * Generic HDLC support routines for Linux
3 * Frame Relay support 3 * Frame Relay support
4 * 4 *
5 * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> 5 * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify it 7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License 8 * under the terms of version 2 of the GNU General Public License
@@ -27,6 +27,10 @@
27 active = open and "link reliable" 27 active = open and "link reliable"
28 exist = new = not used 28 exist = new = not used
29 29
30 CCITT LMI: ITU-T Q.933 Annex A
31 ANSI LMI: ANSI T1.617 Annex D
32 CISCO LMI: the original, aka "Gang of Four" LMI
33
30*/ 34*/
31 35
32#include <linux/module.h> 36#include <linux/module.h>
@@ -49,45 +53,41 @@
49#undef DEBUG_ECN 53#undef DEBUG_ECN
50#undef DEBUG_LINK 54#undef DEBUG_LINK
51 55
52#define MAXLEN_LMISTAT 20 /* max size of status enquiry frame */ 56#define FR_UI 0x03
53 57#define FR_PAD 0x00
54#define PVC_STATE_NEW 0x01 58
55#define PVC_STATE_ACTIVE 0x02 59#define NLPID_IP 0xCC
56#define PVC_STATE_FECN 0x08 /* FECN condition */ 60#define NLPID_IPV6 0x8E
57#define PVC_STATE_BECN 0x10 /* BECN condition */ 61#define NLPID_SNAP 0x80
58 62#define NLPID_PAD 0x00
59 63#define NLPID_CCITT_ANSI_LMI 0x08
60#define FR_UI 0x03 64#define NLPID_CISCO_LMI 0x09
61#define FR_PAD 0x00 65
62 66
63#define NLPID_IP 0xCC 67#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */
64#define NLPID_IPV6 0x8E 68#define LMI_CISCO_DLCI 1023
65#define NLPID_SNAP 0x80 69
66#define NLPID_PAD 0x00 70#define LMI_CALLREF 0x00 /* Call Reference */
67#define NLPID_Q933 0x08 71#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */
68 72#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */
69 73#define LMI_CCITT_REPTYPE 0x51
70#define LMI_DLCI 0 /* LMI DLCI */ 74#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */
71#define LMI_PROTO 0x08 75#define LMI_CCITT_ALIVE 0x53
72#define LMI_CALLREF 0x00 /* Call Reference */ 76#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */
73#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI lockshift */ 77#define LMI_CCITT_PVCSTAT 0x57
74#define LMI_REPTYPE 1 /* report type */ 78
75#define LMI_CCITT_REPTYPE 0x51 79#define LMI_FULLREP 0x00 /* full report */
76#define LMI_ALIVE 3 /* keep alive */ 80#define LMI_INTEGRITY 0x01 /* link integrity report */
77#define LMI_CCITT_ALIVE 0x53 81#define LMI_SINGLE 0x02 /* single PVC report */
78#define LMI_PVCSTAT 7 /* pvc status */ 82
79#define LMI_CCITT_PVCSTAT 0x57
80#define LMI_FULLREP 0 /* full report */
81#define LMI_INTEGRITY 1 /* link integrity report */
82#define LMI_SINGLE 2 /* single pvc report */
83#define LMI_STATUS_ENQUIRY 0x75 83#define LMI_STATUS_ENQUIRY 0x75
84#define LMI_STATUS 0x7D /* reply */ 84#define LMI_STATUS 0x7D /* reply */
85 85
86#define LMI_REPT_LEN 1 /* report type element length */ 86#define LMI_REPT_LEN 1 /* report type element length */
87#define LMI_INTEG_LEN 2 /* link integrity element length */ 87#define LMI_INTEG_LEN 2 /* link integrity element length */
88 88
89#define LMI_LENGTH 13 /* standard LMI frame length */ 89#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */
90#define LMI_ANSI_LENGTH 14 90#define LMI_ANSI_LENGTH 14
91 91
92 92
93typedef struct { 93typedef struct {
@@ -223,51 +223,34 @@ static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
223} 223}
224 224
225 225
226static inline u16 status_to_dlci(u8 *status, int *active, int *new)
227{
228 *new = (status[2] & 0x08) ? 1 : 0;
229 *active = (status[2] & 0x02) ? 1 : 0;
230
231 return ((status[0] & 0x3F) << 4) | ((status[1] & 0x78) >> 3);
232}
233
234
235static inline void dlci_to_status(u16 dlci, u8 *status, int active, int new)
236{
237 status[0] = (dlci >> 4) & 0x3F;
238 status[1] = ((dlci << 3) & 0x78) | 0x80;
239 status[2] = 0x80;
240
241 if (new)
242 status[2] |= 0x08;
243 else if (active)
244 status[2] |= 0x02;
245}
246
247
248
249static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) 226static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
250{ 227{
251 u16 head_len; 228 u16 head_len;
252 struct sk_buff *skb = *skb_p; 229 struct sk_buff *skb = *skb_p;
253 230
254 switch (skb->protocol) { 231 switch (skb->protocol) {
255 case __constant_ntohs(ETH_P_IP): 232 case __constant_ntohs(NLPID_CCITT_ANSI_LMI):
256 head_len = 4; 233 head_len = 4;
257 skb_push(skb, head_len); 234 skb_push(skb, head_len);
258 skb->data[3] = NLPID_IP; 235 skb->data[3] = NLPID_CCITT_ANSI_LMI;
259 break; 236 break;
260 237
261 case __constant_ntohs(ETH_P_IPV6): 238 case __constant_ntohs(NLPID_CISCO_LMI):
262 head_len = 4; 239 head_len = 4;
263 skb_push(skb, head_len); 240 skb_push(skb, head_len);
264 skb->data[3] = NLPID_IPV6; 241 skb->data[3] = NLPID_CISCO_LMI;
265 break; 242 break;
266 243
267 case __constant_ntohs(LMI_PROTO): 244 case __constant_ntohs(ETH_P_IP):
245 head_len = 4;
246 skb_push(skb, head_len);
247 skb->data[3] = NLPID_IP;
248 break;
249
250 case __constant_ntohs(ETH_P_IPV6):
268 head_len = 4; 251 head_len = 4;
269 skb_push(skb, head_len); 252 skb_push(skb, head_len);
270 skb->data[3] = LMI_PROTO; 253 skb->data[3] = NLPID_IPV6;
271 break; 254 break;
272 255
273 case __constant_ntohs(ETH_P_802_3): 256 case __constant_ntohs(ETH_P_802_3):
@@ -461,13 +444,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
461 hdlc_device *hdlc = dev_to_hdlc(dev); 444 hdlc_device *hdlc = dev_to_hdlc(dev);
462 struct sk_buff *skb; 445 struct sk_buff *skb;
463 pvc_device *pvc = hdlc->state.fr.first_pvc; 446 pvc_device *pvc = hdlc->state.fr.first_pvc;
464 int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH 447 int lmi = hdlc->state.fr.settings.lmi;
465 : LMI_LENGTH; 448 int dce = hdlc->state.fr.settings.dce;
466 int stat_len = 3; 449 int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
450 int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
467 u8 *data; 451 u8 *data;
468 int i = 0; 452 int i = 0;
469 453
470 if (hdlc->state.fr.settings.dce && fullrep) { 454 if (dce && fullrep) {
471 len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); 455 len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
472 if (len > HDLC_MAX_MRU) { 456 if (len > HDLC_MAX_MRU) {
473 printk(KERN_WARNING "%s: Too many PVCs while sending " 457 printk(KERN_WARNING "%s: Too many PVCs while sending "
@@ -484,29 +468,31 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
484 } 468 }
485 memset(skb->data, 0, len); 469 memset(skb->data, 0, len);
486 skb_reserve(skb, 4); 470 skb_reserve(skb, 4);
487 skb->protocol = __constant_htons(LMI_PROTO); 471 if (lmi == LMI_CISCO) {
488 fr_hard_header(&skb, LMI_DLCI); 472 skb->protocol = __constant_htons(NLPID_CISCO_LMI);
473 fr_hard_header(&skb, LMI_CISCO_DLCI);
474 } else {
475 skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI);
476 fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
477 }
489 data = skb->tail; 478 data = skb->tail;
490 data[i++] = LMI_CALLREF; 479 data[i++] = LMI_CALLREF;
491 data[i++] = hdlc->state.fr.settings.dce 480 data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY;
492 ? LMI_STATUS : LMI_STATUS_ENQUIRY; 481 if (lmi == LMI_ANSI)
493 if (hdlc->state.fr.settings.lmi == LMI_ANSI)
494 data[i++] = LMI_ANSI_LOCKSHIFT; 482 data[i++] = LMI_ANSI_LOCKSHIFT;
495 data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT) 483 data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
496 ? LMI_CCITT_REPTYPE : LMI_REPTYPE; 484 LMI_ANSI_CISCO_REPTYPE;
497 data[i++] = LMI_REPT_LEN; 485 data[i++] = LMI_REPT_LEN;
498 data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY; 486 data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
499 487 data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
500 data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
501 ? LMI_CCITT_ALIVE : LMI_ALIVE;
502 data[i++] = LMI_INTEG_LEN; 488 data[i++] = LMI_INTEG_LEN;
503 data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq); 489 data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
504 data[i++] = hdlc->state.fr.rxseq; 490 data[i++] = hdlc->state.fr.rxseq;
505 491
506 if (hdlc->state.fr.settings.dce && fullrep) { 492 if (dce && fullrep) {
507 while (pvc) { 493 while (pvc) {
508 data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT) 494 data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
509 ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT; 495 LMI_ANSI_CISCO_PVCSTAT;
510 data[i++] = stat_len; 496 data[i++] = stat_len;
511 497
512 /* LMI start/restart */ 498 /* LMI start/restart */
@@ -523,8 +509,20 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
523 fr_log_dlci_active(pvc); 509 fr_log_dlci_active(pvc);
524 } 510 }
525 511
526 dlci_to_status(pvc->dlci, data + i, 512 if (lmi == LMI_CISCO) {
527 pvc->state.active, pvc->state.new); 513 data[i] = pvc->dlci >> 8;
514 data[i + 1] = pvc->dlci & 0xFF;
515 } else {
516 data[i] = (pvc->dlci >> 4) & 0x3F;
517 data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80;
518 data[i + 2] = 0x80;
519 }
520
521 if (pvc->state.new)
522 data[i + 2] |= 0x08;
523 else if (pvc->state.active)
524 data[i + 2] |= 0x02;
525
528 i += stat_len; 526 i += stat_len;
529 pvc = pvc->next; 527 pvc = pvc->next;
530 } 528 }
@@ -569,6 +567,8 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
569 pvc_carrier(0, pvc); 567 pvc_carrier(0, pvc);
570 pvc->state.exist = pvc->state.active = 0; 568 pvc->state.exist = pvc->state.active = 0;
571 pvc->state.new = 0; 569 pvc->state.new = 0;
570 if (!hdlc->state.fr.settings.dce)
571 pvc->state.bandwidth = 0;
572 pvc = pvc->next; 572 pvc = pvc->next;
573 } 573 }
574 } 574 }
@@ -583,11 +583,12 @@ static void fr_timer(unsigned long arg)
583 int i, cnt = 0, reliable; 583 int i, cnt = 0, reliable;
584 u32 list; 584 u32 list;
585 585
586 if (hdlc->state.fr.settings.dce) 586 if (hdlc->state.fr.settings.dce) {
587 reliable = hdlc->state.fr.request && 587 reliable = hdlc->state.fr.request &&
588 time_before(jiffies, hdlc->state.fr.last_poll + 588 time_before(jiffies, hdlc->state.fr.last_poll +
589 hdlc->state.fr.settings.t392 * HZ); 589 hdlc->state.fr.settings.t392 * HZ);
590 else { 590 hdlc->state.fr.request = 0;
591 } else {
591 hdlc->state.fr.last_errors <<= 1; /* Shift the list */ 592 hdlc->state.fr.last_errors <<= 1; /* Shift the list */
592 if (hdlc->state.fr.request) { 593 if (hdlc->state.fr.request) {
593 if (hdlc->state.fr.reliable) 594 if (hdlc->state.fr.reliable)
@@ -634,65 +635,88 @@ static void fr_timer(unsigned long arg)
634static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb) 635static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
635{ 636{
636 hdlc_device *hdlc = dev_to_hdlc(dev); 637 hdlc_device *hdlc = dev_to_hdlc(dev);
637 int stat_len;
638 pvc_device *pvc; 638 pvc_device *pvc;
639 int reptype = -1, error, no_ram;
640 u8 rxseq, txseq; 639 u8 rxseq, txseq;
641 int i; 640 int lmi = hdlc->state.fr.settings.lmi;
641 int dce = hdlc->state.fr.settings.dce;
642 int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
642 643
643 if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI) 644 if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
644 ? LMI_ANSI_LENGTH : LMI_LENGTH)) { 645 LMI_CCITT_CISCO_LENGTH)) {
645 printk(KERN_INFO "%s: Short LMI frame\n", dev->name); 646 printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
646 return 1; 647 return 1;
647 } 648 }
648 649
649 if (skb->data[5] != (!hdlc->state.fr.settings.dce ? 650 if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
650 LMI_STATUS : LMI_STATUS_ENQUIRY)) { 651 NLPID_CCITT_ANSI_LMI)) {
651 printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n", 652 printk(KERN_INFO "%s: Received non-LMI frame with LMI"
652 dev->name, skb->data[2], 653 " DLCI\n", dev->name);
653 hdlc->state.fr.settings.dce ? "enquiry" : "reply"); 654 return 1;
655 }
656
657 if (skb->data[4] != LMI_CALLREF) {
658 printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
659 dev->name, skb->data[4]);
660 return 1;
661 }
662
663 if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
664 printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
665 dev->name, skb->data[5]);
654 return 1; 666 return 1;
655 } 667 }
656 668
657 i = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? 7 : 6; 669 if (lmi == LMI_ANSI) {
670 if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
671 printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
672 " message (0x%02X)\n", dev->name, skb->data[6]);
673 return 1;
674 }
675 i = 7;
676 } else
677 i = 6;
658 678
659 if (skb->data[i] != 679 if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
660 ((hdlc->state.fr.settings.lmi == LMI_CCITT) 680 LMI_ANSI_CISCO_REPTYPE)) {
661 ? LMI_CCITT_REPTYPE : LMI_REPTYPE)) { 681 printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
662 printk(KERN_INFO "%s: Not a report type=%x\n",
663 dev->name, skb->data[i]); 682 dev->name, skb->data[i]);
664 return 1; 683 return 1;
665 } 684 }
666 i++;
667 685
668 i++; /* Skip length field */ 686 if (skb->data[++i] != LMI_REPT_LEN) {
687 printk(KERN_INFO "%s: Invalid LMI Report type IE length"
688 " (%u)\n", dev->name, skb->data[i]);
689 return 1;
690 }
669 691
670 reptype = skb->data[i++]; 692 reptype = skb->data[++i];
693 if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
694 printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
695 dev->name, reptype);
696 return 1;
697 }
671 698
672 if (skb->data[i]!= 699 if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
673 ((hdlc->state.fr.settings.lmi == LMI_CCITT) 700 LMI_ANSI_CISCO_ALIVE)) {
674 ? LMI_CCITT_ALIVE : LMI_ALIVE)) { 701 printk(KERN_INFO "%s: Not an LMI Link integrity verification"
675 printk(KERN_INFO "%s: Unsupported status element=%x\n", 702 " IE (0x%02X)\n", dev->name, skb->data[i]);
676 dev->name, skb->data[i]);
677 return 1; 703 return 1;
678 } 704 }
679 i++;
680 705
681 i++; /* Skip length field */ 706 if (skb->data[++i] != LMI_INTEG_LEN) {
707 printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
708 " IE length (%u)\n", dev->name, skb->data[i]);
709 return 1;
710 }
711 i++;
682 712
683 hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */ 713 hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
684 rxseq = skb->data[i++]; /* Should confirm our sequence */ 714 rxseq = skb->data[i++]; /* Should confirm our sequence */
685 715
686 txseq = hdlc->state.fr.txseq; 716 txseq = hdlc->state.fr.txseq;
687 717
688 if (hdlc->state.fr.settings.dce) { 718 if (dce)
689 if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
690 printk(KERN_INFO "%s: Unsupported report type=%x\n",
691 dev->name, reptype);
692 return 1;
693 }
694 hdlc->state.fr.last_poll = jiffies; 719 hdlc->state.fr.last_poll = jiffies;
695 }
696 720
697 error = 0; 721 error = 0;
698 if (!hdlc->state.fr.reliable) 722 if (!hdlc->state.fr.reliable)
@@ -703,7 +727,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
703 error = 1; 727 error = 1;
704 } 728 }
705 729
706 if (hdlc->state.fr.settings.dce) { 730 if (dce) {
707 if (hdlc->state.fr.fullrep_sent && !error) { 731 if (hdlc->state.fr.fullrep_sent && !error) {
708/* Stop sending full report - the last one has been confirmed by DTE */ 732/* Stop sending full report - the last one has been confirmed by DTE */
709 hdlc->state.fr.fullrep_sent = 0; 733 hdlc->state.fr.fullrep_sent = 0;
@@ -725,6 +749,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
725 hdlc->state.fr.dce_changed = 0; 749 hdlc->state.fr.dce_changed = 0;
726 } 750 }
727 751
752 hdlc->state.fr.request = 1; /* got request */
728 fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0); 753 fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
729 return 0; 754 return 0;
730 } 755 }
@@ -739,7 +764,6 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
739 if (reptype != LMI_FULLREP) 764 if (reptype != LMI_FULLREP)
740 return 0; 765 return 0;
741 766
742 stat_len = 3;
743 pvc = hdlc->state.fr.first_pvc; 767 pvc = hdlc->state.fr.first_pvc;
744 768
745 while (pvc) { 769 while (pvc) {
@@ -750,24 +774,35 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
750 no_ram = 0; 774 no_ram = 0;
751 while (skb->len >= i + 2 + stat_len) { 775 while (skb->len >= i + 2 + stat_len) {
752 u16 dlci; 776 u16 dlci;
777 u32 bw;
753 unsigned int active, new; 778 unsigned int active, new;
754 779
755 if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT) 780 if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
756 ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) { 781 LMI_ANSI_CISCO_PVCSTAT)) {
757 printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n", 782 printk(KERN_INFO "%s: Not an LMI PVC status IE"
758 dev->name, skb->data[i]); 783 " (0x%02X)\n", dev->name, skb->data[i]);
759 return 1; 784 return 1;
760 } 785 }
761 i++;
762 786
763 if (skb->data[i] != stat_len) { 787 if (skb->data[++i] != stat_len) {
764 printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n", 788 printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
765 dev->name, skb->data[i]); 789 " (%u)\n", dev->name, skb->data[i]);
766 return 1; 790 return 1;
767 } 791 }
768 i++; 792 i++;
769 793
770 dlci = status_to_dlci(skb->data + i, &active, &new); 794 new = !! (skb->data[i + 2] & 0x08);
795 active = !! (skb->data[i + 2] & 0x02);
796 if (lmi == LMI_CISCO) {
797 dlci = (skb->data[i] << 8) | skb->data[i + 1];
798 bw = (skb->data[i + 3] << 16) |
799 (skb->data[i + 4] << 8) |
800 (skb->data[i + 5]);
801 } else {
802 dlci = ((skb->data[i] & 0x3F) << 4) |
803 ((skb->data[i + 1] & 0x78) >> 3);
804 bw = 0;
805 }
771 806
772 pvc = add_pvc(dev, dlci); 807 pvc = add_pvc(dev, dlci);
773 808
@@ -783,9 +818,11 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
783 pvc->state.deleted = 0; 818 pvc->state.deleted = 0;
784 if (active != pvc->state.active || 819 if (active != pvc->state.active ||
785 new != pvc->state.new || 820 new != pvc->state.new ||
821 bw != pvc->state.bandwidth ||
786 !pvc->state.exist) { 822 !pvc->state.exist) {
787 pvc->state.new = new; 823 pvc->state.new = new;
788 pvc->state.active = active; 824 pvc->state.active = active;
825 pvc->state.bandwidth = bw;
789 pvc_carrier(active, pvc); 826 pvc_carrier(active, pvc);
790 fr_log_dlci_active(pvc); 827 fr_log_dlci_active(pvc);
791 } 828 }
@@ -801,6 +838,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
801 pvc_carrier(0, pvc); 838 pvc_carrier(0, pvc);
802 pvc->state.active = pvc->state.new = 0; 839 pvc->state.active = pvc->state.new = 0;
803 pvc->state.exist = 0; 840 pvc->state.exist = 0;
841 pvc->state.bandwidth = 0;
804 fr_log_dlci_active(pvc); 842 fr_log_dlci_active(pvc);
805 } 843 }
806 pvc = pvc->next; 844 pvc = pvc->next;
@@ -829,22 +867,15 @@ static int fr_rx(struct sk_buff *skb)
829 867
830 dlci = q922_to_dlci(skb->data); 868 dlci = q922_to_dlci(skb->data);
831 869
832 if (dlci == LMI_DLCI) { 870 if ((dlci == LMI_CCITT_ANSI_DLCI &&
833 if (hdlc->state.fr.settings.lmi == LMI_NONE) 871 (hdlc->state.fr.settings.lmi == LMI_ANSI ||
834 goto rx_error; /* LMI packet with no LMI? */ 872 hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
835 873 (dlci == LMI_CISCO_DLCI &&
836 if (data[3] == LMI_PROTO) { 874 hdlc->state.fr.settings.lmi == LMI_CISCO)) {
837 if (fr_lmi_recv(ndev, skb)) 875 if (fr_lmi_recv(ndev, skb))
838 goto rx_error; 876 goto rx_error;
839 else { 877 dev_kfree_skb_any(skb);
840 dev_kfree_skb_any(skb); 878 return NET_RX_SUCCESS;
841 return NET_RX_SUCCESS;
842 }
843 }
844
845 printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
846 ndev->name);
847 goto rx_error;
848 } 879 }
849 880
850 pvc = find_pvc(hdlc, dlci); 881 pvc = find_pvc(hdlc, dlci);
@@ -1170,7 +1201,8 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
1170 1201
1171 if ((new_settings.lmi != LMI_NONE && 1202 if ((new_settings.lmi != LMI_NONE &&
1172 new_settings.lmi != LMI_ANSI && 1203 new_settings.lmi != LMI_ANSI &&
1173 new_settings.lmi != LMI_CCITT) || 1204 new_settings.lmi != LMI_CCITT &&
1205 new_settings.lmi != LMI_CISCO) ||
1174 new_settings.t391 < 1 || 1206 new_settings.t391 < 1 ||
1175 new_settings.t392 < 2 || 1207 new_settings.t392 < 2 ||
1176 new_settings.n391 < 1 || 1208 new_settings.n391 < 1 ||
diff --git a/drivers/net/wan/hdlc_generic.c b/drivers/net/wan/hdlc_generic.c
index 6ed064cb4469..a63f6a2cc4f7 100644
--- a/drivers/net/wan/hdlc_generic.c
+++ b/drivers/net/wan/hdlc_generic.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * Generic HDLC support routines for Linux 2 * Generic HDLC support routines for Linux
3 * 3 *
4 * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> 4 * Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License 7 * under the terms of version 2 of the GNU General Public License
@@ -38,7 +38,7 @@
38#include <linux/hdlc.h> 38#include <linux/hdlc.h>
39 39
40 40
41static const char* version = "HDLC support module revision 1.17"; 41static const char* version = "HDLC support module revision 1.18";
42 42
43#undef DEBUG_LINK 43#undef DEBUG_LINK
44 44
@@ -126,10 +126,13 @@ void hdlc_set_carrier(int on, struct net_device *dev)
126 if (!hdlc->open) 126 if (!hdlc->open)
127 goto carrier_exit; 127 goto carrier_exit;
128 128
129 if (hdlc->carrier) 129 if (hdlc->carrier) {
130 printk(KERN_INFO "%s: Carrier detected\n", dev->name);
130 __hdlc_set_carrier_on(dev); 131 __hdlc_set_carrier_on(dev);
131 else 132 } else {
133 printk(KERN_INFO "%s: Carrier lost\n", dev->name);
132 __hdlc_set_carrier_off(dev); 134 __hdlc_set_carrier_off(dev);
135 }
133 136
134carrier_exit: 137carrier_exit:
135 spin_unlock_irqrestore(&hdlc->state_lock, flags); 138 spin_unlock_irqrestore(&hdlc->state_lock, flags);
@@ -157,8 +160,11 @@ int hdlc_open(struct net_device *dev)
157 160
158 spin_lock_irq(&hdlc->state_lock); 161 spin_lock_irq(&hdlc->state_lock);
159 162
160 if (hdlc->carrier) 163 if (hdlc->carrier) {
164 printk(KERN_INFO "%s: Carrier detected\n", dev->name);
161 __hdlc_set_carrier_on(dev); 165 __hdlc_set_carrier_on(dev);
166 } else
167 printk(KERN_INFO "%s: No carrier\n", dev->name);
162 168
163 hdlc->open = 1; 169 hdlc->open = 1;
164 170
diff --git a/include/linux/hdlc.h b/include/linux/hdlc.h
index 503194e62fe1..ed2927ef1ff7 100644
--- a/include/linux/hdlc.h
+++ b/include/linux/hdlc.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * Generic HDLC support routines for Linux 2 * Generic HDLC support routines for Linux
3 * 3 *
4 * Copyright (C) 1999-2003 Krzysztof Halasa <khc@pm.waw.pl> 4 * Copyright (C) 1999-2005 Krzysztof Halasa <khc@pm.waw.pl>
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of version 2 of the GNU General Public License 7 * under the terms of version 2 of the GNU General Public License
@@ -41,6 +41,7 @@
41#define LMI_NONE 1 /* No LMI, all PVCs are static */ 41#define LMI_NONE 1 /* No LMI, all PVCs are static */
42#define LMI_ANSI 2 /* ANSI Annex D */ 42#define LMI_ANSI 2 /* ANSI Annex D */
43#define LMI_CCITT 3 /* ITU-T Annex A */ 43#define LMI_CCITT 3 /* ITU-T Annex A */
44#define LMI_CISCO 4 /* The "original" LMI, aka Gang of Four */
44 45
45#define HDLC_MAX_MTU 1500 /* Ethernet 1500 bytes */ 46#define HDLC_MAX_MTU 1500 /* Ethernet 1500 bytes */
46#define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */ 47#define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */
@@ -89,6 +90,7 @@ typedef struct pvc_device_struct {
89 unsigned int deleted: 1; 90 unsigned int deleted: 1;
90 unsigned int fecn: 1; 91 unsigned int fecn: 1;
91 unsigned int becn: 1; 92 unsigned int becn: 1;
93 unsigned int bandwidth; /* Cisco LMI reporting only */
92 }state; 94 }state;
93}pvc_device; 95}pvc_device;
94 96