aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/gtp.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/net/gtp.c37
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 = &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 +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;