return x0;
 }
 
+static int
+__xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n)
+{
+       int i;
+       int j = 0;
+
+       /* Rule 1: select IPsec transport except AH */
+       for (i = 0; i < n; i++) {
+               if (src[i]->props.mode == XFRM_MODE_TRANSPORT &&
+                   src[i]->id.proto != IPPROTO_AH) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+       if (j == n)
+               goto end;
+
+       /* XXX: Rule 2: select MIPv6 RO or inbound trigger */
+
+       /* Rule 3: select IPsec transport AH */
+       for (i = 0; i < n; i++) {
+               if (src[i] &&
+                   src[i]->props.mode == XFRM_MODE_TRANSPORT &&
+                   src[i]->id.proto == IPPROTO_AH) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+       if (j == n)
+               goto end;
+
+       /* Rule 4: select IPsec tunnel */
+       for (i = 0; i < n; i++) {
+               if (src[i] &&
+                   src[i]->props.mode == XFRM_MODE_TUNNEL) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+       if (likely(j == n))
+               goto end;
+
+       /* Final rule */
+       for (i = 0; i < n; i++) {
+               if (src[i]) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+
+ end:
+       return 0;
+}
+
+static int
+__xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n)
+{
+       int i;
+       int j = 0;
+
+       /* Rule 1: select IPsec transport */
+       for (i = 0; i < n; i++) {
+               if (src[i]->mode == XFRM_MODE_TRANSPORT) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+       if (j == n)
+               goto end;
+
+       /* XXX: Rule 2: select MIPv6 RO or inbound trigger */
+
+       /* Rule 3: select IPsec tunnel */
+       for (i = 0; i < n; i++) {
+               if (src[i] &&
+                   src[i]->mode == XFRM_MODE_TUNNEL) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+       if (likely(j == n))
+               goto end;
+
+       /* Final rule */
+       for (i = 0; i < n; i++) {
+               if (src[i]) {
+                       dst[j++] = src[i];
+                       src[i] = NULL;
+               }
+       }
+
+ end:
+       return 0;
+}
+
 static struct xfrm_state_afinfo xfrm6_state_afinfo = {
        .family                 = AF_INET6,
        .init_tempsel           = __xfrm6_init_tempsel,
        .state_lookup           = __xfrm6_state_lookup,
        .state_lookup_byaddr    = __xfrm6_state_lookup_byaddr,
        .find_acq               = __xfrm6_find_acq,
+       .tmpl_sort              = __xfrm6_tmpl_sort,
+       .state_sort             = __xfrm6_state_sort,
 };
 
 void __init xfrm6_state_init(void)