return -EOPNOTSUPP;
 }
 
+static void geneve_link_config(struct net_device *dev,
+                              struct ip_tunnel_info *info, struct nlattr *tb[])
+{
+       struct geneve_dev *geneve = netdev_priv(dev);
+       int ldev_mtu = 0;
+
+       if (tb[IFLA_MTU]) {
+               geneve_change_mtu(dev, nla_get_u32(tb[IFLA_MTU]));
+               return;
+       }
+
+       switch (ip_tunnel_info_af(info)) {
+       case AF_INET: {
+               struct flowi4 fl4 = { .daddr = info->key.u.ipv4.dst };
+               struct rtable *rt = ip_route_output_key(geneve->net, &fl4);
+
+               if (!IS_ERR(rt) && rt->dst.dev) {
+                       ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV4_HLEN;
+                       ip_rt_put(rt);
+               }
+               break;
+       }
+#if IS_ENABLED(CONFIG_IPV6)
+       case AF_INET6: {
+               struct rt6_info *rt = rt6_lookup(geneve->net,
+                                                &info->key.u.ipv6.dst, NULL, 0,
+                                                NULL, 0);
+
+               if (rt && rt->dst.dev)
+                       ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
+               ip6_rt_put(rt);
+               break;
+       }
+#endif
+       }
+
+       if (ldev_mtu <= 0)
+               return;
+
+       geneve_change_mtu(dev, ldev_mtu - info->options_len);
+}
+
 static int geneve_newlink(struct net *net, struct net_device *dev,
                          struct nlattr *tb[], struct nlattr *data[],
                          struct netlink_ext_ack *extack)
        if (err)
                return err;
 
-       return geneve_configure(net, dev, extack, &info, metadata,
-                               use_udp6_rx_checksums);
+       err = geneve_configure(net, dev, extack, &info, metadata,
+                              use_udp6_rx_checksums);
+       if (err)
+               return err;
+
+       geneve_link_config(dev, &info, tb);
+
+       return 0;
 }
 
 /* Quiesces the geneve device data path for both TX and RX.
        if (err)
                return err;
 
-       if (!geneve_dst_addr_equal(&geneve->info, &info))
+       if (!geneve_dst_addr_equal(&geneve->info, &info)) {
                dst_cache_reset(&info.dst_cache);
+               geneve_link_config(dev, &info, tb);
+       }
 
        geneve_quiesce(geneve, &gs4, &gs6);
        geneve->info = info;