diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 8fd715f806a27f327051d48a8e6b4ab8656c9703..cf45c4468caa51037e2bd5edbeed7266b7108745 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -182,6 +182,7 @@ enum {
 	TCA_U32_MARK,
 	TCA_U32_FLAGS,
 	TCA_U32_PAD,
+	TCA_U32_EXTMARK,
 	__TCA_U32_MAX
 };
 
diff --git a/net/sched/Kconfig b/net/sched/Kconfig
index 87956a768d1b7f829876ea64614d3a2ab8efe6ea..a970e65ebb6e620b218db8c3047ec43d63cc84ea 100644
--- a/net/sched/Kconfig
+++ b/net/sched/Kconfig
@@ -423,6 +423,12 @@ config CLS_U32_MARK
 	---help---
 	  Say Y here to be able to use netfilter marks as u32 key.
 
+config CLS_U32_EXTMARK
+	bool "Netfilter extended marks support"
+	depends on NET_CLS_U32
+	---help---
+	  Say Y here to be able to use netfilter marks as u32 key.
+
 config NET_CLS_RSVP
 	tristate "IPv4 Resource Reservation Protocol (RSVP)"
 	select NET_CLS
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index ae83c3aec3082d3c4a1714c909f817835925a546..f1b770d2fba4d0e1a5750f23815a3b5d99caa5ac 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -64,6 +64,9 @@ struct tc_u_knode {
 	u32			val;
 	u32			mask;
 	u32 __percpu		*pcpu_success;
+#endif
+#ifdef CONFIG_CLS_U32_EXTMARK
+	struct tc_u32_mark      extmark;
 #endif
 	struct tcf_proto	*tp;
 	struct rcu_head		rcu;
@@ -148,6 +151,14 @@ next_knode:
 			__this_cpu_inc(*n->pcpu_success);
 		}
 #endif
+#ifdef CONFIG_CLS_U32_EXTMARK
+		if ((skb->extmark & n->extmark.mask) != n->extmark.val) {
+			n = n->next;
+			goto next_knode;
+		} else {
+			n->extmark.success++;
+		}
+#endif
 
 		for (i = n->sel.nkeys; i > 0; i--, key++) {
 			int toff = off + key->off + (off2 & key->offmask);
@@ -697,6 +708,9 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
 	[TCA_U32_SEL]		= { .len = sizeof(struct tc_u32_sel) },
 	[TCA_U32_INDEV]		= { .type = NLA_STRING, .len = IFNAMSIZ },
 	[TCA_U32_MARK]		= { .len = sizeof(struct tc_u32_mark) },
+#ifdef CONFIG_CLS_U32_EXTMARK
+	[TCA_U32_EXTMARK]	= { .len = sizeof(struct tc_u32_mark) },
+#endif
 	[TCA_U32_FLAGS]		= { .type = NLA_U32 },
 };
 
@@ -1005,6 +1019,15 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
 		n->mask = mark->mask;
 	}
 #endif
+#ifdef CONFIG_CLS_U32_EXTMARK
+	if (tb[TCA_U32_EXTMARK]) {
+		struct tc_u32_mark *extmark;
+
+		extmark = nla_data(tb[TCA_U32_EXTMARK]);
+		memcpy(&n->extmark, extmark, sizeof(struct tc_u32_mark));
+		n->extmark.success = 0;
+	}
+#endif
 
 	err = u32_set_parms(net, tp, base, ht, n, tb, tca[TCA_RATE], ovr);
 	if (err == 0) {
@@ -1149,6 +1172,12 @@ static int u32_dump(struct net *net, struct tcf_proto *tp, unsigned long fh,
 				goto nla_put_failure;
 		}
 #endif
+#ifdef CONFIG_CLS_U32_EXTMARK
+		if ((n->extmark.val || n->extmark.mask) &&
+			nla_put(skb, TCA_U32_EXTMARK,
+				sizeof(n->extmark), &n->extmark))
+			goto nla_put_failure;
+#endif
 
 		if (tcf_exts_dump(skb, &n->exts) < 0)
 			goto nla_put_failure;