Skip to content

Commit 097b19a

Browse files
Eric Kinziedavem330
authored andcommitted
[ATM]: [br2864] routed support
Signed-off-by: Chas Williams <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 900092a commit 097b19a

File tree

2 files changed

+133
-33
lines changed

2 files changed

+133
-33
lines changed

include/linux/atmbr2684.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#define BR2684_MEDIA_FDDI (3)
1515
#define BR2684_MEDIA_802_6 (4) /* 802.6 */
1616

17+
/* used only at device creation: */
18+
#define BR2684_FLAG_ROUTED (1<<16) /* payload is routed, not bridged */
19+
1720
/*
1821
* Is there FCS inbound on this VC? This currently isn't supported.
1922
*/
@@ -35,14 +38,22 @@
3538
#define BR2684_ENCAPS_LLC (1)
3639
#define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */
3740

41+
/*
42+
* Is this VC bridged or routed?
43+
*/
44+
45+
#define BR2684_PAYLOAD_ROUTED (0)
46+
#define BR2684_PAYLOAD_BRIDGED (1)
47+
48+
3849
/*
3950
* This is for the ATM_NEWBACKENDIF call - these are like socket families:
4051
* the first element of the structure is the backend number and the rest
4152
* is per-backend specific
4253
*/
4354
struct atm_newif_br2684 {
4455
atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */
45-
int media; /* BR2684_MEDIA_* */
56+
int media; /* BR2684_MEDIA_*, flags in upper bits */
4657
char ifname[IFNAMSIZ];
4758
int mtu;
4859
};
@@ -95,6 +106,11 @@ struct br2684_filter_set {
95106
struct br2684_filter filter;
96107
};
97108

109+
enum br2684_payload {
110+
p_routed = BR2684_PAYLOAD_ROUTED,
111+
p_bridged = BR2684_PAYLOAD_BRIDGED,
112+
};
113+
98114
#define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \
99115
struct br2684_filter_set)
100116

net/atm/br2684.c

Lines changed: 116 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/*
2-
Experimental ethernet netdevice using ATM AAL5 as underlying carrier
3-
(RFC1483 obsoleted by RFC2684) for Linux 2.4
4-
Author: Marcell GAL, 2000, XDSL Ltd, Hungary
2+
Ethernet netdevice using ATM AAL5 as underlying carrier
3+
(RFC1483 obsoleted by RFC2684) for Linux
4+
Authors: Marcell GAL, 2000, XDSL Ltd, Hungary
5+
Eric Kinzie, 2006-2007, US Naval Research Laboratory
56
*/
67

78
#include <linux/module.h>
@@ -39,9 +40,27 @@ static void skb_debug(const struct sk_buff *skb)
3940
#define skb_debug(skb) do {} while (0)
4041
#endif
4142

43+
#define BR2684_ETHERTYPE_LEN 2
44+
#define BR2684_PAD_LEN 2
45+
46+
#define LLC 0xaa, 0xaa, 0x03
47+
#define SNAP_BRIDGED 0x00, 0x80, 0xc2
48+
#define SNAP_ROUTED 0x00, 0x00, 0x00
49+
#define PID_ETHERNET 0x00, 0x07
50+
#define ETHERTYPE_IPV4 0x08, 0x00
51+
#define ETHERTYPE_IPV6 0x86, 0xdd
52+
#define PAD_BRIDGED 0x00, 0x00
53+
54+
static unsigned char ethertype_ipv4[] =
55+
{ ETHERTYPE_IPV4 };
56+
static unsigned char ethertype_ipv6[] =
57+
{ ETHERTYPE_IPV6 };
4258
static unsigned char llc_oui_pid_pad[] =
43-
{ 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 };
44-
#define PADLEN (2)
59+
{ LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED };
60+
static unsigned char llc_oui_ipv4[] =
61+
{ LLC, SNAP_ROUTED, ETHERTYPE_IPV4 };
62+
static unsigned char llc_oui_ipv6[] =
63+
{ LLC, SNAP_ROUTED, ETHERTYPE_IPV6 };
4564

4665
enum br2684_encaps {
4766
e_vc = BR2684_ENCAPS_VC,
@@ -69,6 +88,7 @@ struct br2684_dev {
6988
struct list_head brvccs; /* one device <=> one vcc (before xmas) */
7089
struct net_device_stats stats;
7190
int mac_was_set;
91+
enum br2684_payload payload;
7292
};
7393

7494
/*
@@ -136,6 +156,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
136156
{
137157
struct atm_vcc *atmvcc;
138158
int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2;
159+
139160
if (skb_headroom(skb) < minheadroom) {
140161
struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom);
141162
brvcc->copies_needed++;
@@ -146,11 +167,32 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev,
146167
}
147168
skb = skb2;
148169
}
149-
skb_push(skb, minheadroom);
150-
if (brvcc->encaps == e_llc)
151-
skb_copy_to_linear_data(skb, llc_oui_pid_pad, 10);
152-
else
153-
memset(skb->data, 0, 2);
170+
171+
if (brvcc->encaps == e_llc) {
172+
if (brdev->payload == p_bridged) {
173+
skb_push(skb, sizeof(llc_oui_pid_pad));
174+
skb_copy_to_linear_data(skb, llc_oui_pid_pad, sizeof(llc_oui_pid_pad));
175+
} else if (brdev->payload == p_routed) {
176+
unsigned short prot = ntohs(skb->protocol);
177+
178+
skb_push(skb, sizeof(llc_oui_ipv4));
179+
switch (prot) {
180+
case ETH_P_IP:
181+
skb_copy_to_linear_data(skb, llc_oui_ipv4, sizeof(llc_oui_ipv4));
182+
break;
183+
case ETH_P_IPV6:
184+
skb_copy_to_linear_data(skb, llc_oui_ipv6, sizeof(llc_oui_ipv6));
185+
break;
186+
default:
187+
dev_kfree_skb(skb);
188+
return 0;
189+
}
190+
}
191+
} else {
192+
skb_push(skb, 2);
193+
if (brdev->payload == p_bridged)
194+
memset(skb->data, 0, 2);
195+
}
154196
skb_debug(skb);
155197

156198
ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
@@ -299,7 +341,6 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
299341
struct br2684_vcc *brvcc = BR2684_VCC(atmvcc);
300342
struct net_device *net_dev = brvcc->device;
301343
struct br2684_dev *brdev = BRPRIV(net_dev);
302-
int plen = sizeof(llc_oui_pid_pad) + ETH_HLEN;
303344

304345
pr_debug("br2684_push\n");
305346

@@ -320,35 +361,50 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb)
320361
atm_return(atmvcc, skb->truesize);
321362
pr_debug("skb from brdev %p\n", brdev);
322363
if (brvcc->encaps == e_llc) {
364+
365+
if (skb->len > 7 && skb->data[7] == 0x01)
366+
__skb_trim(skb, skb->len - 4);
367+
368+
/* accept packets that have "ipv[46]" in the snap header */
369+
if ((skb->len >= (sizeof(llc_oui_ipv4)))
370+
&& (memcmp(skb->data, llc_oui_ipv4, sizeof(llc_oui_ipv4) - BR2684_ETHERTYPE_LEN) == 0)) {
371+
if (memcmp(skb->data + 6, ethertype_ipv6, sizeof(ethertype_ipv6)) == 0)
372+
skb->protocol = __constant_htons(ETH_P_IPV6);
373+
else if (memcmp(skb->data + 6, ethertype_ipv4, sizeof(ethertype_ipv4)) == 0)
374+
skb->protocol = __constant_htons(ETH_P_IP);
375+
else {
376+
brdev->stats.rx_errors++;
377+
dev_kfree_skb(skb);
378+
return;
379+
}
380+
skb_pull(skb, sizeof(llc_oui_ipv4));
381+
skb_reset_network_header(skb);
382+
skb->pkt_type = PACKET_HOST;
383+
323384
/* let us waste some time for checking the encapsulation.
324385
Note, that only 7 char is checked so frames with a valid FCS
325386
are also accepted (but FCS is not checked of course) */
326-
if (memcmp(skb->data, llc_oui_pid_pad, 7)) {
387+
} else if ((skb->len >= sizeof(llc_oui_pid_pad)) &&
388+
(memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) {
389+
skb_pull(skb, sizeof(llc_oui_pid_pad));
390+
skb->protocol = eth_type_trans(skb, net_dev);
391+
} else {
327392
brdev->stats.rx_errors++;
328393
dev_kfree_skb(skb);
329394
return;
330395
}
331396

332-
/* Strip FCS if present */
333-
if (skb->len > 7 && skb->data[7] == 0x01)
334-
__skb_trim(skb, skb->len - 4);
335397
} else {
336-
plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */
337398
/* first 2 chars should be 0 */
338399
if (*((u16 *) (skb->data)) != 0) {
339400
brdev->stats.rx_errors++;
340401
dev_kfree_skb(skb);
341402
return;
342403
}
343-
}
344-
if (skb->len < plen) {
345-
brdev->stats.rx_errors++;
346-
dev_kfree_skb(skb); /* dev_ not needed? */
347-
return;
404+
skb_pull(skb, BR2684_PAD_LEN + ETH_HLEN); /* pad, dstmac, srcmac, ethtype */
405+
skb->protocol = eth_type_trans(skb, net_dev);
348406
}
349407

350-
skb_pull(skb, plen - ETH_HLEN);
351-
skb->protocol = eth_type_trans(skb, net_dev);
352408
#ifdef CONFIG_ATM_BR2684_IPFILTER
353409
if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) {
354410
brdev->stats.rx_dropped++;
@@ -482,25 +538,52 @@ static void br2684_setup(struct net_device *netdev)
482538
INIT_LIST_HEAD(&brdev->brvccs);
483539
}
484540

541+
static void br2684_setup_routed(struct net_device *netdev)
542+
{
543+
struct br2684_dev *brdev = BRPRIV(netdev);
544+
brdev->net_dev = netdev;
545+
546+
netdev->hard_header_len = 0;
547+
my_eth_mac_addr = netdev->set_mac_address;
548+
netdev->set_mac_address = br2684_mac_addr;
549+
netdev->hard_start_xmit = br2684_start_xmit;
550+
netdev->get_stats = br2684_get_stats;
551+
netdev->addr_len = 0;
552+
netdev->mtu = 1500;
553+
netdev->type = ARPHRD_PPP;
554+
netdev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
555+
netdev->tx_queue_len = 100;
556+
INIT_LIST_HEAD(&brdev->brvccs);
557+
}
558+
485559
static int br2684_create(void __user *arg)
486560
{
487561
int err;
488562
struct net_device *netdev;
489563
struct br2684_dev *brdev;
490564
struct atm_newif_br2684 ni;
565+
enum br2684_payload payload;
491566

492567
pr_debug("br2684_create\n");
493568

494569
if (copy_from_user(&ni, arg, sizeof ni)) {
495570
return -EFAULT;
496571
}
572+
573+
if (ni.media & BR2684_FLAG_ROUTED)
574+
payload = p_routed;
575+
else
576+
payload = p_bridged;
577+
ni.media &= 0xffff; /* strip flags */
578+
497579
if (ni.media != BR2684_MEDIA_ETHERNET || ni.mtu != 1500) {
498580
return -EINVAL;
499581
}
500582

501583
netdev = alloc_netdev(sizeof(struct br2684_dev),
502584
ni.ifname[0] ? ni.ifname : "nas%d",
503-
br2684_setup);
585+
(payload == p_routed) ?
586+
br2684_setup_routed : br2684_setup);
504587
if (!netdev)
505588
return -ENOMEM;
506589

@@ -516,6 +599,7 @@ static int br2684_create(void __user *arg)
516599
}
517600

518601
write_lock_irq(&devs_lock);
602+
brdev->payload = payload;
519603
brdev->number = list_empty(&br2684_devs) ? 1 :
520604
BRPRIV(list_entry_brdev(br2684_devs.prev))->number + 1;
521605
list_add_tail(&brdev->br2684_devs, &br2684_devs);
@@ -601,14 +685,14 @@ static int br2684_seq_show(struct seq_file *seq, void *v)
601685
brdev->mac_was_set ? "set" : "auto");
602686

603687
list_for_each_entry(brvcc, &brdev->brvccs, brvccs) {
604-
seq_printf(seq, " vcc %d.%d.%d: encaps=%s"
605-
", failed copies %u/%u"
606-
"\n", brvcc->atmvcc->dev->number,
607-
brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
608-
(brvcc->encaps == e_llc) ? "LLC" : "VC"
609-
, brvcc->copies_failed
610-
, brvcc->copies_needed
611-
);
688+
seq_printf(seq, " vcc %d.%d.%d: encaps=%s payload=%s"
689+
", failed copies %u/%u"
690+
"\n", brvcc->atmvcc->dev->number,
691+
brvcc->atmvcc->vpi, brvcc->atmvcc->vci,
692+
(brvcc->encaps == e_llc) ? "LLC" : "VC",
693+
(brdev->payload == p_bridged) ? "bridged" : "routed",
694+
brvcc->copies_failed,
695+
brvcc->copies_needed);
612696
#ifdef CONFIG_ATM_BR2684_IPFILTER
613697
#define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte]
614698
#define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3)

0 commit comments

Comments
 (0)