#include <vnet/ipsec/esp.h>
#define foreach_esp_encrypt_next \
-_(DROP, "error-drop") \
+_(DROP4, "ip4-drop") \
+_(DROP6, "ip6-drop") \
_(PENDING, "pending") \
-_(HANDOFF, "handoff") \
+_(HANDOFF4, "handoff4") \
+_(HANDOFF6, "handoff6") \
_(INTERFACE_OUTPUT, "interface-output")
#define _(v, s) ESP_ENCRYPT_NEXT_##v,
static_always_inline void
esp_process_chained_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
vnet_crypto_op_t * ops, vlib_buffer_t * b[],
- u16 * nexts, vnet_crypto_op_chunk_t * chunks)
+ u16 * nexts, vnet_crypto_op_chunk_t * chunks,
+ u16 drop_next)
{
u32 n_fail, n_ops = vec_len (ops);
vnet_crypto_op_t *op = ops;
{
u32 bi = op->user_data;
b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
- nexts[bi] = ESP_ENCRYPT_NEXT_DROP;
+ nexts[bi] = drop_next;
n_fail--;
}
op++;
static_always_inline void
esp_process_ops (vlib_main_t * vm, vlib_node_runtime_t * node,
- vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts)
+ vnet_crypto_op_t * ops, vlib_buffer_t * b[], u16 * nexts,
+ u16 drop_next)
{
u32 n_fail, n_ops = vec_len (ops);
vnet_crypto_op_t *op = ops;
{
u32 bi = op->user_data;
b[bi]->error = node->errors[ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR];
- nexts[bi] = ESP_ENCRYPT_NEXT_DROP;
+ nexts[bi] = drop_next;
n_fail--;
}
op++;
/* when submitting a frame is failed, drop all buffers in the frame */
static_always_inline void
esp_async_recycle_failed_submit (vnet_crypto_async_frame_t * f,
- vlib_buffer_t ** b, u16 * next)
+ vlib_buffer_t ** b, u16 * next,
+ u16 drop_next)
{
u32 n_drop = f->n_elts;
while (--n_drop)
{
(b - n_drop)[0]->error = ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR;
- (next - n_drop)[0] = ESP_ENCRYPT_NEXT_DROP;
+ (next - n_drop)[0] = drop_next;
}
vnet_crypto_async_reset_frame (f);
}
vnet_crypto_async_frame_t *async_frame = 0;
int is_async = im->async_mode;
vnet_crypto_async_op_id_t last_async_op = ~0;
+ u16 drop_next = (is_ip6 ? ESP_ENCRYPT_NEXT_DROP6 : ESP_ENCRYPT_NEXT_DROP4);
vlib_get_buffers (vm, from, b, n_left);
if (!is_async)
{
if (vnet_crypto_async_submit_open_frame (vm, async_frame)
< 0)
- esp_async_recycle_failed_submit (async_frame, b, next);
+ esp_async_recycle_failed_submit (async_frame, b,
+ next, drop_next);
}
async_frame =
vnet_crypto_async_get_frame (vm, sa0->crypto_async_enc_op_id);
if (PREDICT_TRUE (thread_index != sa0->encrypt_thread_index))
{
- next[0] = ESP_ENCRYPT_NEXT_HANDOFF;
+ next[0] = (is_ip6 ?
+ ESP_ENCRYPT_NEXT_HANDOFF6 : ESP_ENCRYPT_NEXT_HANDOFF4);
goto trace;
}
if (n_bufs == 0)
{
b[0]->error = node->errors[ESP_ENCRYPT_ERROR_NO_BUFFERS];
- next[0] = ESP_ENCRYPT_NEXT_DROP;
+ next[0] = drop_next;
goto trace;
}
if (PREDICT_FALSE (esp_seq_advance (sa0)))
{
b[0]->error = node->errors[ESP_ENCRYPT_ERROR_SEQ_CYCLED];
- next[0] = ESP_ENCRYPT_NEXT_DROP;
+ next[0] = drop_next;
goto trace;
}
if (!next_hdr_ptr)
{
b[0]->error = node->errors[ESP_ENCRYPT_ERROR_NO_BUFFERS];
- next[0] = ESP_ENCRYPT_NEXT_DROP;
+ next[0] = drop_next;
goto trace;
}
b[0]->flags &= ~VLIB_BUFFER_TOTAL_LENGTH_VALID;
icv_sz, from[b - bufs], next, hdr_len,
async_next, lb))
{
- esp_async_recycle_failed_submit (async_frame, b, next);
+ esp_async_recycle_failed_submit (async_frame, b, next,
+ drop_next);
goto trace;
}
}
current_sa_bytes);
if (!is_async)
{
- esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts);
+ esp_process_ops (vm, node, ptd->crypto_ops, bufs, nexts, drop_next);
esp_process_chained_ops (vm, node, ptd->chained_crypto_ops, bufs, nexts,
- ptd->chunks);
+ ptd->chunks, drop_next);
- esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts);
+ esp_process_ops (vm, node, ptd->integ_ops, bufs, nexts, drop_next);
esp_process_chained_ops (vm, node, ptd->chained_integ_ops, bufs, nexts,
- ptd->chunks);
+ ptd->chunks, drop_next);
}
else if (async_frame && async_frame->n_elts)
{
if (vnet_crypto_async_submit_open_frame (vm, async_frame) < 0)
- esp_async_recycle_failed_submit (async_frame, b, next);
+ esp_async_recycle_failed_submit (async_frame, b, next, drop_next);
}
vlib_node_increment_counter (vm, node->node_index,
.n_next_nodes = ESP_ENCRYPT_N_NEXT,
.next_nodes = {
- [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
- [ESP_ENCRYPT_NEXT_HANDOFF] = "esp4-encrypt-handoff",
+ [ESP_ENCRYPT_NEXT_DROP4] = "ip4-drop",
+ [ESP_ENCRYPT_NEXT_DROP6] = "ip6-drop",
+ [ESP_ENCRYPT_NEXT_HANDOFF4] = "esp4-encrypt-handoff",
+ [ESP_ENCRYPT_NEXT_HANDOFF6] = "esp6-encrypt-handoff",
[ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
[ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
},
.vector_size = sizeof (u32),
.format_trace = format_esp_encrypt_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
+ .sibling_of = "esp4-encrypt",
.n_errors = ARRAY_LEN(esp_encrypt_error_strings),
.error_strings = esp_encrypt_error_strings,
-
- .n_next_nodes = ESP_ENCRYPT_N_NEXT,
- .next_nodes = {
- [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
- [ESP_ENCRYPT_NEXT_HANDOFF] = "esp6-encrypt-handoff",
- [ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "interface-output",
- [ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
- },
};
/* *INDENT-ON* */
.vector_size = sizeof (u32),
.format_trace = format_esp_post_encrypt_trace,
.type = VLIB_NODE_TYPE_INTERNAL,
- .sibling_of = "esp6-encrypt",
+ .sibling_of = "esp4-encrypt",
.n_errors = ARRAY_LEN(esp_encrypt_error_strings),
.error_strings = esp_encrypt_error_strings,
.n_next_nodes = ESP_ENCRYPT_N_NEXT,
.next_nodes = {
- [ESP_ENCRYPT_NEXT_DROP] = "ip4-drop",
- [ESP_ENCRYPT_NEXT_HANDOFF] = "esp4-encrypt-tun-handoff",
+ [ESP_ENCRYPT_NEXT_DROP4] = "ip4-drop",
+ [ESP_ENCRYPT_NEXT_DROP6] = "ip6-drop",
+ [ESP_ENCRYPT_NEXT_HANDOFF4] = "esp4-encrypt-tun-handoff",
+ [ESP_ENCRYPT_NEXT_HANDOFF6] = "error-drop",
[ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
[ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
},
.n_next_nodes = ESP_ENCRYPT_N_NEXT,
.next_nodes = {
- [ESP_ENCRYPT_NEXT_DROP] = "ip6-drop",
- [ESP_ENCRYPT_NEXT_HANDOFF] = "esp6-encrypt-tun-handoff",
+ [ESP_ENCRYPT_NEXT_DROP4] = "ip4-drop",
+ [ESP_ENCRYPT_NEXT_DROP6] = "ip6-drop",
+ [ESP_ENCRYPT_NEXT_HANDOFF4] = "error-drop",
+ [ESP_ENCRYPT_NEXT_HANDOFF6] = "esp6-encrypt-tun-handoff",
[ESP_ENCRYPT_NEXT_PENDING] = "esp-encrypt-pending",
[ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT] = "adj-midchain-tx",
},
unformat_input_t _line_input, *line_input = &_line_input;
ipsec_policy_t p;
int rv, is_add = 0;
- u32 tmp, tmp2, stat_index;
+ u32 tmp, tmp2, stat_index, local_range_set, remote_range_set;
clib_error_t *error = NULL;
u32 is_outbound;
clib_memset (&p, 0, sizeof (p));
p.lport.stop = p.rport.stop = ~0;
- is_outbound = 0;
+ remote_range_set = local_range_set = is_outbound = 0;
if (!unformat_user (input, unformat_line_input, line_input))
return 0;
is_add = 1;
else if (unformat (line_input, "del"))
is_add = 0;
+ else if (unformat (line_input, "ip6"))
+ p.is_ipv6 = 1;
else if (unformat (line_input, "spd %u", &p.id))
;
else if (unformat (line_input, "inbound"))
else if (unformat (line_input, "local-ip-range %U - %U",
unformat_ip4_address, &p.laddr.start.ip4,
unformat_ip4_address, &p.laddr.stop.ip4))
- ;
+ local_range_set = 1;
else if (unformat (line_input, "remote-ip-range %U - %U",
unformat_ip4_address, &p.raddr.start.ip4,
unformat_ip4_address, &p.raddr.stop.ip4))
- ;
+ remote_range_set = 1;
else if (unformat (line_input, "local-ip-range %U - %U",
unformat_ip6_address, &p.laddr.start.ip6,
unformat_ip6_address, &p.laddr.stop.ip6))
{
p.is_ipv6 = 1;
+ local_range_set = 1;
}
else if (unformat (line_input, "remote-ip-range %U - %U",
unformat_ip6_address, &p.raddr.start.ip6,
unformat_ip6_address, &p.raddr.stop.ip6))
{
p.is_ipv6 = 1;
+ remote_range_set = 1;
}
else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2))
{
}
}
+ if (!remote_range_set)
+ {
+ if (p.is_ipv6)
+ clib_memset (&p.raddr.stop.ip6, 0xff, 16);
+ else
+ clib_memset (&p.raddr.stop.ip4, 0xff, 4);
+ }
+ if (!local_range_set)
+ {
+ if (p.is_ipv6)
+ clib_memset (&p.laddr.stop.ip6, 0xff, 16);
+ else
+ clib_memset (&p.laddr.stop.ip4, 0xff, 4);
+ }
+
rv = ipsec_policy_mk_type (is_outbound, p.is_ipv6, p.policy, &p.type);
if (rv)
class TestIpsecEsp1(TemplateIpsecEsp, IpsecTra46Tests,
IpsecTun46Tests, IpsecTra6ExtTests):
""" Ipsec ESP - TUN & TRA tests """
- pass
+
+ @classmethod
+ def setUpClass(cls):
+ super(TestIpsecEsp1, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(TestIpsecEsp1, cls).tearDownClass()
+
+ def setUp(self):
+ super(TestIpsecEsp1, self).setUp()
+
+ def tearDown(self):
+ super(TestIpsecEsp1, self).tearDown()
+
+ def test_tun_46(self):
+ """ ipsec 4o6 tunnel """
+ # add an SPD entry to direct 2.2.2.2 to the v6 tunnel SA
+ p6 = self.ipv6_params
+ p4 = self.ipv4_params
+
+ p6.remote_tun_if_host4 = "2.2.2.2"
+ e = VppEnum.vl_api_ipsec_spd_action_t
+
+ VppIpsecSpdEntry(self,
+ self.tun_spd,
+ p6.scapy_tun_sa_id,
+ self.pg1.remote_addr[p4.addr_type],
+ self.pg1.remote_addr[p4.addr_type],
+ p6.remote_tun_if_host4,
+ p6.remote_tun_if_host4,
+ 0,
+ priority=10,
+ policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+ is_outbound=1).add_vpp_config()
+ VppIpRoute(self, p6.remote_tun_if_host4, p4.addr_len,
+ [VppRoutePath(self.tun_if.remote_addr[p4.addr_type],
+ 0xffffffff)]).add_vpp_config()
+
+ old_name = self.tun6_encrypt_node_name
+ self.tun6_encrypt_node_name = "esp4-encrypt"
+
+ self.verify_tun_46(p6, count=63)
+ self.tun6_encrypt_node_name = old_name
+
+ def test_tun_64(self):
+ """ ipsec 6o4 tunnel """
+ # add an SPD entry to direct 4444::4 to the v4 tunnel SA
+ p6 = self.ipv6_params
+ p4 = self.ipv4_params
+
+ p4.remote_tun_if_host6 = "4444::4"
+ e = VppEnum.vl_api_ipsec_spd_action_t
+
+ VppIpsecSpdEntry(self,
+ self.tun_spd,
+ p4.scapy_tun_sa_id,
+ self.pg1.remote_addr[p6.addr_type],
+ self.pg1.remote_addr[p6.addr_type],
+ p4.remote_tun_if_host6,
+ p4.remote_tun_if_host6,
+ 0,
+ priority=10,
+ policy=e.IPSEC_API_SPD_ACTION_PROTECT,
+ is_outbound=1).add_vpp_config()
+ d = DpoProto.DPO_PROTO_IP6
+ VppIpRoute(self, p4.remote_tun_if_host6, p6.addr_len,
+ [VppRoutePath(self.tun_if.remote_addr[p6.addr_type],
+ 0xffffffff,
+ proto=d)]).add_vpp_config()
+
+ old_name = self.tun4_encrypt_node_name
+ self.tun4_encrypt_node_name = "esp6-encrypt"
+ self.verify_tun_64(p4, count=63)
+ self.tun4_encrypt_node_name = old_name
class TestIpsecEsp2(TemplateIpsecEsp, IpsecTcpTests):