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 <pbshe...@fb.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: