+ if (ipv4_set && ipv6_set)
+ return clib_error_return (0, "both IPv4 and IPv6 addresses specified");
+
+ fib_index = fib_table_find (fib_ip_proto (ipv6_set), table_id);
+
+ if (~0 == fib_index)
+ {
+ rv = VNET_API_ERROR_NO_SUCH_FIB;
+ goto done;
+ }
+
+ if (is_add)
+ {
+ // remote = input, local = output
+ u32 sw_if_index;
+
+ /* create an ip-ip tunnel, then the two SA, then bind them */
+ rv =
+ ipip_add_tunnel (ipv6_set ? IPIP_TRANSPORT_IP6 : IPIP_TRANSPORT_IP4,
+ instance, &local_ip, &remote_ip, fib_index,
+ TUNNEL_ENCAP_DECAP_FLAG_NONE, IP_DSCP_CS0,
+ TUNNEL_MODE_P2P, &sw_if_index);
+ rv |=
+ ipsec_sa_add_and_lock (ipsec_tun_mk_local_sa_id (sw_if_index),
+ local_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
+ &lck, integ_alg, &lik, flags, table_id,
+ clib_host_to_net_u32 (salt), &local_ip,
+ &remote_ip, NULL, IPSEC_UDP_PORT_NONE);
+ rv |=
+ ipsec_sa_add_and_lock (ipsec_tun_mk_remote_sa_id (sw_if_index),
+ remote_spi, IPSEC_PROTOCOL_ESP, crypto_alg,
+ &rck, integ_alg, &rik,
+ (flags | IPSEC_SA_FLAG_IS_INBOUND), table_id,
+ clib_host_to_net_u32 (salt), &remote_ip,
+ &local_ip, NULL, IPSEC_UDP_PORT_NONE);
+ rv |=
+ ipsec_tun_protect_update_one (sw_if_index, &nh,
+ ipsec_tun_mk_local_sa_id (sw_if_index),
+ ipsec_tun_mk_remote_sa_id
+ (sw_if_index));
+ }
+ else
+ rv = 0;