--- iproute2-5.3.0/ip/link_ip6tnl.c	2019-09-24 21:32:05.000000000 +0200
+++ src/ip/link_ip6tnl.c	2019-10-22 16:01:55.657894287 +0200
@@ -45,6 +45,7 @@
 		"			[ fwmark MARK ]\n"
 		"			[ external ]\n"
 		"			[ noencap ]\n"
+		"			[ fmr IP6_PREFIX IP4_PREFIX EA_BITS PSID_OFFSET ]\n"
 		"			[ encap { fou | gue | none } ]\n"
 		"			[ encap-sport PORT ]\n"
 		"			[ encap-dport PORT ]\n"
@@ -296,6 +297,47 @@
 			encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM;
 		} else if (strcmp(*argv, "external") == 0) {
 			metadata = 1;
+		} else if (strcmp(*argv, "fmr") == 0) {
+			inet_prefix addr;
+			struct rtattr *fmrs, *fmr;
+			__u8 ip6_plen, ip4_plen;
+			__u8 ea_len, psid_offset;
+			struct in6_addr ip6;
+			struct in_addr ip4;
+
+			NEXT_ARG();
+
+			get_prefix(&addr, *argv, AF_INET6);
+			if (addr.family != AF_INET6)
+				invarg("\"ip6_prefix\" address family is AF_UNSPEC", *argv);
+			memcpy(&ip6, addr.data, addr.bytelen);
+			ip6_plen = addr.bitlen;
+
+			NEXT_ARG();
+			get_prefix(&addr, *argv, AF_INET);
+			if (addr.family != AF_INET)
+				invarg("\"ip4_prefix\" address family is AF_UNSPEC", *argv);
+			memcpy(&ip4, addr.data, addr.bytelen);
+			ip4_plen = addr.bitlen;
+
+			NEXT_ARG();
+			if (get_u8(&ea_len, *argv, 10))
+				invarg("invalid ea_len", *argv);
+
+			NEXT_ARG();
+			if (get_u8(&psid_offset, *argv, 10))
+				invarg("invalid ea_len", *argv);
+
+			fmrs = addattr_nest(n, 1024, IFLA_IPTUN_FMRS);
+			fmr = addattr_nest(n, 1024, 1);
+			addattr_l(n, 1024, IFLA_IPTUN_FMR_IP6_PREFIX, &ip6, sizeof(ip6));
+			addattr_l(n, 1024, IFLA_IPTUN_FMR_IP4_PREFIX, &ip4, sizeof(ip4));
+			addattr8(n, 1024, IFLA_IPTUN_FMR_IP6_PREFIX_LEN, ip6_plen);
+			addattr8(n, 1024, IFLA_IPTUN_FMR_IP4_PREFIX_LEN, ip4_plen);
+			addattr8(n, 1024, IFLA_IPTUN_FMR_EA_LEN, ea_len);
+			addattr8(n, 1024, IFLA_IPTUN_FMR_OFFSET, psid_offset);
+			addattr_nest_end(n, fmr);
+			addattr_nest_end(n, fmrs);
 		} else {
 			ip6tunnel_print_help(lu, argc, argv, stderr);
 			return -1;
@@ -450,6 +492,46 @@
 		}
 	}
 
+	if (tb[IFLA_IPTUN_FMRS]) {
+		struct rtattr *ltb[16];
+		size_t i;
+
+		parse_rtattr_nested(ltb, 16, tb[IFLA_IPTUN_FMRS]);
+		for (i = 1; i < 16; i++) {
+			struct rtattr *lltb[IFLA_IPTUN_FMR_MAX + 1];
+
+			if (!ltb[i])
+				break;
+
+			parse_rtattr_nested(lltb, IFLA_IPTUN_FMR_MAX, ltb[i]);
+			if (!lltb[IFLA_IPTUN_FMR_IP6_PREFIX] ||
+			    !lltb[IFLA_IPTUN_FMR_IP4_PREFIX] ||
+			    !lltb[IFLA_IPTUN_FMR_IP4_PREFIX_LEN] ||
+			    !lltb[IFLA_IPTUN_FMR_IP6_PREFIX_LEN] ||
+			    !lltb[IFLA_IPTUN_FMR_EA_LEN] ||
+			    !lltb[IFLA_IPTUN_FMR_OFFSET])
+				continue;
+
+			fprintf(f, "fmr ");
+			fprintf(f, "%s/%u ",
+				rt_addr_n2a(AF_INET6,
+					    RTA_PAYLOAD(lltb[IFLA_IPTUN_FMR_IP6_PREFIX]),
+					    RTA_DATA(lltb[IFLA_IPTUN_FMR_IP6_PREFIX])),
+				rta_getattr_u8(lltb[IFLA_IPTUN_FMR_IP6_PREFIX_LEN]));
+
+			fprintf(f, "%s/%u ",
+				rt_addr_n2a(AF_INET,
+					    RTA_PAYLOAD(lltb[IFLA_IPTUN_FMR_IP4_PREFIX]),
+					    RTA_DATA(lltb[IFLA_IPTUN_FMR_IP4_PREFIX])),
+				rta_getattr_u8(lltb[IFLA_IPTUN_FMR_IP4_PREFIX_LEN]));
+
+			fprintf(f, "eabits %u ",
+				rta_getattr_u8(lltb[IFLA_IPTUN_FMR_EA_LEN]));
+			fprintf(f, "psid_offset %u ",
+				rta_getattr_u8(lltb[IFLA_IPTUN_FMR_OFFSET]));
+		}
+	}
+
 	tnl_print_encap(tb,
 			IFLA_IPTUN_ENCAP_TYPE,
 			IFLA_IPTUN_ENCAP_FLAGS,
