Merge remote-tracking branch 'torvalds/master' into perf/core
[sfrench/cifs-2.6.git] / drivers / net / gtp.c
index 4c04e271f18441225663f4f42f4a21521ee311cf..39c00f050fbd8ae3807e024438b69c0e5ce559f1 100644 (file)
@@ -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) {
@@ -539,7 +543,6 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
        if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) &&
            mtu < ntohs(iph->tot_len)) {
                netdev_dbg(dev, "packet too big, fragmentation needed\n");
-               memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
                icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
                              htonl(mtu));
                goto err_rt;
@@ -592,7 +595,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 +615,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         = &gtp_netdev_ops;
        dev->needs_free_netdev  = true;
+       SET_NETDEV_DEVTYPE(dev, &gtp_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 +641,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 +738,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 +748,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;