diff options
Diffstat (limited to 'net/ipv4/ip_gre.c')
| -rw-r--r-- | net/ipv4/ip_gre.c | 39 |
1 files changed, 20 insertions, 19 deletions
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index d1d09f3e5f9e..3978f807fa8b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
| 268 | int len; | 268 | int len; |
| 269 | 269 | ||
| 270 | itn = net_generic(net, erspan_net_id); | 270 | itn = net_generic(net, erspan_net_id); |
| 271 | len = gre_hdr_len + sizeof(*ershdr); | ||
| 272 | |||
| 273 | /* Check based hdr len */ | ||
| 274 | if (unlikely(!pskb_may_pull(skb, len))) | ||
| 275 | return PACKET_REJECT; | ||
| 276 | 271 | ||
| 277 | iph = ip_hdr(skb); | 272 | iph = ip_hdr(skb); |
| 278 | ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); | 273 | ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len); |
| 279 | ver = ershdr->ver; | 274 | ver = ershdr->ver; |
| 280 | 275 | ||
| 281 | /* The original GRE header does not have key field, | ||
| 282 | * Use ERSPAN 10-bit session ID as key. | ||
| 283 | */ | ||
| 284 | tpi->key = cpu_to_be32(get_session_id(ershdr)); | ||
| 285 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, | 276 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, |
| 286 | tpi->flags | TUNNEL_KEY, | 277 | tpi->flags | TUNNEL_KEY, |
| 287 | iph->saddr, iph->daddr, tpi->key); | 278 | iph->saddr, iph->daddr, tpi->key); |
| @@ -569,8 +560,7 @@ err_free_skb: | |||
| 569 | dev->stats.tx_dropped++; | 560 | dev->stats.tx_dropped++; |
| 570 | } | 561 | } |
| 571 | 562 | ||
| 572 | static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, | 563 | static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev) |
| 573 | __be16 proto) | ||
| 574 | { | 564 | { |
| 575 | struct ip_tunnel *tunnel = netdev_priv(dev); | 565 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 576 | struct ip_tunnel_info *tun_info; | 566 | struct ip_tunnel_info *tun_info; |
| @@ -578,10 +568,10 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 578 | struct erspan_metadata *md; | 568 | struct erspan_metadata *md; |
| 579 | struct rtable *rt = NULL; | 569 | struct rtable *rt = NULL; |
| 580 | bool truncate = false; | 570 | bool truncate = false; |
| 571 | __be16 df, proto; | ||
| 581 | struct flowi4 fl; | 572 | struct flowi4 fl; |
| 582 | int tunnel_hlen; | 573 | int tunnel_hlen; |
| 583 | int version; | 574 | int version; |
| 584 | __be16 df; | ||
| 585 | int nhoff; | 575 | int nhoff; |
| 586 | int thoff; | 576 | int thoff; |
| 587 | 577 | ||
| @@ -626,18 +616,20 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 626 | if (version == 1) { | 616 | if (version == 1) { |
| 627 | erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), | 617 | erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)), |
| 628 | ntohl(md->u.index), truncate, true); | 618 | ntohl(md->u.index), truncate, true); |
| 619 | proto = htons(ETH_P_ERSPAN); | ||
| 629 | } else if (version == 2) { | 620 | } else if (version == 2) { |
| 630 | erspan_build_header_v2(skb, | 621 | erspan_build_header_v2(skb, |
| 631 | ntohl(tunnel_id_to_key32(key->tun_id)), | 622 | ntohl(tunnel_id_to_key32(key->tun_id)), |
| 632 | md->u.md2.dir, | 623 | md->u.md2.dir, |
| 633 | get_hwid(&md->u.md2), | 624 | get_hwid(&md->u.md2), |
| 634 | truncate, true); | 625 | truncate, true); |
| 626 | proto = htons(ETH_P_ERSPAN2); | ||
| 635 | } else { | 627 | } else { |
| 636 | goto err_free_rt; | 628 | goto err_free_rt; |
| 637 | } | 629 | } |
| 638 | 630 | ||
| 639 | gre_build_header(skb, 8, TUNNEL_SEQ, | 631 | gre_build_header(skb, 8, TUNNEL_SEQ, |
| 640 | htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++)); | 632 | proto, 0, htonl(tunnel->o_seqno++)); |
| 641 | 633 | ||
| 642 | df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; | 634 | df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; |
| 643 | 635 | ||
| @@ -721,12 +713,13 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, | |||
| 721 | { | 713 | { |
| 722 | struct ip_tunnel *tunnel = netdev_priv(dev); | 714 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 723 | bool truncate = false; | 715 | bool truncate = false; |
| 716 | __be16 proto; | ||
| 724 | 717 | ||
| 725 | if (!pskb_inet_may_pull(skb)) | 718 | if (!pskb_inet_may_pull(skb)) |
| 726 | goto free_skb; | 719 | goto free_skb; |
| 727 | 720 | ||
| 728 | if (tunnel->collect_md) { | 721 | if (tunnel->collect_md) { |
| 729 | erspan_fb_xmit(skb, dev, skb->protocol); | 722 | erspan_fb_xmit(skb, dev); |
| 730 | return NETDEV_TX_OK; | 723 | return NETDEV_TX_OK; |
| 731 | } | 724 | } |
| 732 | 725 | ||
| @@ -742,19 +735,22 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb, | |||
| 742 | } | 735 | } |
| 743 | 736 | ||
| 744 | /* Push ERSPAN header */ | 737 | /* Push ERSPAN header */ |
| 745 | if (tunnel->erspan_ver == 1) | 738 | if (tunnel->erspan_ver == 1) { |
| 746 | erspan_build_header(skb, ntohl(tunnel->parms.o_key), | 739 | erspan_build_header(skb, ntohl(tunnel->parms.o_key), |
| 747 | tunnel->index, | 740 | tunnel->index, |
| 748 | truncate, true); | 741 | truncate, true); |
| 749 | else if (tunnel->erspan_ver == 2) | 742 | proto = htons(ETH_P_ERSPAN); |
| 743 | } else if (tunnel->erspan_ver == 2) { | ||
| 750 | erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), | 744 | erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key), |
| 751 | tunnel->dir, tunnel->hwid, | 745 | tunnel->dir, tunnel->hwid, |
| 752 | truncate, true); | 746 | truncate, true); |
| 753 | else | 747 | proto = htons(ETH_P_ERSPAN2); |
| 748 | } else { | ||
| 754 | goto free_skb; | 749 | goto free_skb; |
| 750 | } | ||
| 755 | 751 | ||
| 756 | tunnel->parms.o_flags &= ~TUNNEL_KEY; | 752 | tunnel->parms.o_flags &= ~TUNNEL_KEY; |
| 757 | __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN)); | 753 | __gre_xmit(skb, dev, &tunnel->parms.iph, proto); |
| 758 | return NETDEV_TX_OK; | 754 | return NETDEV_TX_OK; |
| 759 | 755 | ||
| 760 | free_skb: | 756 | free_skb: |
| @@ -1459,12 +1455,17 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
| 1459 | { | 1455 | { |
| 1460 | struct ip_tunnel *t = netdev_priv(dev); | 1456 | struct ip_tunnel *t = netdev_priv(dev); |
| 1461 | struct ip_tunnel_parm *p = &t->parms; | 1457 | struct ip_tunnel_parm *p = &t->parms; |
| 1458 | __be16 o_flags = p->o_flags; | ||
| 1459 | |||
| 1460 | if ((t->erspan_ver == 1 || t->erspan_ver == 2) && | ||
| 1461 | !t->collect_md) | ||
| 1462 | o_flags |= TUNNEL_KEY; | ||
| 1462 | 1463 | ||
| 1463 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || | 1464 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || |
| 1464 | nla_put_be16(skb, IFLA_GRE_IFLAGS, | 1465 | nla_put_be16(skb, IFLA_GRE_IFLAGS, |
| 1465 | gre_tnl_flags_to_gre_flags(p->i_flags)) || | 1466 | gre_tnl_flags_to_gre_flags(p->i_flags)) || |
| 1466 | nla_put_be16(skb, IFLA_GRE_OFLAGS, | 1467 | nla_put_be16(skb, IFLA_GRE_OFLAGS, |
| 1467 | gre_tnl_flags_to_gre_flags(p->o_flags)) || | 1468 | gre_tnl_flags_to_gre_flags(o_flags)) || |
| 1468 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || | 1469 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || |
| 1469 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || | 1470 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || |
| 1470 | nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || | 1471 | nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) || |
