struct in_addr ms_addr_ip4;
struct in_addr sgsn_addr_ip4;
+ struct net_device *dev;
+
atomic_t tx_seq;
struct rcu_head rcu_head;
};
return false;
}
+static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb, unsigned int hdrlen,
+ bool xnet)
+{
+ struct pcpu_sw_netstats *stats;
+
+ if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
+ netdev_dbg(pctx->dev, "No PDP ctx for this MS\n");
+ return 1;
+ }
+
+ /* Get rid of the GTP + UDP headers. */
+ if (iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet))
+ return -1;
+
+ netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n");
+
+ /* Now that the UDP and the GTP header have been removed, set up the
+ * new network header. This is required by the upper layer to
+ * calculate the transport header.
+ */
+ skb_reset_network_header(skb);
+
+ skb->dev = pctx->dev;
+
+ stats = this_cpu_ptr(pctx->dev->tstats);
+ u64_stats_update_begin(&stats->syncp);
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ u64_stats_update_end(&stats->syncp);
+
+ netif_rx(skb);
+ return 0;
+}
+
/* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */
static int gtp0_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
bool xnet)
return 1;
}
- if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
- netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
- return 1;
- }
-
- /* Get rid of the GTP + UDP headers. */
- return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
+ return gtp_rx(pctx, skb, hdrlen, xnet);
}
static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb,
return 1;
}
- if (!gtp_check_src_ms(skb, pctx, hdrlen)) {
- netdev_dbg(gtp->dev, "No PDP ctx for this MS\n");
- return 1;
- }
-
- /* Get rid of the GTP + UDP headers. */
- return iptunnel_pull_header(skb, hdrlen, skb->protocol, xnet);
+ return gtp_rx(pctx, skb, hdrlen, xnet);
}
static void gtp_encap_destroy(struct sock *sk)
*/
static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
{
- struct pcpu_sw_netstats *stats;
struct gtp_dev *gtp;
+ int ret = 0;
bool xnet;
- int ret;
gtp = rcu_dereference_sk_user_data(sk);
if (!gtp)
switch (ret) {
case 1:
netdev_dbg(gtp->dev, "pass up to the process\n");
- return 1;
+ break;
case 0:
- netdev_dbg(gtp->dev, "forwarding packet from GGSN to uplink\n");
break;
case -1:
netdev_dbg(gtp->dev, "GTP packet has been dropped\n");
kfree_skb(skb);
- return 0;
+ ret = 0;
+ break;
}
- /* Now that the UDP and the GTP header have been removed, set up the
- * new network header. This is required by the upper layer to
- * calculate the transport header.
- */
- skb_reset_network_header(skb);
-
- skb->dev = gtp->dev;
-
- stats = this_cpu_ptr(gtp->dev->tstats);
- u64_stats_update_begin(&stats->syncp);
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
- u64_stats_update_end(&stats->syncp);
-
- netif_rx(skb);
-
- return 0;
+ return ret;
}
static int gtp_dev_init(struct net_device *dev)
if (pctx == NULL)
return -ENOMEM;
+ pctx->dev = gtp->dev;
ipv4_pdp_fill(pctx, info);
atomic_set(&pctx->tx_seq, 0);