if (IS_ERR(rt))
return PTR_ERR(rt);
- skb_tunnel_check_pmtu(skb, &rt->dst,
- GENEVE_IPV4_HLEN + info->options_len, false);
+ err = skb_tunnel_check_pmtu(skb, &rt->dst,
+ GENEVE_IPV4_HLEN + info->options_len,
+ netif_is_any_bridge_port(dev));
+ if (err < 0) {
+ dst_release(&rt->dst);
+ return err;
+ } else if (err) {
+ struct ip_tunnel_info *info;
+
+ info = skb_tunnel_info(skb);
+ if (info) {
+ info->key.u.ipv4.dst = fl4.saddr;
+ info->key.u.ipv4.src = fl4.daddr;
+ }
+
+ if (!pskb_may_pull(skb, ETH_HLEN)) {
+ dst_release(&rt->dst);
+ return -EINVAL;
+ }
+
+ skb->protocol = eth_type_trans(skb, geneve->dev);
+ netif_rx(skb);
+ dst_release(&rt->dst);
+ return -EMSGSIZE;
+ }
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
if (geneve->cfg.collect_md) {
if (IS_ERR(dst))
return PTR_ERR(dst);
- skb_tunnel_check_pmtu(skb, dst, GENEVE_IPV6_HLEN + info->options_len,
- false);
+ err = skb_tunnel_check_pmtu(skb, dst,
+ GENEVE_IPV6_HLEN + info->options_len,
+ netif_is_any_bridge_port(dev));
+ if (err < 0) {
+ dst_release(dst);
+ return err;
+ } else if (err) {
+ struct ip_tunnel_info *info = skb_tunnel_info(skb);
+
+ if (info) {
+ info->key.u.ipv6.dst = fl6.saddr;
+ info->key.u.ipv6.src = fl6.daddr;
+ }
+
+ if (!pskb_may_pull(skb, ETH_HLEN)) {
+ dst_release(dst);
+ return -EINVAL;
+ }
+
+ skb->protocol = eth_type_trans(skb, geneve->dev);
+ netif_rx(skb);
+ dst_release(dst);
+ return -EMSGSIZE;
+ }
sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
if (geneve->cfg.collect_md) {
if (likely(!err))
return NETDEV_TX_OK;
- dev_kfree_skb(skb);
+ if (err != -EMSGSIZE)
+ dev_kfree_skb(skb);
if (err == -ELOOP)
dev->stats.collisions++;