+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;
+}
+