+clib_error_t *
+ipsec_add_del_sa_sess_cb (ipsec_main_t * im, u32 sa_index, u8 is_add)
+{
+ ipsec_ah_backend_t *ah =
+ pool_elt_at_index (im->ah_backends, im->ah_current_backend);
+ if (ah->add_del_sa_sess_cb)
+ {
+ clib_error_t *err = ah->add_del_sa_sess_cb (sa_index, is_add);
+ if (err)
+ return err;
+ }
+ ipsec_esp_backend_t *esp =
+ pool_elt_at_index (im->esp_backends, im->esp_current_backend);
+ if (esp->add_del_sa_sess_cb)
+ {
+ clib_error_t *err = esp->add_del_sa_sess_cb (sa_index, is_add);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+clib_error_t *
+ipsec_check_support_cb (ipsec_main_t * im, ipsec_sa_t * sa)
+{
+ clib_error_t *error = 0;
+ ipsec_ah_backend_t *ah =
+ pool_elt_at_index (im->ah_backends, im->ah_current_backend);
+ ASSERT (ah->check_support_cb);
+ error = ah->check_support_cb (sa);
+ if (error)
+ return error;
+ ipsec_esp_backend_t *esp =
+ pool_elt_at_index (im->esp_backends, im->esp_current_backend);
+ ASSERT (esp->check_support_cb);
+ error = esp->check_support_cb (sa);
+ return error;
+}
+
+
+static void
+ipsec_add_node (vlib_main_t * vm, const char *node_name,
+ const char *prev_node_name, u32 * out_node_index,
+ u32 * out_next_index)
+{
+ vlib_node_t *prev_node, *node;
+ prev_node = vlib_get_node_by_name (vm, (u8 *) prev_node_name);
+ ASSERT (prev_node);
+ node = vlib_get_node_by_name (vm, (u8 *) node_name);
+ ASSERT (node);
+ *out_node_index = node->index;
+ *out_next_index = vlib_node_add_next (vm, prev_node->index, node->index);
+}
+
+u32
+ipsec_register_ah_backend (vlib_main_t * vm, ipsec_main_t * im,
+ const char *name,
+ const char *ah4_encrypt_node_name,
+ const char *ah4_decrypt_node_name,
+ const char *ah6_encrypt_node_name,
+ const char *ah6_decrypt_node_name,
+ check_support_cb_t ah_check_support_cb,
+ add_del_sa_sess_cb_t ah_add_del_sa_sess_cb)
+{
+ ipsec_ah_backend_t *b;
+ pool_get (im->ah_backends, b);
+ b->name = format (NULL, "%s", name);
+
+ ipsec_add_node (vm, ah4_encrypt_node_name, "ipsec4-output",
+ &b->ah4_encrypt_node_index, &b->ah4_encrypt_next_index);
+ ipsec_add_node (vm, ah4_decrypt_node_name, "ipsec4-input",
+ &b->ah4_decrypt_node_index, &b->ah4_decrypt_next_index);
+ ipsec_add_node (vm, ah6_encrypt_node_name, "ipsec6-output",
+ &b->ah6_encrypt_node_index, &b->ah6_encrypt_next_index);
+ ipsec_add_node (vm, ah6_decrypt_node_name, "ipsec6-input",
+ &b->ah6_decrypt_node_index, &b->ah6_decrypt_next_index);
+
+ b->check_support_cb = ah_check_support_cb;
+ b->add_del_sa_sess_cb = ah_add_del_sa_sess_cb;
+ return b - im->ah_backends;
+}
+
+u32
+ipsec_register_esp_backend (vlib_main_t * vm, ipsec_main_t * im,
+ const char *name,
+ const char *esp4_encrypt_node_name,
+ const char *esp4_decrypt_node_name,
+ const char *esp6_encrypt_node_name,
+ const char *esp6_decrypt_node_name,
+ check_support_cb_t esp_check_support_cb,
+ add_del_sa_sess_cb_t esp_add_del_sa_sess_cb)
+{
+ ipsec_esp_backend_t *b;
+ pool_get (im->esp_backends, b);
+ b->name = format (NULL, "%s", name);
+
+ ipsec_add_node (vm, esp4_encrypt_node_name, "ipsec4-output",
+ &b->esp4_encrypt_node_index, &b->esp4_encrypt_next_index);
+ ipsec_add_node (vm, esp4_decrypt_node_name, "ipsec4-input",
+ &b->esp4_decrypt_node_index, &b->esp4_decrypt_next_index);
+ ipsec_add_node (vm, esp6_encrypt_node_name, "ipsec6-output",
+ &b->esp6_encrypt_node_index, &b->esp6_encrypt_next_index);
+ ipsec_add_node (vm, esp6_decrypt_node_name, "ipsec6-input",
+ &b->esp6_decrypt_node_index, &b->esp6_decrypt_next_index);
+
+ b->check_support_cb = esp_check_support_cb;
+ b->add_del_sa_sess_cb = esp_add_del_sa_sess_cb;
+ return b - im->esp_backends;
+}
+
+int
+ipsec_select_ah_backend (ipsec_main_t * im, u32 backend_idx)
+{
+ if (pool_elts (im->sad) > 0
+ || pool_is_free_index (im->ah_backends, backend_idx))
+ {
+ return -1;
+ }
+ ipsec_ah_backend_t *b = pool_elt_at_index (im->ah_backends, backend_idx);
+ im->ah_current_backend = backend_idx;
+ im->ah4_encrypt_node_index = b->ah4_encrypt_node_index;
+ im->ah4_decrypt_node_index = b->ah4_decrypt_node_index;
+ im->ah4_encrypt_next_index = b->ah4_encrypt_next_index;
+ im->ah4_decrypt_next_index = b->ah4_decrypt_next_index;
+ im->ah6_encrypt_node_index = b->ah6_encrypt_node_index;
+ im->ah6_decrypt_node_index = b->ah6_decrypt_node_index;
+ im->ah6_encrypt_next_index = b->ah6_encrypt_next_index;
+ im->ah6_decrypt_next_index = b->ah6_decrypt_next_index;
+ return 0;
+}
+
+int
+ipsec_select_esp_backend (ipsec_main_t * im, u32 backend_idx)
+{
+ if (pool_elts (im->sad) > 0
+ || pool_is_free_index (im->esp_backends, backend_idx))
+ {
+ return -1;
+ }
+ ipsec_esp_backend_t *b = pool_elt_at_index (im->esp_backends, backend_idx);
+ im->esp_current_backend = backend_idx;
+ im->esp4_encrypt_node_index = b->esp4_encrypt_node_index;
+ im->esp4_decrypt_node_index = b->esp4_decrypt_node_index;
+ im->esp4_encrypt_next_index = b->esp4_encrypt_next_index;
+ im->esp4_decrypt_next_index = b->esp4_decrypt_next_index;
+ im->esp6_encrypt_node_index = b->esp6_encrypt_node_index;
+ im->esp6_decrypt_node_index = b->esp6_decrypt_node_index;
+ im->esp6_encrypt_next_index = b->esp6_encrypt_next_index;
+ im->esp6_decrypt_next_index = b->esp6_decrypt_next_index;
+ return 0;
+}
+