]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/core/fib_rules.c
[NET] rules: Protocol independant mark selector
[mirror_ubuntu-bionic-kernel.git] / net / core / fib_rules.c
index 6b0e63cacd93347be11dcf085b2c3774ef4c2534..da91bf2e6151bcea2a6bf1d7afac04308a07f896 100644 (file)
@@ -119,6 +119,9 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
                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 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                        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 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
                    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 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
        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;