aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ip_gre.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv4/ip_gre.c')
-rw-r--r--net/ipv4/ip_gre.c39
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
572static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev, 563static 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
760free_skb: 756free_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) ||