diff options
Diffstat (limited to 'net/atm/br2684.c')
-rw-r--r-- | net/atm/br2684.c | 38 |
1 files changed, 13 insertions, 25 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index d07223c834af..353fccf1cde3 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -53,6 +53,7 @@ static const unsigned char ethertype_ipv4[] = { ETHERTYPE_IPV4 }; | |||
53 | static const unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 }; | 53 | static const unsigned char ethertype_ipv6[] = { ETHERTYPE_IPV6 }; |
54 | static const unsigned char llc_oui_pid_pad[] = | 54 | static const unsigned char llc_oui_pid_pad[] = |
55 | { LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED }; | 55 | { LLC, SNAP_BRIDGED, PID_ETHERNET, PAD_BRIDGED }; |
56 | static const unsigned char pad[] = { PAD_BRIDGED }; | ||
56 | static const unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 }; | 57 | static const unsigned char llc_oui_ipv4[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV4 }; |
57 | static const unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 }; | 58 | static const unsigned char llc_oui_ipv6[] = { LLC, SNAP_ROUTED, ETHERTYPE_IPV6 }; |
58 | 59 | ||
@@ -202,7 +203,10 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev, | |||
202 | { | 203 | { |
203 | struct br2684_dev *brdev = BRPRIV(dev); | 204 | struct br2684_dev *brdev = BRPRIV(dev); |
204 | struct atm_vcc *atmvcc; | 205 | struct atm_vcc *atmvcc; |
205 | int minheadroom = (brvcc->encaps == e_llc) ? 10 : 2; | 206 | int minheadroom = (brvcc->encaps == e_llc) ? |
207 | ((brdev->payload == p_bridged) ? | ||
208 | sizeof(llc_oui_pid_pad) : sizeof(llc_oui_ipv4)) : | ||
209 | ((brdev->payload == p_bridged) ? BR2684_PAD_LEN : 0); | ||
206 | 210 | ||
207 | if (skb_headroom(skb) < minheadroom) { | 211 | if (skb_headroom(skb) < minheadroom) { |
208 | struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom); | 212 | struct sk_buff *skb2 = skb_realloc_headroom(skb, minheadroom); |
@@ -450,7 +454,7 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
450 | skb->pkt_type = PACKET_HOST; | 454 | skb->pkt_type = PACKET_HOST; |
451 | } else { /* p_bridged */ | 455 | } else { /* p_bridged */ |
452 | /* first 2 chars should be 0 */ | 456 | /* first 2 chars should be 0 */ |
453 | if (*((u16 *) (skb->data)) != 0) | 457 | if (memcmp(skb->data, pad, BR2684_PAD_LEN) != 0) |
454 | goto error; | 458 | goto error; |
455 | skb_pull(skb, BR2684_PAD_LEN); | 459 | skb_pull(skb, BR2684_PAD_LEN); |
456 | skb->protocol = eth_type_trans(skb, net_dev); | 460 | skb->protocol = eth_type_trans(skb, net_dev); |
@@ -489,15 +493,11 @@ free_skb: | |||
489 | */ | 493 | */ |
490 | static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | 494 | static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) |
491 | { | 495 | { |
492 | struct sk_buff_head queue; | ||
493 | int err; | ||
494 | struct br2684_vcc *brvcc; | 496 | struct br2684_vcc *brvcc; |
495 | struct sk_buff *skb, *tmp; | ||
496 | struct sk_buff_head *rq; | ||
497 | struct br2684_dev *brdev; | 497 | struct br2684_dev *brdev; |
498 | struct net_device *net_dev; | 498 | struct net_device *net_dev; |
499 | struct atm_backend_br2684 be; | 499 | struct atm_backend_br2684 be; |
500 | unsigned long flags; | 500 | int err; |
501 | 501 | ||
502 | if (copy_from_user(&be, arg, sizeof be)) | 502 | if (copy_from_user(&be, arg, sizeof be)) |
503 | return -EFAULT; | 503 | return -EFAULT; |
@@ -550,23 +550,6 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
550 | atmvcc->push = br2684_push; | 550 | atmvcc->push = br2684_push; |
551 | atmvcc->pop = br2684_pop; | 551 | atmvcc->pop = br2684_pop; |
552 | 552 | ||
553 | __skb_queue_head_init(&queue); | ||
554 | rq = &sk_atm(atmvcc)->sk_receive_queue; | ||
555 | |||
556 | spin_lock_irqsave(&rq->lock, flags); | ||
557 | skb_queue_splice_init(rq, &queue); | ||
558 | spin_unlock_irqrestore(&rq->lock, flags); | ||
559 | |||
560 | skb_queue_walk_safe(&queue, skb, tmp) { | ||
561 | struct net_device *dev; | ||
562 | |||
563 | br2684_push(atmvcc, skb); | ||
564 | dev = skb->dev; | ||
565 | |||
566 | dev->stats.rx_bytes -= skb->len; | ||
567 | dev->stats.rx_packets--; | ||
568 | } | ||
569 | |||
570 | /* initialize netdev carrier state */ | 553 | /* initialize netdev carrier state */ |
571 | if (atmvcc->dev->signal == ATM_PHY_SIG_LOST) | 554 | if (atmvcc->dev->signal == ATM_PHY_SIG_LOST) |
572 | netif_carrier_off(net_dev); | 555 | netif_carrier_off(net_dev); |
@@ -574,6 +557,10 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
574 | netif_carrier_on(net_dev); | 557 | netif_carrier_on(net_dev); |
575 | 558 | ||
576 | __module_get(THIS_MODULE); | 559 | __module_get(THIS_MODULE); |
560 | |||
561 | /* re-process everything received between connection setup and | ||
562 | backend setup */ | ||
563 | vcc_process_recv_queue(atmvcc); | ||
577 | return 0; | 564 | return 0; |
578 | 565 | ||
579 | error: | 566 | error: |
@@ -600,6 +587,7 @@ static void br2684_setup(struct net_device *netdev) | |||
600 | struct br2684_dev *brdev = BRPRIV(netdev); | 587 | struct br2684_dev *brdev = BRPRIV(netdev); |
601 | 588 | ||
602 | ether_setup(netdev); | 589 | ether_setup(netdev); |
590 | netdev->hard_header_len += sizeof(llc_oui_pid_pad); /* worst case */ | ||
603 | brdev->net_dev = netdev; | 591 | brdev->net_dev = netdev; |
604 | 592 | ||
605 | netdev->netdev_ops = &br2684_netdev_ops; | 593 | netdev->netdev_ops = &br2684_netdev_ops; |
@@ -612,7 +600,7 @@ static void br2684_setup_routed(struct net_device *netdev) | |||
612 | struct br2684_dev *brdev = BRPRIV(netdev); | 600 | struct br2684_dev *brdev = BRPRIV(netdev); |
613 | 601 | ||
614 | brdev->net_dev = netdev; | 602 | brdev->net_dev = netdev; |
615 | netdev->hard_header_len = 0; | 603 | netdev->hard_header_len = sizeof(llc_oui_ipv4); /* worst case */ |
616 | netdev->netdev_ops = &br2684_netdev_ops_routed; | 604 | netdev->netdev_ops = &br2684_netdev_ops_routed; |
617 | netdev->addr_len = 0; | 605 | netdev->addr_len = 0; |
618 | netdev->mtu = 1500; | 606 | netdev->mtu = 1500; |