[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Sat, 12 Dec 2020 14:11:33 -0800
From: Jakub Kicinski <kuba@...nel.org>
To: Pravin B Shelar <pbshelar@...com>
Cc: <netdev@...r.kernel.org>, <pablo@...filter.org>,
<laforge@...monks.org>, <jonas@...rbonn.se>, <pravin.ovn@...il.com>
Subject: Re: [PATCH net-next v2] GTP: add support for flow based tunneling
API
On Fri, 11 Dec 2020 20:40:17 -0800 Pravin B Shelar wrote:
> Following patch add support for flow based tunneling API
> to send and recv GTP tunnel packet over tunnel metadata API.
> This would allow this device integration with OVS or eBPF using
> flow based tunneling APIs.
>
> Signed-off-by: Pravin B Shelar <pbshelar@...com>
> ---
> Fixed according to comments from Jonas Bonn
This adds a sparse warning:
drivers/net/gtp.c:218:39: warning: incorrect type in assignment (different base types)
drivers/net/gtp.c:218:39: expected restricted __be16 [usertype] protocol
drivers/net/gtp.c:218:39: got int
Coding nits below.
> @@ -179,33 +183,107 @@ static bool gtp_check_ms(struct sk_buff *skb, struct pdp_ctx *pctx,
> return false;
> }
>
> -static int gtp_rx(struct pdp_ctx *pctx, struct sk_buff *skb,
> - unsigned int hdrlen, unsigned int role)
> +static int gtp_rx(struct gtp_dev *gtp, struct sk_buff *skb,
> + unsigned int hdrlen, u8 gtp_version, unsigned int role,
> + __be64 tid, u8 flags, u8 type)
> {
> - if (!gtp_check_ms(skb, pctx, hdrlen, role)) {
> - netdev_dbg(pctx->dev, "No PDP ctx for this MS\n");
> - return 1;
> - }
> + if (ip_tunnel_collect_metadata() || gtp->collect_md) {
nit: this is a static function which is almost entirely indented now.
Please refactor.
> + struct metadata_dst *tun_dst;
> + int opts_len = 0;
> +
> + if (unlikely(flags & GTP1_F_MASK))
> + opts_len = sizeof(struct gtpu_metadata);
> +
> + tun_dst =
> + udp_tun_rx_dst(skb, gtp->sk1u->sk_family, TUNNEL_KEY, tid, opts_len);
Strange why to break a like after =, rather than just wrap function
args.
> + if (!tun_dst) {
> + netdev_dbg(gtp->dev, "Failed to allocate tun_dst");
> + goto err;
> + }
>
> - /* 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;
> + netdev_dbg(gtp->dev, "attaching metadata_dst to skb, gtp ver %d hdrlen %d\n",
> + gtp_version, hdrlen);
> + if (unlikely(opts_len)) {
> + struct gtpu_metadata *opts = ip_tunnel_info_opts(&tun_dst->u.tun_info);
> + struct gtp1_header *gtp1 = (struct gtp1_header *)(skb->data +
> + sizeof(struct udphdr));
Why bother initializing inline if it creates very long lines?
Please move both of those to separate statements.
> + opts->ver = GTP_METADATA_V1;
> + opts->flags = gtp1->flags;
> + opts->type = gtp1->type;
> + netdev_dbg(gtp->dev, "recved control pkt: flag %x type: %d\n",
> + opts->flags, opts->type);
> + tun_dst->u.tun_info.key.tun_flags |= TUNNEL_GTPU_OPT;
> + tun_dst->u.tun_info.options_len = opts_len;
> + skb->protocol = 0xffff; /* Unknown */
> + }
> + /* Get rid of the GTP + UDP headers. */
> + if (iptunnel_pull_header(skb, hdrlen, skb->protocol,
> + !net_eq(sock_net(gtp->sk1u), dev_net(gtp->dev)))) {
> + gtp->dev->stats.rx_length_errors++;
> + goto err;
> + }
> +
> + skb_dst_set(skb, &tun_dst->dst);
> + } else {
> + struct pdp_ctx *pctx;
> +
> + if (flags & GTP1_F_MASK)
> + hdrlen += 4;
> +
> + if (type != GTP_TPDU)
> + return 1;
>
> - netdev_dbg(pctx->dev, "forwarding packet from GGSN to uplink\n");
> + if (gtp_version == GTP_V0)
> + pctx = gtp0_pdp_find(gtp, be64_to_cpu(tid));
> + else
> + pctx = gtp1_pdp_find(gtp, be64_to_cpu(tid));
> + if (!pctx) {
> + netdev_dbg(gtp->dev, "No PDP ctx to decap skb=%p\n", skb);
> + return 1;
> + }
> +
> + if (!gtp_check_ms(skb, pctx, hdrlen, role)) {
> + 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,
> + !net_eq(sock_net(pctx->sk), dev_net(gtp->dev)))) {
> + gtp->dev->stats.rx_length_errors++;
> + goto err;
> + }
> + }
> + netdev_dbg(gtp->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);
> + if (pskb_may_pull(skb, sizeof(struct iphdr))) {
> + struct iphdr *iph;
> +
> + iph = ip_hdr(skb);
> + if (iph->version == 4) {
> + netdev_dbg(gtp->dev, "inner pkt: ipv4");
> + skb->protocol = htons(ETH_P_IP);
> + } else if (iph->version == 6) {
> + netdev_dbg(gtp->dev, "inner pkt: ipv6");
> + skb->protocol = htons(ETH_P_IPV6);
> + } else {
> + netdev_dbg(gtp->dev, "inner pkt error: Unknown type");
> + }
> + }
>
> - skb->dev = pctx->dev;
> -
> - dev_sw_netstats_rx_add(pctx->dev, skb->len);
> -
> + skb->dev = gtp->dev;
> + dev_sw_netstats_rx_add(gtp->dev, skb->len);
> netif_rx(skb);
> return 0;
> +
> +err:
> + gtp->dev->stats.rx_dropped++;
> + return -1;
> }
>
> /* 1 means pass up to the stack, -1 means drop and 0 means decapsulated. */
> @@ -329,7 +391,7 @@ static int gtp_encap_recv(struct sock *sk, struct sk_buff *skb)
> if (!gtp)
> return 1;
>
> - netdev_dbg(gtp->dev, "encap_recv sk=%p\n", sk);
> + netdev_dbg(gtp->dev, "encap_recv sk=%p type %d\n", sk, udp_sk(sk)->encap_type);
Prefer wrapping code at 80 chars.
> switch (udp_sk(sk)->encap_type) {
> case UDP_ENCAP_GTP0:
> @@ -737,6 +912,9 @@ 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 (gtp->collect_md && nla_put_flag(skb, IFLA_GTP_COLLECT_METADATA))
Double space before &&
> + goto nla_put_failure;
> +
> return 0;
>
> nla_put_failure:
Powered by blists - more mailing lists