#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <sstream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <numeric>
#include <cctype>
#include <tuple>
#include <array>
#include <climits>
#include <bitset>
#include <cassert>
#include <unordered_map>
#include <complex>

#ifdef _MSC_VER
#include <agents.h>
#endif

#define FOR(i, a, b) for(int i = (a); i < (int)(b); ++i)
#define rep(i, n) FOR(i, 0, n)
#define ALL(v) v.begin(), v.end()
#define REV(v) v.rbegin(), v.rend()
#define MEMSET(v, s) memset(v, s, sizeof(v))
#define UNIQUE(v) (v).erase(unique(ALL(v)), (v).end())
#define MP make_pair
#define MT make_tuple

using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> P;

struct Value{
	ll value, sum, size;

	Value(){
		value = sum = size = 0;
	}
	Value(ll x){
		value = 0;
		sum = x;
		size = 1;
	}
};

Value operator *(const Value &lhs, const Value &rhs){
	Value res;
	res.sum = lhs.sum + rhs.sum;
	res.value = lhs.value + rhs.value + lhs.sum * rhs.size;
	res.size = lhs.size + rhs.size;
	return res;
}

Value operator +(const Value &lhs, const Value &rhs){
	Value res;
	res.size = 1;
	res.value = lhs.value + rhs.value;
	res.sum = lhs.sum + rhs.sum;
	return res;
}

struct SegTree{
	vector<Value> dat;
	int n;

	SegTree(int _n){
		n = 1;
		while (n < _n) n *= 2;
		dat.resize(2 * n);
	}

	void update(int i, Value x){
		i += n - 1;
		dat[i] = x;
		while (i){
			i = (i - 1) / 2;
			dat[i] = dat[i * 2 + 1] * dat[i * 2 + 2];
		}
	}
	void add(int i, Value x){
		i += n - 1;
		dat[i] = dat[i] + x;
		while (i){
			i = (i - 1) / 2;
			dat[i] = dat[i * 2 + 1] * dat[i * 2 + 2];
		}
	}

	Value query(int a, int b){
		return query(a, b, 0, 0, n);
	}

	Value query(int a, int b, int i, int l, int r){
		if (b <= l || r <= a) return Value();
		if (a <= l && r <= b){ return dat[i]; }
		int chl = i * 2 + 1, chr = i * 2 + 2, mid = (l + r) / 2;
		auto left = query(a, b, chl, l, mid);
		auto right = query(a, b, chr, mid, r);
		return left*right;
	}
};

struct heavy_light_decomposition{
	struct node{
		int chainid, index;
	};
	struct chain{
		int parchain, parnode, depth, length;
	};

	int n;
	vector<node> nodes;
	vector<chain> chains;
	vector<int> size, par;
	vector<vector<int>> G;

	heavy_light_decomposition(int _n):n(_n){
		G.resize(n);
		size.resize(n);
		par.resize(n);
	}
	void add_edge(int a, int b){
		G[a].emplace_back(b);
		G[b].emplace_back(a);
	}

	void build(int root = 0){
		stack<int> in, out;
		in.push(root);
		par[root] = -1;
		// set parent
		while (!in.empty()){
			int v = in.top(); in.pop();
			out.push(v);
			for (auto &e : G[v]){
				if (e == par[v]) continue;
				par[e] = v;
				in.push(e);
			}
		}
		// calculate size
		while (!out.empty()){
			int v = out.top(); out.pop();
			size[v] = 1;
			for (auto &e : G[v]){
				if (e == par[v]) continue;
				size[v] += size[e];
			}
		}
		decomposition(root);
	}

	void decomposition(int root){
		nodes.assign(n, { -1, -1 });
		stack<int> in;
		in.push(root);
		while (!in.empty()){
			int v = in.top(); in.pop();
			int &cid = nodes[v].chainid;
			if (cid < 0){
				int pid = par[v];
				int pcid = pid < 0 ? -1 : nodes[par[v]].chainid;
				cid = chains.size();
				chains.push_back({ pcid, pid, pcid < 0 ? 0 : chains[pcid].depth + 1, 0 });
			}
			nodes[v].index = chains[cid].length++;

			pair<int, int> heavy(-1, -1);
			for (auto &e : G[v]){
				if (e == par[v]) continue;
				heavy = max(heavy, make_pair(size[e], e));
			}
			if (heavy.first < 0) continue;
			for (auto &e : G[v]){
				if (e == par[v]) continue;
				if (heavy.second == e) nodes[e].chainid = cid;
				in.push(e);
			}
		}
	}

	int chain(int v){
		return nodes[v].chainid;
	}

	int lca(int u, int v){
		while (chain(u) != chain(v)){
			int &x = (chains[chain(u)].depth > chains[chain(v)].depth ? u : v);
			x = chains[chain(x)].parnode;
		}
		return nodes[u].index < nodes[v].index ? u : v;
	}

	struct path{
		int chainid, left, right;
	};

	// v -> ancestor
	vector<path> get_path(int v, int ancestor){
		int ca = chain(ancestor);
		vector<path> res;
		while (chain(v) != ca){
			res.push_back({ chain(v), 0, nodes[v].index + 1 });
			v = chains[chain(v)].parnode;
		}
		if (v != ancestor) res.push_back({ ca, nodes[ancestor].index + 1, nodes[v].index + 1 });
		return res;
	}
};

struct HLD_SegTree{
	heavy_light_decomposition hld;
	vector<SegTree> segs;

	HLD_SegTree(int n) : hld(n){}

	void add_edge(int a, int b){
		hld.add_edge(a, b);
	}

	void build(vector<Value> value, int root = 0){
		hld.build(root);
		auto &nodes = hld.nodes;
		auto &chains = hld.chains;
		for(auto chain : chains){
			segs.push_back(SegTree(chain.length));
		}
		int n = value.size();
		for (int i = 0; i < n; ++i){
			auto &node = nodes[i];
			segs[node.chainid].update(node.index, value[i]);
		}
	}

	void add(int i, Value x){
		auto &node = hld.nodes[i];
		segs[node.chainid].add(node.index, x);
	}

	Value query(vector<heavy_light_decomposition::path> &paths){
		reverse(ALL(paths));
		auto res = Value();
		for (auto path : paths){
			res = res * segs[path.chainid].query(path.left, path.right);
		}
		return res;
	}

	ll query(int u, int v, int root = 0){
		int lca = hld.lca(u, v);
		auto p1 = hld.get_path(u, lca);
		auto p2 = hld.get_path(v, lca);
		auto p3 = hld.get_path(lca, root);
		auto q1 = query(p1);
		auto q2 = query(p2);
		auto q3 = query(p3);
		return q1.value + q2.value + q3.sum * (q1.size + q2.size);
	}
};

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(20);

	int n, q;
	cin >> n >> q;

	HLD_SegTree seg(n + 1);

	rep(i, n - 1){
		int a, b;
		cin >> a >> b;
		seg.add_edge(a, b);
	}

	seg.add_edge(n, 0);

	vector<Value> v(n + 1, Value(0));
	seg.build(v, n);

	while (q--){
		int t, u, v;
		cin >> t >> u >> v;

		if (t){
			seg.add(u, Value(v));
		}
		else{
			cout <<  seg.query(u, v, n) << '\n';
		}
	}
}

Measured memory_bytes: 77152