diff options
Diffstat (limited to 'target/linux/generic-2.4/patches/226-atm_br2684.patch')
-rw-r--r-- | target/linux/generic-2.4/patches/226-atm_br2684.patch | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/target/linux/generic-2.4/patches/226-atm_br2684.patch b/target/linux/generic-2.4/patches/226-atm_br2684.patch new file mode 100644 index 0000000..56f0015 --- /dev/null +++ b/target/linux/generic-2.4/patches/226-atm_br2684.patch @@ -0,0 +1,578 @@ +diff -urN linux-2.4.32/net/atm/br2684.c linux-2.4.32.new/net/atm/br2684.c +--- linux-2.4.32/net/atm/br2684.c 2004-08-08 01:26:06.000000000 +0200 ++++ linux-2.4.32.new/net/atm/br2684.c 2006-02-06 18:59:40.000000000 +0100 +@@ -55,36 +55,55 @@ + #define skb_debug(skb) do {} while (0) + #endif + ++#define BR2684_LLC_LEN 3 ++#define BR2684_SNAP_LEN 3 ++#define BR2684_ETHERTYPE_LEN 2 ++#define BR2684_PID_LEN 2 ++#define BR2684_PAD_LEN 2 ++ ++static unsigned char llc_common[] = { 0xaa, 0xaa, 0x03 }; ++static unsigned char snap_bridged[] = { 0x00, 0x80, 0xc2 }; ++static unsigned char snap_routed[] = { 0x00, 0x00, 0x00 }; ++static unsigned char pid_ipv4[] = { 0x00, 0x07 }; ++static unsigned char ethertype_ipv4[] = { 0x08, 0x00 }; ++static unsigned char ethertype_ipv6[] = { 0x86, 0xdd }; ++static unsigned char pad_bridged[] = { 0x00, 0x00 }; ++ + static unsigned char llc_oui_pid_pad[] = + { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 }; ++static unsigned char llc_oui_ipv6[] = ++ { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd }; ++static unsigned char llc_oui_ipv4[] = ++ { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00 }; + #define PADLEN (2) + + enum br2684_encaps { +- e_vc = BR2684_ENCAPS_VC, ++ e_vc = BR2684_ENCAPS_VC, + e_llc = BR2684_ENCAPS_LLC, + }; + + struct br2684_vcc { +- struct atm_vcc *atmvcc; ++ struct atm_vcc *atmvcc; + struct br2684_dev *brdev; + /* keep old push,pop functions for chaining */ +- void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); ++ void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb); + /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */ + enum br2684_encaps encaps; ++ enum br2684_payload payload; + struct list_head brvccs; + #ifdef CONFIG_ATM_BR2684_IPFILTER + struct br2684_filter filter; +-#endif /* CONFIG_ATM_BR2684_IPFILTER */ ++#endif /* CONFIG_ATM_BR2684_IPFILTER */ + #ifndef FASTER_VERSION + unsigned copies_needed, copies_failed; +-#endif /* FASTER_VERSION */ ++#endif /* FASTER_VERSION */ + }; + + struct br2684_dev { + struct net_device net_dev; + struct list_head br2684_devs; + int number; +- struct list_head brvccs; /* one device <=> one vcc (before xmas) */ ++ struct list_head brvccs; /* one device <=> one vcc (before xmas) */ + struct net_device_stats stats; + int mac_was_set; + }; +@@ -173,24 +192,84 @@ + } + skb = skb2; + } +- skb_push(skb, minheadroom); +- if (brvcc->encaps == e_llc) +- memcpy(skb->data, llc_oui_pid_pad, 10); +- else +- memset(skb->data, 0, 2); +-#endif /* FASTER_VERSION */ ++ ++ /* This skb_push is a problem: routed packets need less headroom than ++ * bridged packets. ++ */ ++ ++/* skb_push(skb, minheadroom); */ ++ if (brvcc->encaps == e_llc) { ++ int offset = 0; ++ int actual_headroom; ++ ++ actual_headroom = ++ BR2684_LLC_LEN + ++ BR2684_SNAP_LEN + ++ ((brvcc->payload == p_bridged) ? ++ (BR2684_PID_LEN + BR2684_PAD_LEN) : ++ BR2684_ETHERTYPE_LEN); ++ ++ skb_push(skb, actual_headroom); ++ memcpy(skb->data, llc_common, BR2684_LLC_LEN); ++ offset += BR2684_LLC_LEN; ++ ++ if (brvcc->payload == p_bridged) { ++ memcpy(skb->data + offset, snap_bridged, ++ BR2684_SNAP_LEN); ++ offset += BR2684_SNAP_LEN; ++ /* pid_ipv4 is poorly named. should probably be ++ * pid_ethernet ++ */ ++ memcpy(skb->data + offset, pid_ipv4, ++ BR2684_PID_LEN); ++ offset += BR2684_PID_LEN; ++ memcpy(skb->data + offset, pad_bridged, ++ BR2684_PAD_LEN); ++ offset += BR2684_PAD_LEN; ++ } else if (brvcc->payload == p_routed) { ++ unsigned short prot = ++ __constant_ntohs(skb->protocol); ++ memcpy(skb->data + offset, snap_routed, ++ BR2684_SNAP_LEN); ++ offset += BR2684_SNAP_LEN; ++ ++ switch (prot) { ++ case ETH_P_IP: ++ memcpy(skb->data + offset, ++ ethertype_ipv4, ++ BR2684_ETHERTYPE_LEN); ++ break; ++ case ETH_P_IPV6: ++ memcpy(skb->data + offset, ++ ethertype_ipv6, ++ BR2684_ETHERTYPE_LEN); ++ break; ++ default: ++ dev_kfree_skb(skb); ++ return 0; ++ } ++ offset += BR2684_ETHERTYPE_LEN; ++ ++ } ++ } else { ++ skb_push(skb, 2); ++ if (brvcc->payload == p_bridged) ++ memset(skb->data, 0, 2); ++ } ++#endif /* FASTER_VERSION */ + skb_debug(skb); + + ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; +- DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); ++ DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, ++ atmvcc->dev); + if (!atm_may_send(atmvcc, skb->truesize)) { + /* we free this here for now, because we cannot know in a higher +- layer whether the skb point it supplied wasn't freed yet. +- now, it always is. +- */ ++ layer whether the skb point it supplied wasn't freed yet. ++ now, it always is. ++ */ + dev_kfree_skb(skb); + return 0; +- } ++ } + atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc); + ATM_SKB(skb)->atm_options = atmvcc->atm_options; + brdev->stats.tx_packets++; +@@ -428,18 +507,39 @@ + atm_return(atmvcc, skb->truesize); + DPRINTK("skb from brdev %p\n", brdev); + if (brvcc->encaps == e_llc) { ++ /* accept packets that have "ipv[46]" in the snap header */ ++ /* 8 - 2 == sizeof(llc_oui_ipv6) - BR2684_ETHERTYPE_LEN */ ++ if (memcmp(skb->data, llc_oui_ipv6, 8 - 2) == 0) { ++ plen = sizeof(llc_oui_ipv6); ++ ++ if (memcmp(skb->data + 6, ethertype_ipv6, 2) == 0) ++ skb->protocol = ++ __constant_htons(ETH_P_IPV6); ++ else if (memcmp(skb->data + 6, ethertype_ipv4, 2) ++ == 0) ++ skb->protocol = __constant_htons(ETH_P_IP); ++ else { ++ brdev->stats.rx_errors++; ++ dev_kfree_skb(skb); ++ return; ++ } ++ skb_pull(skb, plen); ++ skb->nh.raw = skb->data; ++ skb->pkt_type = PACKET_HOST; ++ } ++ + /* let us waste some time for checking the encapsulation. + Note, that only 7 char is checked so frames with a valid FCS + are also accepted (but FCS is not checked of course) */ +- if (memcmp(skb->data, llc_oui_pid_pad, 7)) { ++ else if (memcmp(skb->data, llc_oui_pid_pad, 7) == 0) { ++ skb_pull(skb, plen - ETH_HLEN); ++ skb->protocol = ++ eth_type_trans(skb, &brdev->net_dev); ++ } else { + brdev->stats.rx_errors++; + dev_kfree_skb(skb); + return; + } +- +- /* Strip FCS if present */ +- if (skb->len > 7 && skb->data[7] == 0x01) +- __skb_trim(skb, skb->len - 4); + } else { + plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */ + /* first 2 chars should be 0 */ +@@ -448,13 +548,14 @@ + dev_kfree_skb(skb); + return; + } ++ skb_pull(skb, plen - ETH_HLEN); ++ skb->protocol = eth_type_trans(skb, &brdev->net_dev); + } + if (skb->len < plen) { + brdev->stats.rx_errors++; + dev_kfree_skb(skb); /* dev_ not needed? */ + return; + } +- + #ifdef FASTER_VERSION + /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier, + than should be. What else should I set? */ +@@ -465,30 +566,29 @@ + skb->protocol = ((u16 *) skb->data)[-1]; + #else /* some protocols might require this: */ + skb->protocol = br_type_trans(skb, &brdev->net_dev); +-#endif /* CONFIG_BR2684_FAST_TRANS */ ++#endif /* CONFIG_BR2684_FAST_TRANS */ + #else +- skb_pull(skb, plen - ETH_HLEN); +- skb->protocol = eth_type_trans(skb, &brdev->net_dev); +-#endif /* FASTER_VERSION */ ++ /* skb_pull(skb, plen - ETH_HLEN); */ ++ /* skb->protocol = eth_type_trans(skb, &brdev->net_dev); */ ++#endif /* FASTER_VERSION */ + #ifdef CONFIG_ATM_BR2684_IPFILTER + if (packet_fails_filter(skb->protocol, brvcc, skb)) { + brdev->stats.rx_dropped++; + dev_kfree_skb(skb); + return; + } +-#endif /* CONFIG_ATM_BR2684_IPFILTER */ ++#endif /* CONFIG_ATM_BR2684_IPFILTER */ + skb->dev = &brdev->net_dev; +- ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ ++ /* ATM_SKB(skb)->vcc = atmvcc; *//* needed ? */ + DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol)); + skb_debug(skb); +- if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ ++ if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ + brdev->stats.rx_dropped++; + dev_kfree_skb(skb); + return; + } + brdev->stats.rx_packets++; + brdev->stats.rx_bytes += skb->len; +- memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); + netif_rx(skb); + } + +@@ -525,10 +625,10 @@ + err = -EEXIST; + goto error; + } +- if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO || +- be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps != +- BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) || +- be.min_size != 0) { ++ if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO ++ || be.fcs_auto || be.has_vpiid || be.send_padding ++ || (be.encaps != BR2684_ENCAPS_VC ++ && be.encaps != BR2684_ENCAPS_LLC) || be.min_size != 0) { + err = -EINVAL; + goto error; + } +@@ -554,18 +654,21 @@ + brvcc->atmvcc = atmvcc; + atmvcc->user_back = brvcc; + brvcc->encaps = (enum br2684_encaps) be.encaps; ++ brvcc->payload = (enum br2684_payload) be.payload; + brvcc->old_push = atmvcc->push; + barrier(); + atmvcc->push = br2684_push; + skb_queue_head_init(©); + skb_migrate(&atmvcc->sk->receive_queue, ©); + while ((skb = skb_dequeue(©))) { ++#ifdef notdef + BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; + BRPRIV(skb->dev)->stats.rx_packets--; ++#endif + br2684_push(atmvcc, skb); + } + return 0; +- error: ++ error: + write_unlock_irq(&devs_lock); + MOD_DEC_USE_COUNT; + return err; +@@ -608,12 +711,25 @@ + + if (ni.ifname[0] != '\0') { + memcpy(brdev->net_dev.name, ni.ifname, +- sizeof(brdev->net_dev.name)); +- brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0'; ++ sizeof(brdev->net_dev.name)); ++ brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = ++ '\0'; + } else + sprintf(brdev->net_dev.name, "nas%d", brdev->number); + DPRINTK("registered netdev %s\n", brdev->net_dev.name); +- ether_setup(&brdev->net_dev); ++ if (ni.payload == p_routed) { ++ brdev->net_dev.hard_header_len = 0; ++ brdev->net_dev.addr_len = 0; ++ brdev->net_dev.mtu = 1500; ++ ++ /* Type PPP seems most suitable */ ++ brdev->net_dev.type = ARPHRD_PPP; ++ brdev->net_dev.flags = ++ IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; ++ brdev->net_dev.tx_queue_len = 100; ++ } else { ++ ether_setup(&brdev->net_dev); ++ } + brdev->mac_was_set = 0; + #ifdef FASTER_VERSION + my_eth_header = brdev->net_dev.hard_header; +@@ -677,12 +793,11 @@ + err = br2684_setfilt(atmvcc, arg); + MOD_DEC_USE_COUNT; + return err; +-#endif /* CONFIG_ATM_BR2684_IPFILTER */ ++#endif /* CONFIG_ATM_BR2684_IPFILTER */ + } + return -ENOIOCTLCMD; + } + +-#ifdef CONFIG_PROC_FS + /* Never put more than 256 bytes in at once */ + static int br2684_proc_engine(loff_t pos, char *buf) + { +@@ -692,52 +807,62 @@ + list_for_each(lhd, &br2684_devs) { + brdev = list_entry_brdev(lhd); + if (pos-- == 0) +- return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" +- "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name, +- brdev->number, +- brdev->net_dev.dev_addr[0], +- brdev->net_dev.dev_addr[1], +- brdev->net_dev.dev_addr[2], +- brdev->net_dev.dev_addr[3], +- brdev->net_dev.dev_addr[4], +- brdev->net_dev.dev_addr[5], +- brdev->mac_was_set ? "set" : "auto"); ++ return sprintf(buf, ++ "dev %.16s: num=%d, mac=%02X:%02X:" ++ "%02X:%02X:%02X:%02X (%s)\n", ++ brdev->net_dev.name, brdev->number, ++ brdev->net_dev.dev_addr[0], ++ brdev->net_dev.dev_addr[1], ++ brdev->net_dev.dev_addr[2], ++ brdev->net_dev.dev_addr[3], ++ brdev->net_dev.dev_addr[4], ++ brdev->net_dev.dev_addr[5], ++ brdev-> ++ mac_was_set ? "set" : "auto"); + list_for_each(lhc, &brdev->brvccs) { + brvcc = list_entry_brvcc(lhc); + if (pos-- == 0) +- return sprintf(buf, " vcc %d.%d.%d: encaps=%s" ++ return sprintf(buf, ++ " vcc %d.%d.%d: encaps=%s" ++ ", payload=%s" + #ifndef FASTER_VERSION +- ", failed copies %u/%u" +-#endif /* FASTER_VERSION */ +- "\n", brvcc->atmvcc->dev->number, +- brvcc->atmvcc->vpi, brvcc->atmvcc->vci, +- (brvcc->encaps == e_llc) ? "LLC" : "VC" ++ ", failed copies %u/%u" ++#endif /* FASTER_VERSION */ ++ "\n", ++ brvcc->atmvcc->dev->number, ++ brvcc->atmvcc->vpi, ++ brvcc->atmvcc->vci, ++ (brvcc->encaps == ++ e_llc) ? "LLC" : "VC", ++ (brvcc->payload == ++ p_bridged) ? "bridged" : ++ "routed" + #ifndef FASTER_VERSION +- , brvcc->copies_failed +- , brvcc->copies_needed +-#endif /* FASTER_VERSION */ ++ , brvcc->copies_failed, ++ brvcc->copies_needed ++#endif /* FASTER_VERSION */ + ); + #ifdef CONFIG_ATM_BR2684_IPFILTER + #define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte] + #define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3) + if (brvcc->filter.netmask != 0 && pos-- == 0) +- return sprintf(buf, " filter=%d.%d.%d.%d/" +- "%d.%d.%d.%d\n", bs(prefix), bs(netmask)); ++ return sprintf(buf, ++ " filter=%d.%d.%d.%d/" ++ "%d.%d.%d.%d\n", bs(prefix), ++ bs(netmask)); + #undef bs + #undef b1 +-#endif /* CONFIG_ATM_BR2684_IPFILTER */ ++#endif /* CONFIG_ATM_BR2684_IPFILTER */ + } + } + return 0; + } + + static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, +- loff_t *pos) ++ loff_t * pos) + { + unsigned long page; + int len = 0, x, left; +- loff_t n = *pos; +- + page = get_free_page(GFP_KERNEL); + if (!page) + return -ENOMEM; +@@ -746,7 +871,7 @@ + left = count; + read_lock(&devs_lock); + for (;;) { +- x = br2684_proc_engine(n, &((char *) page)[len]); ++ x = br2684_proc_engine(*pos, &((char *) page)[len]); + if (x == 0) + break; + if (x > left) +@@ -761,12 +886,11 @@ + } + len += x; + left -= x; +- n++; ++ (*pos)++; + if (left < 256) + break; + } + read_unlock(&devs_lock); +- *pos = n; + if (len > 0 && copy_to_user(buf, (char *) page, len)) + len = -EFAULT; + free_page(page); +@@ -774,23 +898,20 @@ + } + + static struct file_operations br2684_proc_operations = { +- read: br2684_proc_read, ++ read:br2684_proc_read, + }; + + extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ +-#endif /* CONFIG_PROC_FS */ + + /* the following avoids some spurious warnings from the compiler */ + #define UNUSED __attribute__((unused)) + + static int __init UNUSED br2684_init(void) + { +-#ifdef CONFIG_PROC_FS + struct proc_dir_entry *p; + if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) + return -ENOMEM; + p->proc_fops = &br2684_proc_operations; +-#endif /* CONFIG_PROC_FS */ + br2684_ioctl_set(br2684_ioctl); + return 0; + } +@@ -799,9 +920,7 @@ + { + struct br2684_dev *brdev; + br2684_ioctl_set(NULL); +-#ifdef CONFIG_PROC_FS + remove_proc_entry("br2684", atm_proc_root); +-#endif /* CONFIG_PROC_FS */ + while (!list_empty(&br2684_devs)) { + brdev = list_entry_brdev(br2684_devs.next); + unregister_netdev(&brdev->net_dev); +diff -urN linux-2.4.32/net/atm/common.c linux-2.4.32.new/net/atm/common.c +--- linux-2.4.32/net/atm/common.c 2004-02-18 14:36:32.000000000 +0100 ++++ linux-2.4.32.new/net/atm/common.c 2006-02-06 17:26:52.000000000 +0100 +@@ -158,6 +158,7 @@ + } + #ifdef CONFIG_ATM_BR2684_MODULE + EXPORT_SYMBOL(br2684_ioctl_set); ++EXPORT_SYMBOL(br2684_ioctl_hook); + #endif + #endif + +--- linux-2.4.32/include/linux/atmbr2684.h 2002-08-03 02:39:45.000000000 +0200 ++++ linux-2.4.32.new/include/linux/atmbr2684.h 2006-02-06 19:01:24.000000000 +0100 +@@ -3,6 +3,7 @@ + + #include <linux/atm.h> + #include <linux/if.h> /* For IFNAMSIZ */ ++#include <linux/if_ether.h> /* ETH_P_* */ + + /* + * Type of media we're bridging (ethernet, token ring, etc) Currently only +@@ -36,15 +37,24 @@ + #define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */ + + /* ++ * Is this VC bridged or routed? ++ */ ++ ++#define BR2684_PAYLOAD_ROUTED (0) ++#define BR2684_PAYLOAD_BRIDGED (1) ++ ++ ++/* + * This is for the ATM_NEWBACKENDIF call - these are like socket families: + * the first element of the structure is the backend number and the rest + * is per-backend specific + */ + struct atm_newif_br2684 { +- atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ +- int media; /* BR2684_MEDIA_* */ +- char ifname[IFNAMSIZ]; +- int mtu; ++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ ++ int media; /* BR2684_MEDIA_* */ ++ char ifname[IFNAMSIZ]; ++ int mtu; ++ int payload; /* bridged or routed */ + }; + + /* +@@ -68,16 +78,17 @@ + * is per-backend specific + */ + struct atm_backend_br2684 { +- atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ ++ atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ + struct br2684_if_spec ifspec; +- int fcs_in; /* BR2684_FCSIN_* */ +- int fcs_out; /* BR2684_FCSOUT_* */ +- int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */ +- int encaps; /* BR2684_ENCAPS_* */ +- int has_vpiid; /* 1: use vpn_id - Unsupported */ +- __u8 vpn_id[7]; +- int send_padding; /* unsupported */ +- int min_size; /* we will pad smaller packets than this */ ++ int fcs_in; /* BR2684_FCSIN_* */ ++ int fcs_out; /* BR2684_FCSOUT_* */ ++ int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */ ++ int encaps; /* BR2684_ENCAPS_* */ ++ int payload; /* BR2684_PAYLOAD_* */ ++ int has_vpiid; /* 1: use vpn_id - Unsupported */ ++ __u8 vpn_id[7]; ++ int send_padding; /* unsupported */ ++ int min_size; /* we will pad smaller packets than this */ + }; + + /* +@@ -95,7 +106,12 @@ + struct br2684_filter filter; + }; + ++enum br2684_payload { ++ p_routed = BR2684_PAYLOAD_ROUTED, ++ p_bridged = BR2684_PAYLOAD_BRIDGED, ++}; ++ + #define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \ + struct br2684_filter_set) + +-#endif /* _LINUX_ATMBR2684_H */ ++#endif /* _LINUX_ATMBR2684_H */ |