diff options
Diffstat (limited to 'drivers/net/gtp.c')
-rw-r--r-- | drivers/net/gtp.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c index 4c04e271f184..9a70f05baf6e 100644 --- a/drivers/net/gtp.c +++ b/drivers/net/gtp.c @@ -189,8 +189,10 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, /* Get rid of the GTP + UDP headers. */ if (iptunnel_pull_header(skb, hdrlen, skb->protocol, - !net_eq(sock_net(pctx->sk), dev_net(pctx->dev)))) - return -1; + !net_eq(sock_net(pctx->sk), dev_net(pctx->dev)))) { + pctx->dev->stats.rx_length_errors++; + goto err; + } netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n"); @@ -206,6 +208,10 @@ static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, netif_rx(skb); return 0; + +err: + pctx->dev->stats.rx_dropped++; + return -1; } /* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */ @@ -515,8 +521,6 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev, goto err_rt; } - skb_dst_drop(skb); - /* This is similar to tnl_update_pmtu(). */ df = iph->frag_off; if (df) { @@ -592,7 +596,9 @@ static netdev_tx_t gtp_dev_xmit(struct sk_buff *skb, struct net_device *dev) ip4_dst_hoplimit(&pktinfo.rt->dst), 0, pktinfo.gtph_port, pktinfo.gtph_port, - true, false); + !net_eq(sock_net(pktinfo.pctx->sk), + dev_net(dev)), + false); break; } @@ -610,13 +616,23 @@ static const struct net_device_ops gtp_netdev_ops = { .ndo_get_stats64 = dev_get_tstats64, }; +static const struct device_type gtp_type = { + .name = "gtp", +}; + static void gtp_link_setup(struct net_device *dev) { + unsigned int max_gtp_header_len = sizeof(struct iphdr) + + sizeof(struct udphdr) + + sizeof(struct gtp0_header); + dev->netdev_ops = >p_netdev_ops; dev->needs_free_netdev = true; + SET_NETDEV_DEVTYPE(dev, >p_type); dev->hard_header_len = 0; dev->addr_len = 0; + dev->mtu = ETH_DATA_LEN - max_gtp_header_len; /* Zero header length. */ dev->type = ARPHRD_NONE; @@ -626,11 +642,7 @@ static void gtp_link_setup(struct net_device *dev) dev->features |= NETIF_F_LLTX; netif_keep_dst(dev); - /* Assume largest header, ie. GTPv0. */ - dev->needed_headroom = LL_MAX_HEADER + - sizeof(struct iphdr) + - sizeof(struct udphdr) + - sizeof(struct gtp0_header); + dev->needed_headroom = LL_MAX_HEADER + max_gtp_header_len; } static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize); @@ -727,7 +739,8 @@ static int gtp_validate(struct nlattr *tb[], struct nlattr *data[], static size_t gtp_get_size(const struct net_device *dev) { - return nla_total_size(sizeof(__u32)); /* IFLA_GTP_PDP_HASHSIZE */ + return nla_total_size(sizeof(__u32)) + /* IFLA_GTP_PDP_HASHSIZE */ + nla_total_size(sizeof(__u32)); /* IFLA_GTP_ROLE */ } static int gtp_fill_info(struct sk_buff *skb, const struct net_device *dev) @@ -736,6 +749,8 @@ static int gtp_fill_info(struct sk_buff *skb, const struct net_device *dev) if (nla_put_u32(skb, IFLA_GTP_PDP_HASHSIZE, gtp->hash_size)) goto nla_put_failure; + if (nla_put_u32(skb, IFLA_GTP_ROLE, gtp->role)) + goto nla_put_failure; return 0; |