| 1 | --- a/net/atm/br2684.c |
| 2 | +++ b/net/atm/br2684.c |
| 3 | @@ -55,36 +55,55 @@ static void skb_debug(const struct sk_bu |
| 4 | #define skb_debug(skb) do {} while (0) |
| 5 | #endif |
| 6 | |
| 7 | +#define BR2684_LLC_LEN 3 |
| 8 | +#define BR2684_SNAP_LEN 3 |
| 9 | +#define BR2684_ETHERTYPE_LEN 2 |
| 10 | +#define BR2684_PID_LEN 2 |
| 11 | +#define BR2684_PAD_LEN 2 |
| 12 | + |
| 13 | +static unsigned char llc_common[] = { 0xaa, 0xaa, 0x03 }; |
| 14 | +static unsigned char snap_bridged[] = { 0x00, 0x80, 0xc2 }; |
| 15 | +static unsigned char snap_routed[] = { 0x00, 0x00, 0x00 }; |
| 16 | +static unsigned char pid_ipv4[] = { 0x00, 0x07 }; |
| 17 | +static unsigned char ethertype_ipv4[] = { 0x08, 0x00 }; |
| 18 | +static unsigned char ethertype_ipv6[] = { 0x86, 0xdd }; |
| 19 | +static unsigned char pad_bridged[] = { 0x00, 0x00 }; |
| 20 | + |
| 21 | static unsigned char llc_oui_pid_pad[] = |
| 22 | { 0xAA, 0xAA, 0x03, 0x00, 0x80, 0xC2, 0x00, 0x07, 0x00, 0x00 }; |
| 23 | +static unsigned char llc_oui_ipv6[] = |
| 24 | + { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd }; |
| 25 | +static unsigned char llc_oui_ipv4[] = |
| 26 | + { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00 }; |
| 27 | #define PADLEN (2) |
| 28 | |
| 29 | enum br2684_encaps { |
| 30 | - e_vc = BR2684_ENCAPS_VC, |
| 31 | + e_vc = BR2684_ENCAPS_VC, |
| 32 | e_llc = BR2684_ENCAPS_LLC, |
| 33 | }; |
| 34 | |
| 35 | struct br2684_vcc { |
| 36 | - struct atm_vcc *atmvcc; |
| 37 | + struct atm_vcc *atmvcc; |
| 38 | struct br2684_dev *brdev; |
| 39 | /* keep old push,pop functions for chaining */ |
| 40 | - void (*old_push)(struct atm_vcc *vcc,struct sk_buff *skb); |
| 41 | + void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb); |
| 42 | /* void (*old_pop)(struct atm_vcc *vcc,struct sk_buff *skb); */ |
| 43 | enum br2684_encaps encaps; |
| 44 | + enum br2684_payload payload; |
| 45 | struct list_head brvccs; |
| 46 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
| 47 | struct br2684_filter filter; |
| 48 | -#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 49 | +#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 50 | #ifndef FASTER_VERSION |
| 51 | unsigned copies_needed, copies_failed; |
| 52 | -#endif /* FASTER_VERSION */ |
| 53 | +#endif /* FASTER_VERSION */ |
| 54 | }; |
| 55 | |
| 56 | struct br2684_dev { |
| 57 | struct net_device net_dev; |
| 58 | struct list_head br2684_devs; |
| 59 | int number; |
| 60 | - struct list_head brvccs; /* one device <=> one vcc (before xmas) */ |
| 61 | + struct list_head brvccs; /* one device <=> one vcc (before xmas) */ |
| 62 | struct net_device_stats stats; |
| 63 | int mac_was_set; |
| 64 | }; |
| 65 | @@ -173,24 +192,84 @@ static int br2684_xmit_vcc(struct sk_buf |
| 66 | } |
| 67 | skb = skb2; |
| 68 | } |
| 69 | - skb_push(skb, minheadroom); |
| 70 | - if (brvcc->encaps == e_llc) |
| 71 | - memcpy(skb->data, llc_oui_pid_pad, 10); |
| 72 | - else |
| 73 | - memset(skb->data, 0, 2); |
| 74 | -#endif /* FASTER_VERSION */ |
| 75 | + |
| 76 | + /* This skb_push is a problem: routed packets need less headroom than |
| 77 | + * bridged packets. |
| 78 | + */ |
| 79 | + |
| 80 | +/* skb_push(skb, minheadroom); */ |
| 81 | + if (brvcc->encaps == e_llc) { |
| 82 | + int offset = 0; |
| 83 | + int actual_headroom; |
| 84 | + |
| 85 | + actual_headroom = |
| 86 | + BR2684_LLC_LEN + |
| 87 | + BR2684_SNAP_LEN + |
| 88 | + ((brvcc->payload == p_bridged) ? |
| 89 | + (BR2684_PID_LEN + BR2684_PAD_LEN) : |
| 90 | + BR2684_ETHERTYPE_LEN); |
| 91 | + |
| 92 | + skb_push(skb, actual_headroom); |
| 93 | + memcpy(skb->data, llc_common, BR2684_LLC_LEN); |
| 94 | + offset += BR2684_LLC_LEN; |
| 95 | + |
| 96 | + if (brvcc->payload == p_bridged) { |
| 97 | + memcpy(skb->data + offset, snap_bridged, |
| 98 | + BR2684_SNAP_LEN); |
| 99 | + offset += BR2684_SNAP_LEN; |
| 100 | + /* pid_ipv4 is poorly named. should probably be |
| 101 | + * pid_ethernet |
| 102 | + */ |
| 103 | + memcpy(skb->data + offset, pid_ipv4, |
| 104 | + BR2684_PID_LEN); |
| 105 | + offset += BR2684_PID_LEN; |
| 106 | + memcpy(skb->data + offset, pad_bridged, |
| 107 | + BR2684_PAD_LEN); |
| 108 | + offset += BR2684_PAD_LEN; |
| 109 | + } else if (brvcc->payload == p_routed) { |
| 110 | + unsigned short prot = |
| 111 | + __constant_ntohs(skb->protocol); |
| 112 | + memcpy(skb->data + offset, snap_routed, |
| 113 | + BR2684_SNAP_LEN); |
| 114 | + offset += BR2684_SNAP_LEN; |
| 115 | + |
| 116 | + switch (prot) { |
| 117 | + case ETH_P_IP: |
| 118 | + memcpy(skb->data + offset, |
| 119 | + ethertype_ipv4, |
| 120 | + BR2684_ETHERTYPE_LEN); |
| 121 | + break; |
| 122 | + case ETH_P_IPV6: |
| 123 | + memcpy(skb->data + offset, |
| 124 | + ethertype_ipv6, |
| 125 | + BR2684_ETHERTYPE_LEN); |
| 126 | + break; |
| 127 | + default: |
| 128 | + dev_kfree_skb(skb); |
| 129 | + return 0; |
| 130 | + } |
| 131 | + offset += BR2684_ETHERTYPE_LEN; |
| 132 | + |
| 133 | + } |
| 134 | + } else { |
| 135 | + skb_push(skb, 2); |
| 136 | + if (brvcc->payload == p_bridged) |
| 137 | + memset(skb->data, 0, 2); |
| 138 | + } |
| 139 | +#endif /* FASTER_VERSION */ |
| 140 | skb_debug(skb); |
| 141 | |
| 142 | ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; |
| 143 | - DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); |
| 144 | + DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, |
| 145 | + atmvcc->dev); |
| 146 | if (!atm_may_send(atmvcc, skb->truesize)) { |
| 147 | /* we free this here for now, because we cannot know in a higher |
| 148 | - layer whether the skb point it supplied wasn't freed yet. |
| 149 | - now, it always is. |
| 150 | - */ |
| 151 | + layer whether the skb point it supplied wasn't freed yet. |
| 152 | + now, it always is. |
| 153 | + */ |
| 154 | dev_kfree_skb(skb); |
| 155 | return 0; |
| 156 | - } |
| 157 | + } |
| 158 | atomic_add(skb->truesize, &atmvcc->sk->wmem_alloc); |
| 159 | ATM_SKB(skb)->atm_options = atmvcc->atm_options; |
| 160 | brdev->stats.tx_packets++; |
| 161 | @@ -428,18 +507,39 @@ static void br2684_push(struct atm_vcc * |
| 162 | atm_return(atmvcc, skb->truesize); |
| 163 | DPRINTK("skb from brdev %p\n", brdev); |
| 164 | if (brvcc->encaps == e_llc) { |
| 165 | + /* accept packets that have "ipv[46]" in the snap header */ |
| 166 | + /* 8 - 2 == sizeof(llc_oui_ipv6) - BR2684_ETHERTYPE_LEN */ |
| 167 | + if (memcmp(skb->data, llc_oui_ipv6, 8 - 2) == 0) { |
| 168 | + plen = sizeof(llc_oui_ipv6); |
| 169 | + |
| 170 | + if (memcmp(skb->data + 6, ethertype_ipv6, 2) == 0) |
| 171 | + skb->protocol = |
| 172 | + __constant_htons(ETH_P_IPV6); |
| 173 | + else if (memcmp(skb->data + 6, ethertype_ipv4, 2) |
| 174 | + == 0) |
| 175 | + skb->protocol = __constant_htons(ETH_P_IP); |
| 176 | + else { |
| 177 | + brdev->stats.rx_errors++; |
| 178 | + dev_kfree_skb(skb); |
| 179 | + return; |
| 180 | + } |
| 181 | + skb_pull(skb, plen); |
| 182 | + skb->nh.raw = skb->data; |
| 183 | + skb->pkt_type = PACKET_HOST; |
| 184 | + } |
| 185 | + |
| 186 | /* let us waste some time for checking the encapsulation. |
| 187 | Note, that only 7 char is checked so frames with a valid FCS |
| 188 | are also accepted (but FCS is not checked of course) */ |
| 189 | - if (memcmp(skb->data, llc_oui_pid_pad, 7)) { |
| 190 | + else if (memcmp(skb->data, llc_oui_pid_pad, 7) == 0) { |
| 191 | + skb_pull(skb, plen - ETH_HLEN); |
| 192 | + skb->protocol = |
| 193 | + eth_type_trans(skb, &brdev->net_dev); |
| 194 | + } else { |
| 195 | brdev->stats.rx_errors++; |
| 196 | dev_kfree_skb(skb); |
| 197 | return; |
| 198 | } |
| 199 | - |
| 200 | - /* Strip FCS if present */ |
| 201 | - if (skb->len > 7 && skb->data[7] == 0x01) |
| 202 | - __skb_trim(skb, skb->len - 4); |
| 203 | } else { |
| 204 | plen = PADLEN + ETH_HLEN; /* pad, dstmac,srcmac, ethtype */ |
| 205 | /* first 2 chars should be 0 */ |
| 206 | @@ -448,13 +548,14 @@ static void br2684_push(struct atm_vcc * |
| 207 | dev_kfree_skb(skb); |
| 208 | return; |
| 209 | } |
| 210 | + skb_pull(skb, plen - ETH_HLEN); |
| 211 | + skb->protocol = eth_type_trans(skb, &brdev->net_dev); |
| 212 | } |
| 213 | if (skb->len < plen) { |
| 214 | brdev->stats.rx_errors++; |
| 215 | dev_kfree_skb(skb); /* dev_ not needed? */ |
| 216 | return; |
| 217 | } |
| 218 | - |
| 219 | #ifdef FASTER_VERSION |
| 220 | /* FIXME: tcpdump shows that pointer to mac header is 2 bytes earlier, |
| 221 | than should be. What else should I set? */ |
| 222 | @@ -465,30 +566,29 @@ static void br2684_push(struct atm_vcc * |
| 223 | skb->protocol = ((u16 *) skb->data)[-1]; |
| 224 | #else /* some protocols might require this: */ |
| 225 | skb->protocol = br_type_trans(skb, &brdev->net_dev); |
| 226 | -#endif /* CONFIG_BR2684_FAST_TRANS */ |
| 227 | +#endif /* CONFIG_BR2684_FAST_TRANS */ |
| 228 | #else |
| 229 | - skb_pull(skb, plen - ETH_HLEN); |
| 230 | - skb->protocol = eth_type_trans(skb, &brdev->net_dev); |
| 231 | -#endif /* FASTER_VERSION */ |
| 232 | + /* skb_pull(skb, plen - ETH_HLEN); */ |
| 233 | + /* skb->protocol = eth_type_trans(skb, &brdev->net_dev); */ |
| 234 | +#endif /* FASTER_VERSION */ |
| 235 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
| 236 | if (packet_fails_filter(skb->protocol, brvcc, skb)) { |
| 237 | brdev->stats.rx_dropped++; |
| 238 | dev_kfree_skb(skb); |
| 239 | return; |
| 240 | } |
| 241 | -#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 242 | +#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 243 | skb->dev = &brdev->net_dev; |
| 244 | - ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ |
| 245 | + /* ATM_SKB(skb)->vcc = atmvcc; *//* needed ? */ |
| 246 | DPRINTK("received packet's protocol: %x\n", ntohs(skb->protocol)); |
| 247 | skb_debug(skb); |
| 248 | - if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ |
| 249 | + if (!(brdev->net_dev.flags & IFF_UP)) { /* sigh, interface is down */ |
| 250 | brdev->stats.rx_dropped++; |
| 251 | dev_kfree_skb(skb); |
| 252 | return; |
| 253 | } |
| 254 | brdev->stats.rx_packets++; |
| 255 | brdev->stats.rx_bytes += skb->len; |
| 256 | - memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
| 257 | netif_rx(skb); |
| 258 | } |
| 259 | |
| 260 | @@ -529,10 +629,10 @@ Note: we do not have explicit unassign, |
| 261 | err = -EEXIST; |
| 262 | goto error; |
| 263 | } |
| 264 | - if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO || |
| 265 | - be.fcs_auto || be.has_vpiid || be.send_padding || (be.encaps != |
| 266 | - BR2684_ENCAPS_VC && be.encaps != BR2684_ENCAPS_LLC) || |
| 267 | - be.min_size != 0) { |
| 268 | + if (be.fcs_in != BR2684_FCSIN_NO || be.fcs_out != BR2684_FCSOUT_NO |
| 269 | + || be.fcs_auto || be.has_vpiid || be.send_padding |
| 270 | + || (be.encaps != BR2684_ENCAPS_VC |
| 271 | + && be.encaps != BR2684_ENCAPS_LLC) || be.min_size != 0) { |
| 272 | err = -EINVAL; |
| 273 | goto error; |
| 274 | } |
| 275 | @@ -553,18 +653,21 @@ Note: we do not have explicit unassign, |
| 276 | brvcc->atmvcc = atmvcc; |
| 277 | atmvcc->user_back = brvcc; |
| 278 | brvcc->encaps = (enum br2684_encaps) be.encaps; |
| 279 | + brvcc->payload = (enum br2684_payload) be.payload; |
| 280 | brvcc->old_push = atmvcc->push; |
| 281 | barrier(); |
| 282 | atmvcc->push = br2684_push; |
| 283 | skb_queue_head_init(©); |
| 284 | skb_migrate(&atmvcc->sk->receive_queue, ©); |
| 285 | while ((skb = skb_dequeue(©))) { |
| 286 | +#ifdef notdef |
| 287 | BRPRIV(skb->dev)->stats.rx_bytes -= skb->len; |
| 288 | BRPRIV(skb->dev)->stats.rx_packets--; |
| 289 | +#endif |
| 290 | br2684_push(atmvcc, skb); |
| 291 | } |
| 292 | return 0; |
| 293 | - error: |
| 294 | + error: |
| 295 | write_unlock_irq(&devs_lock); |
| 296 | kfree(brvcc); |
| 297 | MOD_DEC_USE_COUNT; |
| 298 | @@ -608,12 +711,25 @@ static int br2684_create(unsigned long a |
| 299 | |
| 300 | if (ni.ifname[0] != '\0') { |
| 301 | memcpy(brdev->net_dev.name, ni.ifname, |
| 302 | - sizeof(brdev->net_dev.name)); |
| 303 | - brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = '\0'; |
| 304 | + sizeof(brdev->net_dev.name)); |
| 305 | + brdev->net_dev.name[sizeof(brdev->net_dev.name) - 1] = |
| 306 | + '\0'; |
| 307 | } else |
| 308 | sprintf(brdev->net_dev.name, "nas%d", brdev->number); |
| 309 | DPRINTK("registered netdev %s\n", brdev->net_dev.name); |
| 310 | - ether_setup(&brdev->net_dev); |
| 311 | + if (ni.payload == p_routed) { |
| 312 | + brdev->net_dev.hard_header_len = 0; |
| 313 | + brdev->net_dev.addr_len = 0; |
| 314 | + brdev->net_dev.mtu = 1500; |
| 315 | + |
| 316 | + /* Type PPP seems most suitable */ |
| 317 | + brdev->net_dev.type = ARPHRD_PPP; |
| 318 | + brdev->net_dev.flags = |
| 319 | + IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; |
| 320 | + brdev->net_dev.tx_queue_len = 100; |
| 321 | + } else { |
| 322 | + ether_setup(&brdev->net_dev); |
| 323 | + } |
| 324 | brdev->mac_was_set = 0; |
| 325 | #ifdef FASTER_VERSION |
| 326 | my_eth_header = brdev->net_dev.hard_header; |
| 327 | @@ -677,12 +793,11 @@ static int br2684_ioctl(struct atm_vcc * |
| 328 | err = br2684_setfilt(atmvcc, arg); |
| 329 | MOD_DEC_USE_COUNT; |
| 330 | return err; |
| 331 | -#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 332 | +#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 333 | } |
| 334 | return -ENOIOCTLCMD; |
| 335 | } |
| 336 | |
| 337 | -#ifdef CONFIG_PROC_FS |
| 338 | /* Never put more than 256 bytes in at once */ |
| 339 | static int br2684_proc_engine(loff_t pos, char *buf) |
| 340 | { |
| 341 | @@ -692,52 +807,62 @@ static int br2684_proc_engine(loff_t pos |
| 342 | list_for_each(lhd, &br2684_devs) { |
| 343 | brdev = list_entry_brdev(lhd); |
| 344 | if (pos-- == 0) |
| 345 | - return sprintf(buf, "dev %.16s: num=%d, mac=%02X:%02X:" |
| 346 | - "%02X:%02X:%02X:%02X (%s)\n", brdev->net_dev.name, |
| 347 | - brdev->number, |
| 348 | - brdev->net_dev.dev_addr[0], |
| 349 | - brdev->net_dev.dev_addr[1], |
| 350 | - brdev->net_dev.dev_addr[2], |
| 351 | - brdev->net_dev.dev_addr[3], |
| 352 | - brdev->net_dev.dev_addr[4], |
| 353 | - brdev->net_dev.dev_addr[5], |
| 354 | - brdev->mac_was_set ? "set" : "auto"); |
| 355 | + return sprintf(buf, |
| 356 | + "dev %.16s: num=%d, mac=%02X:%02X:" |
| 357 | + "%02X:%02X:%02X:%02X (%s)\n", |
| 358 | + brdev->net_dev.name, brdev->number, |
| 359 | + brdev->net_dev.dev_addr[0], |
| 360 | + brdev->net_dev.dev_addr[1], |
| 361 | + brdev->net_dev.dev_addr[2], |
| 362 | + brdev->net_dev.dev_addr[3], |
| 363 | + brdev->net_dev.dev_addr[4], |
| 364 | + brdev->net_dev.dev_addr[5], |
| 365 | + brdev-> |
| 366 | + mac_was_set ? "set" : "auto"); |
| 367 | list_for_each(lhc, &brdev->brvccs) { |
| 368 | brvcc = list_entry_brvcc(lhc); |
| 369 | if (pos-- == 0) |
| 370 | - return sprintf(buf, " vcc %d.%d.%d: encaps=%s" |
| 371 | + return sprintf(buf, |
| 372 | + " vcc %d.%d.%d: encaps=%s" |
| 373 | + ", payload=%s" |
| 374 | #ifndef FASTER_VERSION |
| 375 | - ", failed copies %u/%u" |
| 376 | -#endif /* FASTER_VERSION */ |
| 377 | - "\n", brvcc->atmvcc->dev->number, |
| 378 | - brvcc->atmvcc->vpi, brvcc->atmvcc->vci, |
| 379 | - (brvcc->encaps == e_llc) ? "LLC" : "VC" |
| 380 | + ", failed copies %u/%u" |
| 381 | +#endif /* FASTER_VERSION */ |
| 382 | + "\n", |
| 383 | + brvcc->atmvcc->dev->number, |
| 384 | + brvcc->atmvcc->vpi, |
| 385 | + brvcc->atmvcc->vci, |
| 386 | + (brvcc->encaps == |
| 387 | + e_llc) ? "LLC" : "VC", |
| 388 | + (brvcc->payload == |
| 389 | + p_bridged) ? "bridged" : |
| 390 | + "routed" |
| 391 | #ifndef FASTER_VERSION |
| 392 | - , brvcc->copies_failed |
| 393 | - , brvcc->copies_needed |
| 394 | -#endif /* FASTER_VERSION */ |
| 395 | + , brvcc->copies_failed, |
| 396 | + brvcc->copies_needed |
| 397 | +#endif /* FASTER_VERSION */ |
| 398 | ); |
| 399 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
| 400 | #define b1(var, byte) ((u8 *) &brvcc->filter.var)[byte] |
| 401 | #define bs(var) b1(var, 0), b1(var, 1), b1(var, 2), b1(var, 3) |
| 402 | if (brvcc->filter.netmask != 0 && pos-- == 0) |
| 403 | - return sprintf(buf, " filter=%d.%d.%d.%d/" |
| 404 | - "%d.%d.%d.%d\n", bs(prefix), bs(netmask)); |
| 405 | + return sprintf(buf, |
| 406 | + " filter=%d.%d.%d.%d/" |
| 407 | + "%d.%d.%d.%d\n", bs(prefix), |
| 408 | + bs(netmask)); |
| 409 | #undef bs |
| 410 | #undef b1 |
| 411 | -#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 412 | +#endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 413 | } |
| 414 | } |
| 415 | return 0; |
| 416 | } |
| 417 | |
| 418 | static ssize_t br2684_proc_read(struct file *file, char *buf, size_t count, |
| 419 | - loff_t *pos) |
| 420 | + loff_t * pos) |
| 421 | { |
| 422 | unsigned long page; |
| 423 | int len = 0, x, left; |
| 424 | - loff_t n = *pos; |
| 425 | - |
| 426 | page = get_free_page(GFP_KERNEL); |
| 427 | if (!page) |
| 428 | return -ENOMEM; |
| 429 | @@ -746,7 +871,7 @@ static ssize_t br2684_proc_read(struct f |
| 430 | left = count; |
| 431 | read_lock(&devs_lock); |
| 432 | for (;;) { |
| 433 | - x = br2684_proc_engine(n, &((char *) page)[len]); |
| 434 | + x = br2684_proc_engine(*pos, &((char *) page)[len]); |
| 435 | if (x == 0) |
| 436 | break; |
| 437 | if (x > left) |
| 438 | @@ -761,12 +886,11 @@ static ssize_t br2684_proc_read(struct f |
| 439 | } |
| 440 | len += x; |
| 441 | left -= x; |
| 442 | - n++; |
| 443 | + (*pos)++; |
| 444 | if (left < 256) |
| 445 | break; |
| 446 | } |
| 447 | read_unlock(&devs_lock); |
| 448 | - *pos = n; |
| 449 | if (len > 0 && copy_to_user(buf, (char *) page, len)) |
| 450 | len = -EFAULT; |
| 451 | free_page(page); |
| 452 | @@ -774,23 +898,20 @@ static ssize_t br2684_proc_read(struct f |
| 453 | } |
| 454 | |
| 455 | static struct file_operations br2684_proc_operations = { |
| 456 | - read: br2684_proc_read, |
| 457 | + read:br2684_proc_read, |
| 458 | }; |
| 459 | |
| 460 | extern struct proc_dir_entry *atm_proc_root; /* from proc.c */ |
| 461 | -#endif /* CONFIG_PROC_FS */ |
| 462 | |
| 463 | /* the following avoids some spurious warnings from the compiler */ |
| 464 | #define UNUSED __attribute__((unused)) |
| 465 | |
| 466 | static int __init UNUSED br2684_init(void) |
| 467 | { |
| 468 | -#ifdef CONFIG_PROC_FS |
| 469 | struct proc_dir_entry *p; |
| 470 | if ((p = create_proc_entry("br2684", 0, atm_proc_root)) == NULL) |
| 471 | return -ENOMEM; |
| 472 | p->proc_fops = &br2684_proc_operations; |
| 473 | -#endif /* CONFIG_PROC_FS */ |
| 474 | br2684_ioctl_set(br2684_ioctl); |
| 475 | return 0; |
| 476 | } |
| 477 | @@ -799,9 +920,7 @@ static void __exit UNUSED br2684_exit(vo |
| 478 | { |
| 479 | struct br2684_dev *brdev; |
| 480 | br2684_ioctl_set(NULL); |
| 481 | -#ifdef CONFIG_PROC_FS |
| 482 | remove_proc_entry("br2684", atm_proc_root); |
| 483 | -#endif /* CONFIG_PROC_FS */ |
| 484 | while (!list_empty(&br2684_devs)) { |
| 485 | brdev = list_entry_brdev(br2684_devs.next); |
| 486 | unregister_netdev(&brdev->net_dev); |
| 487 | --- a/net/atm/common.c |
| 488 | +++ b/net/atm/common.c |
| 489 | @@ -158,6 +158,7 @@ void br2684_ioctl_set(int (*hook)(struct |
| 490 | } |
| 491 | #ifdef CONFIG_ATM_BR2684_MODULE |
| 492 | EXPORT_SYMBOL(br2684_ioctl_set); |
| 493 | +EXPORT_SYMBOL(br2684_ioctl_hook); |
| 494 | #endif |
| 495 | #endif |
| 496 | |
| 497 | --- a/include/linux/atmbr2684.h |
| 498 | +++ b/include/linux/atmbr2684.h |
| 499 | @@ -3,6 +3,7 @@ |
| 500 | |
| 501 | #include <linux/atm.h> |
| 502 | #include <linux/if.h> /* For IFNAMSIZ */ |
| 503 | +#include <linux/if_ether.h> /* ETH_P_* */ |
| 504 | |
| 505 | /* |
| 506 | * Type of media we're bridging (ethernet, token ring, etc) Currently only |
| 507 | @@ -36,15 +37,24 @@ |
| 508 | #define BR2684_ENCAPS_AUTODETECT (2) /* Unsuported */ |
| 509 | |
| 510 | /* |
| 511 | + * Is this VC bridged or routed? |
| 512 | + */ |
| 513 | + |
| 514 | +#define BR2684_PAYLOAD_ROUTED (0) |
| 515 | +#define BR2684_PAYLOAD_BRIDGED (1) |
| 516 | + |
| 517 | + |
| 518 | +/* |
| 519 | * This is for the ATM_NEWBACKENDIF call - these are like socket families: |
| 520 | * the first element of the structure is the backend number and the rest |
| 521 | * is per-backend specific |
| 522 | */ |
| 523 | struct atm_newif_br2684 { |
| 524 | - atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ |
| 525 | - int media; /* BR2684_MEDIA_* */ |
| 526 | - char ifname[IFNAMSIZ]; |
| 527 | - int mtu; |
| 528 | + atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ |
| 529 | + int media; /* BR2684_MEDIA_* */ |
| 530 | + char ifname[IFNAMSIZ]; |
| 531 | + int mtu; |
| 532 | + int payload; /* bridged or routed */ |
| 533 | }; |
| 534 | |
| 535 | /* |
| 536 | @@ -68,16 +78,17 @@ struct br2684_if_spec { |
| 537 | * is per-backend specific |
| 538 | */ |
| 539 | struct atm_backend_br2684 { |
| 540 | - atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ |
| 541 | + atm_backend_t backend_num; /* ATM_BACKEND_BR2684 */ |
| 542 | struct br2684_if_spec ifspec; |
| 543 | - int fcs_in; /* BR2684_FCSIN_* */ |
| 544 | - int fcs_out; /* BR2684_FCSOUT_* */ |
| 545 | - int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */ |
| 546 | - int encaps; /* BR2684_ENCAPS_* */ |
| 547 | - int has_vpiid; /* 1: use vpn_id - Unsupported */ |
| 548 | - __u8 vpn_id[7]; |
| 549 | - int send_padding; /* unsupported */ |
| 550 | - int min_size; /* we will pad smaller packets than this */ |
| 551 | + int fcs_in; /* BR2684_FCSIN_* */ |
| 552 | + int fcs_out; /* BR2684_FCSOUT_* */ |
| 553 | + int fcs_auto; /* 1: fcs_{in,out} disabled if no FCS rx'ed */ |
| 554 | + int encaps; /* BR2684_ENCAPS_* */ |
| 555 | + int payload; /* BR2684_PAYLOAD_* */ |
| 556 | + int has_vpiid; /* 1: use vpn_id - Unsupported */ |
| 557 | + __u8 vpn_id[7]; |
| 558 | + int send_padding; /* unsupported */ |
| 559 | + int min_size; /* we will pad smaller packets than this */ |
| 560 | }; |
| 561 | |
| 562 | /* |
| 563 | @@ -95,7 +106,12 @@ struct br2684_filter_set { |
| 564 | struct br2684_filter filter; |
| 565 | }; |
| 566 | |
| 567 | +enum br2684_payload { |
| 568 | + p_routed = BR2684_PAYLOAD_ROUTED, |
| 569 | + p_bridged = BR2684_PAYLOAD_BRIDGED, |
| 570 | +}; |
| 571 | + |
| 572 | #define BR2684_SETFILT _IOW( 'a', ATMIOC_BACKEND + 0, \ |
| 573 | struct br2684_filter_set) |
| 574 | |
| 575 | -#endif /* _LINUX_ATMBR2684_H */ |
| 576 | +#endif /* _LINUX_ATMBR2684_H */ |
| 577 | |