[NET] rules: Protocol independant mark selector

Move mark selector currently implemented per protocol into
the protocol independant part.

Signed-off-by: Thomas Graf <tgraf@suug.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 6b0e63c..da91bf2 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -119,6 +119,9 @@
 		if (rule->ifindex && (rule->ifindex != fl->iif))
 			continue;
 
+		if ((rule->mark ^ fl->mark) & rule->mark_mask)
+			continue;
+
 		if (!ops->match(rule, fl, flags))
 			continue;
 
@@ -179,6 +182,18 @@
 			rule->ifindex = dev->ifindex;
 	}
 
+	if (tb[FRA_FWMARK]) {
+		rule->mark = nla_get_u32(tb[FRA_FWMARK]);
+		if (rule->mark)
+			/* compatibility: if the mark value is non-zero all bits
+			 * are compared unless a mask is explicitly specified.
+			 */
+			rule->mark_mask = 0xFFFFFFFF;
+	}
+
+	if (tb[FRA_FWMASK])
+		rule->mark_mask = nla_get_u32(tb[FRA_FWMASK]);
+
 	rule->action = frh->action;
 	rule->flags = frh->flags;
 	rule->table = frh_get_table(frh, tb);
@@ -250,6 +265,14 @@
 		    nla_strcmp(tb[FRA_IFNAME], rule->ifname))
 			continue;
 
+		if (tb[FRA_FWMARK] &&
+		    (rule->mark != nla_get_u32(tb[FRA_FWMARK])))
+			continue;
+
+		if (tb[FRA_FWMASK] &&
+		    (rule->mark_mask != nla_get_u32(tb[FRA_FWMASK])))
+			continue;
+
 		if (!ops->compare(rule, frh, tb))
 			continue;
 
@@ -298,6 +321,12 @@
 	if (rule->pref)
 		NLA_PUT_U32(skb, FRA_PRIORITY, rule->pref);
 
+	if (rule->mark)
+		NLA_PUT_U32(skb, FRA_FWMARK, rule->mark);
+
+	if (rule->mark_mask || rule->mark)
+		NLA_PUT_U32(skb, FRA_FWMASK, rule->mark_mask);
+
 	if (ops->fill(rule, skb, nlh, frh) < 0)
 		goto nla_put_failure;