diff options
| author | Eric Kinzie <ekinzie@cmf.nrl.navy.mil> | 2008-06-16 20:18:18 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-06-16 20:18:18 -0400 |
| commit | 7e903c2ae36efb526eacab3b25d00e90424bd8a8 (patch) | |
| tree | 857f53f4d5b039ecc8c40238b2e8a115c7e497b0 | |
| parent | 059e3779b59527150e1d1942026ec149192cbf77 (diff) | |
atm: [br2864] fix routed vcmux support
From: Eric Kinzie <ekinzie@cmf.nrl.navy.mil>
Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | net/atm/br2684.c | 76 |
1 files changed, 44 insertions, 32 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index ac6035046adc..05fafdc2eea3 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
| @@ -188,10 +188,13 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct br2684_dev *brdev, | |||
| 188 | return 0; | 188 | return 0; |
| 189 | } | 189 | } |
| 190 | } | 190 | } |
| 191 | } else { | 191 | } else { /* e_vc */ |
| 192 | skb_push(skb, 2); | 192 | if (brdev->payload == p_bridged) { |
| 193 | if (brdev->payload == p_bridged) | 193 | skb_push(skb, 2); |
| 194 | memset(skb->data, 0, 2); | 194 | memset(skb->data, 0, 2); |
| 195 | } else { /* p_routed */ | ||
| 196 | skb_pull(skb, ETH_HLEN); | ||
| 197 | } | ||
| 195 | } | 198 | } |
| 196 | skb_debug(skb); | 199 | skb_debug(skb); |
| 197 | 200 | ||
| @@ -377,11 +380,8 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
| 377 | (skb->data + 6, ethertype_ipv4, | 380 | (skb->data + 6, ethertype_ipv4, |
| 378 | sizeof(ethertype_ipv4)) == 0) | 381 | sizeof(ethertype_ipv4)) == 0) |
| 379 | skb->protocol = __constant_htons(ETH_P_IP); | 382 | skb->protocol = __constant_htons(ETH_P_IP); |
| 380 | else { | 383 | else |
| 381 | brdev->stats.rx_errors++; | 384 | goto error; |
| 382 | dev_kfree_skb(skb); | ||
| 383 | return; | ||
| 384 | } | ||
| 385 | skb_pull(skb, sizeof(llc_oui_ipv4)); | 385 | skb_pull(skb, sizeof(llc_oui_ipv4)); |
| 386 | skb_reset_network_header(skb); | 386 | skb_reset_network_header(skb); |
| 387 | skb->pkt_type = PACKET_HOST; | 387 | skb->pkt_type = PACKET_HOST; |
| @@ -394,44 +394,56 @@ static void br2684_push(struct atm_vcc *atmvcc, struct sk_buff *skb) | |||
| 394 | (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { | 394 | (memcmp(skb->data, llc_oui_pid_pad, 7) == 0)) { |
| 395 | skb_pull(skb, sizeof(llc_oui_pid_pad)); | 395 | skb_pull(skb, sizeof(llc_oui_pid_pad)); |
| 396 | skb->protocol = eth_type_trans(skb, net_dev); | 396 | skb->protocol = eth_type_trans(skb, net_dev); |
| 397 | } else { | 397 | } else |
| 398 | brdev->stats.rx_errors++; | 398 | goto error; |
| 399 | dev_kfree_skb(skb); | ||
| 400 | return; | ||
| 401 | } | ||
| 402 | 399 | ||
| 403 | } else { | 400 | } else { /* e_vc */ |
| 404 | /* first 2 chars should be 0 */ | 401 | if (brdev->payload == p_routed) { |
| 405 | if (*((u16 *) (skb->data)) != 0) { | 402 | struct iphdr *iph; |
| 406 | brdev->stats.rx_errors++; | 403 | |
| 407 | dev_kfree_skb(skb); | 404 | skb_reset_network_header(skb); |
| 408 | return; | 405 | iph = ip_hdr(skb); |
| 406 | if (iph->version == 4) | ||
| 407 | skb->protocol = __constant_htons(ETH_P_IP); | ||
| 408 | else if (iph->version == 6) | ||
| 409 | skb->protocol = __constant_htons(ETH_P_IPV6); | ||
| 410 | else | ||
| 411 | goto error; | ||
| 412 | skb->pkt_type = PACKET_HOST; | ||
| 413 | } else { /* p_bridged */ | ||
| 414 | /* first 2 chars should be 0 */ | ||
| 415 | if (*((u16 *) (skb->data)) != 0) | ||
| 416 | goto error; | ||
| 417 | skb_pull(skb, BR2684_PAD_LEN); | ||
| 418 | skb->protocol = eth_type_trans(skb, net_dev); | ||
| 409 | } | 419 | } |
| 410 | skb_pull(skb, BR2684_PAD_LEN + ETH_HLEN); /* pad, dstmac, srcmac, ethtype */ | ||
| 411 | skb->protocol = eth_type_trans(skb, net_dev); | ||
| 412 | } | 420 | } |
| 413 | 421 | ||
| 414 | #ifdef CONFIG_ATM_BR2684_IPFILTER | 422 | #ifdef CONFIG_ATM_BR2684_IPFILTER |
| 415 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) { | 423 | if (unlikely(packet_fails_filter(skb->protocol, brvcc, skb))) |
| 416 | brdev->stats.rx_dropped++; | 424 | goto dropped; |
| 417 | dev_kfree_skb(skb); | ||
| 418 | return; | ||
| 419 | } | ||
| 420 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ | 425 | #endif /* CONFIG_ATM_BR2684_IPFILTER */ |
| 421 | skb->dev = net_dev; | 426 | skb->dev = net_dev; |
| 422 | ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ | 427 | ATM_SKB(skb)->vcc = atmvcc; /* needed ? */ |
| 423 | pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol)); | 428 | pr_debug("received packet's protocol: %x\n", ntohs(skb->protocol)); |
| 424 | skb_debug(skb); | 429 | skb_debug(skb); |
| 425 | if (unlikely(!(net_dev->flags & IFF_UP))) { | 430 | /* sigh, interface is down? */ |
| 426 | /* sigh, interface is down */ | 431 | if (unlikely(!(net_dev->flags & IFF_UP))) |
| 427 | brdev->stats.rx_dropped++; | 432 | goto dropped; |
| 428 | dev_kfree_skb(skb); | ||
| 429 | return; | ||
| 430 | } | ||
| 431 | brdev->stats.rx_packets++; | 433 | brdev->stats.rx_packets++; |
| 432 | brdev->stats.rx_bytes += skb->len; | 434 | brdev->stats.rx_bytes += skb->len; |
| 433 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); | 435 | memset(ATM_SKB(skb), 0, sizeof(struct atm_skb_data)); |
| 434 | netif_rx(skb); | 436 | netif_rx(skb); |
| 437 | return; | ||
| 438 | |||
| 439 | dropped: | ||
| 440 | brdev->stats.rx_dropped++; | ||
| 441 | goto free_skb; | ||
| 442 | error: | ||
| 443 | brdev->stats.rx_errors++; | ||
| 444 | free_skb: | ||
| 445 | dev_kfree_skb(skb); | ||
| 446 | return; | ||
| 435 | } | 447 | } |
| 436 | 448 | ||
| 437 | /* | 449 | /* |
