diff options
Diffstat (limited to 'net/ipv6/ip6_tunnel.c')
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 6022fc5e557a..985d106dff6d 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -513,14 +513,17 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
513 | return 0; | 513 | return 0; |
514 | } | 514 | } |
515 | 515 | ||
516 | static inline void ip6ip6_ecn_decapsulate(struct ipv6hdr *outer_iph, | 516 | static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, |
517 | struct sk_buff *skb) | 517 | struct ipv6hdr *ipv6h, |
518 | struct sk_buff *skb) | ||
518 | { | 519 | { |
519 | struct ipv6hdr *inner_iph = skb->nh.ipv6h; | 520 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) |
521 | ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); | ||
520 | 522 | ||
521 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | 523 | if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h))) |
522 | IP6_ECN_set_ce(inner_iph); | 524 | IP6_ECN_set_ce(skb->nh.ipv6h); |
523 | } | 525 | } |
526 | |||
524 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | 527 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) |
525 | { | 528 | { |
526 | struct ip6_tnl_parm *p = &t->parms; | 529 | struct ip6_tnl_parm *p = &t->parms; |
@@ -546,12 +549,16 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | |||
546 | /** | 549 | /** |
547 | * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally | 550 | * ip6ip6_rcv - decapsulate IPv6 packet and retransmit it locally |
548 | * @skb: received socket buffer | 551 | * @skb: received socket buffer |
552 | * @protocol: ethernet protocol ID | ||
553 | * @dscp_ecn_decapsulate: the function to decapsulate DSCP code and ECN | ||
549 | * | 554 | * |
550 | * Return: 0 | 555 | * Return: 0 |
551 | **/ | 556 | **/ |
552 | 557 | ||
553 | static int | 558 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, |
554 | ip6ip6_rcv(struct sk_buff *skb) | 559 | void (*dscp_ecn_decapsulate)(struct ip6_tnl *t, |
560 | struct ipv6hdr *ipv6h, | ||
561 | struct sk_buff *skb)) | ||
555 | { | 562 | { |
556 | struct ipv6hdr *ipv6h; | 563 | struct ipv6hdr *ipv6h; |
557 | struct ip6_tnl *t; | 564 | struct ip6_tnl *t; |
@@ -574,16 +581,16 @@ ip6ip6_rcv(struct sk_buff *skb) | |||
574 | secpath_reset(skb); | 581 | secpath_reset(skb); |
575 | skb->mac.raw = skb->nh.raw; | 582 | skb->mac.raw = skb->nh.raw; |
576 | skb->nh.raw = skb->data; | 583 | skb->nh.raw = skb->data; |
577 | skb->protocol = htons(ETH_P_IPV6); | 584 | skb->protocol = htons(protocol); |
578 | skb->pkt_type = PACKET_HOST; | 585 | skb->pkt_type = PACKET_HOST; |
579 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); | 586 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); |
580 | skb->dev = t->dev; | 587 | skb->dev = t->dev; |
581 | dst_release(skb->dst); | 588 | dst_release(skb->dst); |
582 | skb->dst = NULL; | 589 | skb->dst = NULL; |
583 | nf_reset(skb); | 590 | nf_reset(skb); |
584 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | 591 | |
585 | ipv6_copy_dscp(ipv6h, skb->nh.ipv6h); | 592 | dscp_ecn_decapsulate(t, ipv6h, skb); |
586 | ip6ip6_ecn_decapsulate(ipv6h, skb); | 593 | |
587 | t->stat.rx_packets++; | 594 | t->stat.rx_packets++; |
588 | t->stat.rx_bytes += skb->len; | 595 | t->stat.rx_bytes += skb->len; |
589 | netif_rx(skb); | 596 | netif_rx(skb); |
@@ -598,6 +605,11 @@ discard: | |||
598 | return 0; | 605 | return 0; |
599 | } | 606 | } |
600 | 607 | ||
608 | static int ip6ip6_rcv(struct sk_buff *skb) | ||
609 | { | ||
610 | return ip6_tnl_rcv(skb, ETH_P_IPV6, ip6ip6_dscp_ecn_decapsulate); | ||
611 | } | ||
612 | |||
601 | struct ipv6_tel_txoption { | 613 | struct ipv6_tel_txoption { |
602 | struct ipv6_txoptions ops; | 614 | struct ipv6_txoptions ops; |
603 | __u8 dst_opt[8]; | 615 | __u8 dst_opt[8]; |