Skip to content

Commit 308edfd

Browse files
tomratbertdavem330
authored andcommitted
gre6: Cleanup GREv6 receive path, call common GRE functions
- Create gre_rcv function. This calls gre_parse_header and ip6gre_rcv. - Call ip6_tnl_rcv. Doing this and using gre_parse_header eliminates most of the code in ip6gre_rcv. Signed-off-by: Tom Herbert <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 95f5c64 commit 308edfd

File tree

1 file changed

+23
-117
lines changed

1 file changed

+23
-117
lines changed

net/ipv6/ip6_gre.c

Lines changed: 23 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
#include <net/ip6_fib.h>
5555
#include <net/ip6_route.h>
5656
#include <net/ip6_tunnel.h>
57+
#include <net/gre.h>
5758

5859

5960
static bool log_ecn_error = true;
@@ -443,137 +444,40 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
443444
t->err_time = jiffies;
444445
}
445446

446-
static int ip6gre_rcv(struct sk_buff *skb)
447+
static int ip6gre_rcv(struct sk_buff *skb, const struct tnl_ptk_info *tpi)
447448
{
448449
const struct ipv6hdr *ipv6h;
449-
u8 *h;
450-
__be16 flags;
451-
__sum16 csum = 0;
452-
__be32 key = 0;
453-
u32 seqno = 0;
454450
struct ip6_tnl *tunnel;
455-
int offset = 4;
456-
__be16 gre_proto;
457-
int err;
458-
459-
if (!pskb_may_pull(skb, sizeof(struct in6_addr)))
460-
goto drop;
461451

462452
ipv6h = ipv6_hdr(skb);
463-
h = skb->data;
464-
flags = *(__be16 *)h;
465-
466-
if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) {
467-
/* - Version must be 0.
468-
- We do not support routing headers.
469-
*/
470-
if (flags&(GRE_VERSION|GRE_ROUTING))
471-
goto drop;
472-
473-
if (flags&GRE_CSUM) {
474-
csum = skb_checksum_simple_validate(skb);
475-
offset += 4;
476-
}
477-
if (flags&GRE_KEY) {
478-
key = *(__be32 *)(h + offset);
479-
offset += 4;
480-
}
481-
if (flags&GRE_SEQ) {
482-
seqno = ntohl(*(__be32 *)(h + offset));
483-
offset += 4;
484-
}
485-
}
486-
487-
gre_proto = *(__be16 *)(h + 2);
488-
489453
tunnel = ip6gre_tunnel_lookup(skb->dev,
490-
&ipv6h->saddr, &ipv6h->daddr, key,
491-
gre_proto);
454+
&ipv6h->saddr, &ipv6h->daddr, tpi->key,
455+
tpi->proto);
492456
if (tunnel) {
493-
struct pcpu_sw_netstats *tstats;
494-
495-
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
496-
goto drop;
497-
498-
if (!ip6_tnl_rcv_ctl(tunnel, &ipv6h->daddr, &ipv6h->saddr)) {
499-
tunnel->dev->stats.rx_dropped++;
500-
goto drop;
501-
}
502-
503-
skb->protocol = gre_proto;
504-
/* WCCP version 1 and 2 protocol decoding.
505-
* - Change protocol to IPv6
506-
* - When dealing with WCCPv2, Skip extra 4 bytes in GRE header
507-
*/
508-
if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) {
509-
skb->protocol = htons(ETH_P_IPV6);
510-
if ((*(h + offset) & 0xF0) != 0x40)
511-
offset += 4;
512-
}
457+
ip6_tnl_rcv(tunnel, skb, tpi, NULL, false);
513458

514-
skb->mac_header = skb->network_header;
515-
__pskb_pull(skb, offset);
516-
skb_postpull_rcsum(skb, skb_transport_header(skb), offset);
517-
518-
if (((flags&GRE_CSUM) && csum) ||
519-
(!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) {
520-
tunnel->dev->stats.rx_crc_errors++;
521-
tunnel->dev->stats.rx_errors++;
522-
goto drop;
523-
}
524-
if (tunnel->parms.i_flags&GRE_SEQ) {
525-
if (!(flags&GRE_SEQ) ||
526-
(tunnel->i_seqno &&
527-
(s32)(seqno - tunnel->i_seqno) < 0)) {
528-
tunnel->dev->stats.rx_fifo_errors++;
529-
tunnel->dev->stats.rx_errors++;
530-
goto drop;
531-
}
532-
tunnel->i_seqno = seqno + 1;
533-
}
534-
535-
/* Warning: All skb pointers will be invalidated! */
536-
if (tunnel->dev->type == ARPHRD_ETHER) {
537-
if (!pskb_may_pull(skb, ETH_HLEN)) {
538-
tunnel->dev->stats.rx_length_errors++;
539-
tunnel->dev->stats.rx_errors++;
540-
goto drop;
541-
}
542-
543-
ipv6h = ipv6_hdr(skb);
544-
skb->protocol = eth_type_trans(skb, tunnel->dev);
545-
skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
546-
}
547-
548-
__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
459+
return PACKET_RCVD;
460+
}
549461

550-
skb_reset_network_header(skb);
462+
return PACKET_REJECT;
463+
}
551464

552-
err = IP6_ECN_decapsulate(ipv6h, skb);
553-
if (unlikely(err)) {
554-
if (log_ecn_error)
555-
net_info_ratelimited("non-ECT from %pI6 with dsfield=%#x\n",
556-
&ipv6h->saddr,
557-
ipv6_get_dsfield(ipv6h));
558-
if (err > 1) {
559-
++tunnel->dev->stats.rx_frame_errors;
560-
++tunnel->dev->stats.rx_errors;
561-
goto drop;
562-
}
563-
}
465+
static int gre_rcv(struct sk_buff *skb)
466+
{
467+
struct tnl_ptk_info tpi;
468+
bool csum_err = false;
469+
int hdr_len;
564470

565-
tstats = this_cpu_ptr(tunnel->dev->tstats);
566-
u64_stats_update_begin(&tstats->syncp);
567-
tstats->rx_packets++;
568-
tstats->rx_bytes += skb->len;
569-
u64_stats_update_end(&tstats->syncp);
471+
if (gre_parse_header(skb, &tpi, &csum_err, &hdr_len) < 0)
472+
goto drop;
570473

571-
netif_rx(skb);
474+
if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false))
475+
goto drop;
572476

477+
if (ip6gre_rcv(skb, &tpi) == PACKET_RCVD)
573478
return 0;
574-
}
575-
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
576479

480+
icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0);
577481
drop:
578482
kfree_skb(skb);
579483
return 0;
@@ -1075,6 +979,8 @@ static int ip6gre_tunnel_ioctl(struct net_device *dev,
1075979
struct net *net = t->net;
1076980
struct ip6gre_net *ign = net_generic(net, ip6gre_net_id);
1077981

982+
memset(&p1, 0, sizeof(p1));
983+
1078984
switch (cmd) {
1079985
case SIOCGETTUNNEL:
1080986
if (dev == ign->fb_tunnel_dev) {
@@ -1318,7 +1224,7 @@ static void ip6gre_fb_tunnel_init(struct net_device *dev)
13181224

13191225

13201226
static struct inet6_protocol ip6gre_protocol __read_mostly = {
1321-
.handler = ip6gre_rcv,
1227+
.handler = gre_rcv,
13221228
.err_handler = ip6gre_err,
13231229
.flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
13241230
};

0 commit comments

Comments
 (0)