kernel-pfkey: Update priority calculation formula to the new one in kernel-netlink
authorTobias Brunner <tobias@strongswan.org>
Mon, 11 Apr 2016 09:19:26 +0000 (11:19 +0200)
committerTobias Brunner <tobias@strongswan.org>
Fri, 15 Apr 2016 08:39:00 +0000 (10:39 +0200)
Since the selectors are not exactly the same (no port masks, no interface)
some small tweaks have been applied.

src/libcharon/plugins/kernel_pfkey/kernel_pfkey_ipsec.c

index 7eb6c58..8de33d3 100644 (file)
 #define SOL_UDP IPPROTO_UDP
 #endif
 
-/** base priority for installed policies */
-#define PRIO_BASE 384
+/** Base priority for installed policies */
+#define PRIO_BASE 100000
 
 #ifdef __APPLE__
 /** from xnu/bsd/net/pfkeyv2.h */
@@ -590,33 +590,44 @@ static inline bool policy_entry_match_byindex(policy_entry_t *current,
 
 /**
  * Calculate the priority of a policy
+ *
+ * This is the same formula we use in the kernel-netlink interface, but some
+ * features are currently not or only partially supported by PF_KEY.
+ *
+ * bits 0-0:  reserved for interface restriction (0..1)     1 bit
+ * bits 1-6:  src + dst port mask bits (2 * 0..16)          6 bits
+ * bits 7-7:  restriction to protocol (0..1)                1 bit
+ * bits 8-16: src + dst network mask bits (2 * 0..128)      9 bits
+ *                                                         17 bits
+ *
+ * smallest value: 000000000 0 000000 0:      0, lowest priority = 100'000
+ * largest value : 100000000 1 100000 0: 65'728, highst priority =  34'272
  */
 static inline uint32_t get_priority(policy_entry_t *policy,
                                                                         policy_priority_t prio)
 {
        uint32_t priority = PRIO_BASE;
+
        switch (prio)
        {
                case POLICY_PRIORITY_FALLBACK:
-                       priority <<= 1;
+                       priority += PRIO_BASE;
                        /* fall-through */
                case POLICY_PRIORITY_ROUTED:
-                       priority <<= 1;
+                       priority += PRIO_BASE;
                        /* fall-through */
                case POLICY_PRIORITY_DEFAULT:
-                       priority <<= 1;
-                       /* fall-trough */
+                       priority += PRIO_BASE;
+                       /* fall-through */
                case POLICY_PRIORITY_PASS:
                        break;
        }
-       /* calculate priority based on selector size, small size = high prio */
-       priority -= policy->src.mask;
-       priority -= policy->dst.mask;
-       priority <<= 2; /* make some room for the two flags */
-       priority += policy->src.net->get_port(policy->src.net) ||
-                               policy->dst.net->get_port(policy->dst.net) ?
-                               0 : 2;
-       priority += policy->src.proto != IPSEC_PROTO_ANY ? 0 : 1;
+
+       /* calculate priority */
+       priority -= (policy->src.mask + policy->dst.mask) * 256;
+       priority -=  policy->src.proto != IPSEC_PROTO_ANY ? 128 : 0;
+       priority -= policy->src.net->get_port(policy->src.net) ? 32 : 0;
+       priority -= policy->dst.net->get_port(policy->dst.net) ? 32 : 0;
        return priority;
 }