--- libnl-3.2.25/lib/route/link/ip6tnl.c	2014-07-01 12:32:53.000000000 +0200
+++ src/lib/route/link/ip6tnl.c	2015-10-01 20:28:40.316659364 +0200
@@ -42,6 +42,15 @@
 #define IP6_TNL_ATTR_PROTO         (1 << 7)
 #define IP6_TNL_ATTR_FLOWINFO      (1 << 8)
 
+struct ip6_tnl_fmr {
+	struct in6_addr		ip6;
+	struct in_addr		ip4;
+	uint8_t			ip6_plen;
+	uint8_t			ip4_plen;
+	uint8_t			ea_bits;
+	uint8_t			psid_offset;
+};
+
 struct ip6_tnl_info
 {
 	uint8_t                 ttl;
@@ -54,6 +63,9 @@
 	struct in6_addr         local;
 	struct in6_addr         remote;
 	uint32_t                ip6_tnl_mask;
+
+	struct ip6_tnl_fmr	fmrs[4];
+	unsigned int		fmr_count;
 };
 
 static struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
@@ -68,6 +80,16 @@
 	[IFLA_IPTUN_PROTO]        = { .type = NLA_U8 },
+	[IFLA_IPTUN_FMRS]         = { .type = NLA_NESTED },
 };
 
+static struct nla_policy ip6_fmr_policy[IFLA_IPTUN_FMR_MAX + 1] = {
+	[IFLA_IPTUN_FMR_IP6_PREFIX]	= { .minlen = sizeof(struct in6_addr) },
+	[IFLA_IPTUN_FMR_IP4_PREFIX]	= { .type = NLA_U32 },
+	[IFLA_IPTUN_FMR_IP6_PREFIX_LEN]	= { .type = NLA_U8 },
+	[IFLA_IPTUN_FMR_IP4_PREFIX_LEN]	= { .type = NLA_U8 },
+	[IFLA_IPTUN_FMR_EA_LEN]		= { .type = NLA_U8 },
+	[IFLA_IPTUN_FMR_OFFSET]		= { .type = NLA_U8 },
+};
+
 static int ip6_tnl_alloc(struct rtnl_link *link)
 {
 	struct ip6_tnl_info *ip6_tnl;
@@ -145,6 +166,53 @@
 		ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
 	}
 
+	if (tb[IFLA_IPTUN_FMRS]) {
+		struct nlattr *ltb[4];
+		size_t i;
+
+		memset(ltb, 0, sizeof (*ltb));
+		err = nla_parse_nested(ltb, 4, tb[IFLA_IPTUN_FMRS], NULL);
+		if (err < 0)
+			goto errout;
+
+		for (i = 1; i < 4; i++) {
+			struct nlattr *lltb[IFLA_IPTUN_FMR_MAX + 1];
+			struct ip6_tnl_fmr *fmr;
+
+			if (!ltb[i])
+				break;
+
+			err = nla_parse_nested(lltb, IFLA_IPTUN_FMR_MAX, ltb[i],
+					       ip6_fmr_policy);
+
+			if (err < 0)
+				goto errout;
+			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])
+				break;
+
+			fmr = &ip6_tnl->fmrs[i - 1];
+
+			nla_memcpy(&fmr->ip6, lltb[IFLA_IPTUN_FMR_IP6_PREFIX],
+				   sizeof(struct in6_addr));
+
+			nla_memcpy(&fmr->ip4, lltb[IFLA_IPTUN_FMR_IP4_PREFIX],
+				   sizeof(struct in_addr));
+
+			fmr->ip6_plen = nla_get_u8(lltb[IFLA_IPTUN_FMR_IP6_PREFIX_LEN]);
+
+			fmr->ip4_plen = nla_get_u8(lltb[IFLA_IPTUN_FMR_IP4_PREFIX_LEN]);
+
+			fmr->ea_bits = nla_get_u8(lltb[IFLA_IPTUN_FMR_EA_LEN]);
+			fmr->psid_offset = nla_get_u8(lltb[IFLA_IPTUN_FMR_OFFSET]);
+			ip6_tnl->fmr_count++;
+		}
+	}
+
 	err = 0;
 
 errout:
@@ -190,6 +250,36 @@
 	else
 		NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, 0);
 
+	if (ip6_tnl->fmr_count) {
+		struct nlattr *fdata;
+		size_t i;
+
+		fdata = nla_nest_start(msg, IFLA_IPTUN_FMRS);
+
+		for (i = 0; i < ip6_tnl->fmr_count; i++) {
+			const struct ip6_tnl_fmr *fmr = &ip6_tnl->fmrs[i];
+			struct nlattr *ffdata;
+
+			ffdata = nla_nest_start(msg, i + 1);
+			NLA_PUT(msg, IFLA_IPTUN_FMR_IP6_PREFIX,
+				sizeof(struct in6_addr), &fmr->ip6);
+			NLA_PUT(msg, IFLA_IPTUN_FMR_IP4_PREFIX,
+				sizeof(struct in_addr), &fmr->ip4);
+
+			NLA_PUT_U8(msg, IFLA_IPTUN_FMR_IP6_PREFIX_LEN,
+				   fmr->ip6_plen);
+			NLA_PUT_U8(msg, IFLA_IPTUN_FMR_IP4_PREFIX_LEN,
+				   fmr->ip4_plen);
+			NLA_PUT_U8(msg, IFLA_IPTUN_FMR_EA_LEN,
+				   fmr->ea_bits);
+			NLA_PUT_U8(msg, IFLA_IPTUN_FMR_OFFSET,
+				   fmr->psid_offset);
+
+			nla_nest_end(msg, ffdata);
+		}
+		nla_nest_end(msg, fdata);
+	}
+
 	nla_nest_end(msg, data);
 
 nla_put_failure:
@@ -677,6 +767,30 @@
 	return ip6_tnl->proto;
 }
 
+int rtnl_link_ip6_tnl_add_fmr(struct rtnl_link *link,
+			      const struct in6_addr *ip6,
+			      const struct in_addr *ip4,
+			      unsigned int ip6_plen,
+			      unsigned int ip4_plen,
+			      unsigned int ea_bits,
+			      unsigned int psid_offset)
+{
+	struct ip6_tnl_info *ip6_tnl = link->l_info;
+	struct ip6_tnl_fmr *fmr;
+
+	IS_IP6_TNL_LINK_ASSERT(link);
+
+	fmr = &ip6_tnl->fmrs[ip6_tnl->fmr_count++];
+	memcpy(&fmr->ip6, ip6, sizeof(struct in6_addr));
+	memcpy(&fmr->ip4, ip4, sizeof(struct in_addr));
+	fmr->ip6_plen = ip6_plen;
+	fmr->ip4_plen = ip4_plen;
+	fmr->ea_bits = ea_bits;
+	fmr->psid_offset = psid_offset;
+
+	return 0;
+}
+
 static void __init ip6_tnl_init(void)
 {
 	rtnl_link_register_info(&ip6_tnl_info_ops);
--- libnl-3.2.25/include/linux/if_tunnel.h	2014-06-16 16:45:51.000000000 +0200
+++ src/include/linux/if_tunnel.h	2015-10-01 19:59:41.822961308 +0200
@@ -1,5 +1,5 @@
-#ifndef _UAPI_IF_TUNNEL_H_
-#define _UAPI_IF_TUNNEL_H_
+#ifndef _IF_TUNNEL_H_
+#define _IF_TUNNEL_H_
 
 #include <linux/types.h>
 #include <asm/byteorder.h>
@@ -53,10 +53,37 @@
 	IFLA_IPTUN_6RD_RELAY_PREFIX,
 	IFLA_IPTUN_6RD_PREFIXLEN,
 	IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
+	IFLA_IPTUN_ENCAP_TYPE,
+	IFLA_IPTUN_ENCAP_FLAGS,
+	IFLA_IPTUN_ENCAP_SPORT,
+	IFLA_IPTUN_ENCAP_DPORT,
+	IFLA_IPTUN_FMRS,
 	__IFLA_IPTUN_MAX,
 };
 #define IFLA_IPTUN_MAX	(__IFLA_IPTUN_MAX - 1)
 
+enum {
+	IFLA_IPTUN_FMR_UNSPEC,
+	IFLA_IPTUN_FMR_IP6_PREFIX,
+	IFLA_IPTUN_FMR_IP4_PREFIX,
+	IFLA_IPTUN_FMR_IP6_PREFIX_LEN,
+	IFLA_IPTUN_FMR_IP4_PREFIX_LEN,
+	IFLA_IPTUN_FMR_EA_LEN,
+	IFLA_IPTUN_FMR_OFFSET,
+	__IFLA_IPTUN_FMR_MAX,
+};
+#define IFLA_IPTUN_FMR_MAX (__IFLA_IPTUN_FMR_MAX - 1)
+
+enum tunnel_encap_types {
+	TUNNEL_ENCAP_NONE,
+	TUNNEL_ENCAP_FOU,
+	TUNNEL_ENCAP_GUE,
+};
+
+#define TUNNEL_ENCAP_FLAG_CSUM		(1<<0)
+#define TUNNEL_ENCAP_FLAG_CSUM6		(1<<1)
+#define TUNNEL_ENCAP_FLAG_REMCSUM	(1<<2)
+
 /* SIT-mode i_flags */
 #define	SIT_ISATAP	0x0001
 
@@ -94,13 +121,17 @@
 	IFLA_GRE_ENCAP_LIMIT,
 	IFLA_GRE_FLOWINFO,
 	IFLA_GRE_FLAGS,
+	IFLA_GRE_ENCAP_TYPE,
+	IFLA_GRE_ENCAP_FLAGS,
+	IFLA_GRE_ENCAP_SPORT,
+	IFLA_GRE_ENCAP_DPORT,
 	__IFLA_GRE_MAX,
 };
 
 #define IFLA_GRE_MAX	(__IFLA_GRE_MAX - 1)
 
 /* VTI-mode i_flags */
-#define VTI_ISVTI 0x0001
+#define VTI_ISVTI ((__be16)0x0001)
 
 enum {
 	IFLA_VTI_UNSPEC,
@@ -113,4 +144,4 @@
 };
 
 #define IFLA_VTI_MAX	(__IFLA_VTI_MAX - 1)
-#endif /* _UAPI_IF_TUNNEL_H_ */
+#endif /* _IF_TUNNEL_H_ */
--- libnl-3.2.25/include/netlink/route/link/ip6tnl.h	2014-07-01 12:32:52.000000000 +0200
+++ src/include/netlink/route/link/ip6tnl.h	2015-10-01 20:44:46.504210752 +0200
@@ -49,6 +49,13 @@
 	extern int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto);
 	extern uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link);
 
+	extern int rtnl_link_ip6_tnl_add_fmr(struct rtnl_link *link,
+					     const struct in6_addr *ip6,
+					     const struct in_addr *ip4,
+					     unsigned int ip6_plen,
+					     unsigned int ip4_plen,
+					     unsigned int ea_bits,
+					     unsigned int psid_offset);
 #ifdef _cplusplus
 }
 #endif
