From: Roopa Prabhu <ro...@cumulusnetworks.com>

Add support to match on src port, dst port and ip protocol.

Signed-off-by: Roopa Prabhu <ro...@cumulusnetworks.com>
---
 net/ipv6/fib6_rules.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 46 insertions(+), 3 deletions(-)

diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index b240f24..57c0836 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -28,13 +28,17 @@ struct fib6_rule {
        struct rt6key           src;
        struct rt6key           dst;
        u8                      tclass;
+       u8                      proto;
+       __be16                  sport;
+       __be16                  dport;
 };
 
 static bool fib6_rule_matchall(const struct fib_rule *rule)
 {
        struct fib6_rule *r = container_of(rule, struct fib6_rule, common);
 
-       if (r->dst.plen || r->src.plen || r->tclass)
+       if (r->dst.plen || r->src.plen || r->tclass || r->proto || r->sport ||
+           r->dport)
                return false;
        return fib_rule_matchall(rule);
 }
@@ -223,6 +227,15 @@ static int fib6_rule_match(struct fib_rule *rule, struct 
flowi *fl, int flags)
        if (r->tclass && r->tclass != ip6_tclass(fl6->flowlabel))
                return 0;
 
+       if (r->proto && r->proto != fl6->flowi6_proto)
+               return 0;
+
+       if (r->sport && r->sport != fl6->fl6_sport)
+               return 0;
+
+       if (r->dport && r->dport != fl6->fl6_dport)
+               return 0;
+
        return 1;
 }
 
@@ -258,6 +271,15 @@ static int fib6_rule_configure(struct fib_rule *rule, 
struct sk_buff *skb,
        rule6->dst.plen = frh->dst_len;
        rule6->tclass = frh->tos;
 
+       if (tb[FRA_PROTO])
+               rule6->proto = nla_get_u8(tb[FRA_PROTO]);
+
+       if (tb[FRA_SPORT])
+               rule6->sport = nla_get_be16(tb[FRA_SPORT]);
+
+       if (tb[FRA_DPORT])
+               rule6->dport = nla_get_be16(tb[FRA_DPORT]);
+
        net->ipv6.fib6_has_custom_rules = true;
        err = 0;
 errout:
@@ -286,6 +308,18 @@ static int fib6_rule_compare(struct fib_rule *rule, struct 
fib_rule_hdr *frh,
            nla_memcmp(tb[FRA_DST], &rule6->dst.addr, sizeof(struct in6_addr)))
                return 0;
 
+       if (tb[FRA_PROTO] &&
+           (rule6->proto != nla_get_u8(tb[FRA_PROTO])))
+               return 0;
+
+       if (tb[FRA_SPORT] &&
+           (rule6->sport != nla_get_be32(tb[FRA_SPORT])))
+               return 0;
+
+       if (tb[FRA_DPORT] &&
+           (rule6->dport != nla_get_be32(tb[FRA_DPORT])))
+               return 0;
+
        return 1;
 }
 
@@ -301,7 +335,13 @@ static int fib6_rule_fill(struct fib_rule *rule, struct 
sk_buff *skb,
        if ((rule6->dst.plen &&
             nla_put_in6_addr(skb, FRA_DST, &rule6->dst.addr)) ||
            (rule6->src.plen &&
-            nla_put_in6_addr(skb, FRA_SRC, &rule6->src.addr)))
+            nla_put_in6_addr(skb, FRA_SRC, &rule6->src.addr)) ||
+           (rule6->proto &&
+               nla_put_u8(skb, FRA_PROTO, rule6->proto)) ||
+           (rule6->sport &&
+               nla_put_be16(skb, FRA_SPORT, rule6->sport)) ||
+           (rule6->dport &&
+               nla_put_be16(skb, FRA_DPORT, rule6->dport)))
                goto nla_put_failure;
        return 0;
 
@@ -312,7 +352,10 @@ static int fib6_rule_fill(struct fib_rule *rule, struct 
sk_buff *skb,
 static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
 {
        return nla_total_size(16) /* dst */
-              + nla_total_size(16); /* src */
+              + nla_total_size(16) /* src */
+              + nla_total_size(1) /* proto */
+              + nla_total_size(2) /* sport */
+              + nla_total_size(2); /* dport */
 }
 
 static const struct fib_rules_ops __net_initconst fib6_rules_ops_template = {
-- 
2.1.4

Reply via email to