+ if (~0 == fib_index)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto done;
+ }
+
+ if (mp->is_add)
+ {
+ // remote = input, local = output
+ /* create an ip-ip tunnel, then the two SA, then bind them */
+ rv = ipip_add_tunnel (transport,
+ (mp->renumber ? ntohl (mp->show_instance) : ~0),
+ &local_ip,
+ &remote_ip, fib_index,
+ TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
+ TUNNEL_MODE_P2P, &sw_if_index);
+
+ if (rv)
+ goto done;
+
+ rv = ipsec_sa_add_and_lock (ipsec_tun_mk_input_sa_id (sw_if_index),
+ ntohl (mp->remote_spi),
+ IPSEC_PROTOCOL_ESP,
+ mp->crypto_alg,
+ &crypto_key,
+ mp->integ_alg,
+ &integ_key,
+ (flags | IPSEC_SA_FLAG_IS_INBOUND),
+ ntohl (mp->tx_table_id),
+ mp->salt, &remote_ip, &local_ip, NULL);
+
+ if (rv)
+ goto done;
+
+ rv = ipsec_sa_add_and_lock (ipsec_tun_mk_output_sa_id (sw_if_index),
+ ntohl (mp->local_spi),
+ IPSEC_PROTOCOL_ESP,
+ mp->crypto_alg,
+ &crypto_key,
+ mp->integ_alg,
+ &integ_key,
+ flags,
+ ntohl (mp->tx_table_id),
+ mp->salt, &local_ip, &remote_ip, NULL);
+
+ if (rv)
+ goto done;
+
+ rv = ipsec_tun_protect_update_one (sw_if_index, NULL,
+ ipsec_tun_mk_output_sa_id
+ (sw_if_index),
+ ipsec_tun_mk_input_sa_id
+ (sw_if_index));
+ if (rv)
+ goto done;
+
+ /* the SAs are locked as a result of being used for proection,
+ * they cannot be removed from the API, since they cannot be refered
+ * to by the API. unlock them now, so that if the tunnel is rekeyed
+ * they-ll disapper
+ */
+ ipsec_sa_unlock_id (ipsec_tun_mk_input_sa_id (sw_if_index));
+ ipsec_sa_unlock_id (ipsec_tun_mk_output_sa_id (sw_if_index));
+ }
+ else
+ {
+ /* *INDENT-OFF* */
+ ipip_tunnel_key_t key = {
+ .transport = transport,
+ .fib_index = fib_index,
+ .src = local_ip,
+ .dst = remote_ip
+ };
+ /* *INDENT-ON* */
+
+ ipip_tunnel_t *t = ipip_tunnel_db_find (&key);
+
+ if (NULL != t)
+ {
+ rv = ipsec_tun_protect_del (t->sw_if_index, NULL);
+ ipip_del_tunnel (t->sw_if_index);
+ }
+ else
+ rv = VNET_API_ERROR_NO_SUCH_ENTRY;
+ }