diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 8475913f2070..d2acb63d1e5d 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -62,6 +62,52 @@ static int tcf_connmark_act(struct sk_buff *skb, const struct tc_action *a,
 
 	c = nf_ct_get(skb, &ctinfo);
 	if (c) {
+		if (getdscp & proto) {
+			if (!(c->mark & 0x01000000)) {
+			/* store the DSCP bits into c->mark */
+				switch (proto) {
+				case NFPROTO_IPV4:
+					dscp = ipv4_get_dsfield(ip_hdr(skb));
+					break;
+				case NFPROTO_IPV6:
+					dscp = ipv6_get_dsfield(ip_hdr(skb));
+					break;
+				default:
+					dscp = 0;
+					break;
+				}
+				c->mark &= 0x00ffffff;
+				c->mark |= (0x01 | dscp) << 24;
+			}
+			if (bleach) {
+				switch (proto) {
+				case NFPROTO_IPV4:
+					if (ipv4_get_dsfield(ip_hdr(skb) & ~INET_ECN_MASK)
+						ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, 0);
+					break;
+				case NFPROTO_IPV6:
+					if (ipv6_get_dsfield(ip_hdr(skb) & ~INET_ECN_MASK)
+						ipv6_change_dsfield(ip_hdr(skb), INET_ECN_MASK, 0);
+					break;
+				default:
+					break;
+				}
+			}
+		} else if (setdscp & proto && (c->mark & 0x01000000)) {
+			/* restore the DSCP bits from c->mark into diffserv */
+			switch (proto) {
+			case NFPROTO_IPV4:
+				if (ipv4_get_dsfield(ip_hdr(skb) & ~INET_ECN_MASK) != c->mark >> 24 & ~INET_ECN_MASK)
+					ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, c->mark >> 24 & ~INET_ECN_MASK);
+				break;
+			case NFPROTO_IPV6:
+				if (ipv6_get_dsfield(ip_hdr(skb) & ~INET_ECN_MASK) != c->mark >> 24 & ~INET_ECN_MASK)
+					ipv6_change_dsfield(ip_hdr(skb), INET_ECN_MASK, c->mark >> 24 & ~INET_ECN_MASK);
+				break;
+			default:
+				break;
+			}
+		}
 		skb->mark = c->mark;
 		/* using overlimits stats to count how many packets marked */
 		ca->tcf_qstats.overlimits++;
