From a09c1ff5b6ae535932b4fc9477ffc4e39748ca62 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 4 Feb 2019 01:10:30 -0800 Subject: [PATCH] IPSEC: SPD counters in the stats sgement - return the stats_index of each SPD in the create API call - no ip_any in the API as this creates 2 SPD entries. client must add both v4 and v6 explicitly - only one pool of SPD entries (rhter than one per-SPD) to support this - no packets/bytes in the dump API. Polling the stats segment is much more efficient (if the SA lifetime is based on packet/bytes) - emit the policy index in the packet trace and CLI commands. Change-Id: I7eaf52c9d0495fa24450facf55229941279b8569 Signed-off-by: Neale Ranns --- src/vat/api_format.c | 1 - src/vnet/ipsec/ipsec.api | 18 ++- src/vnet/ipsec/ipsec.h | 6 +- src/vnet/ipsec/ipsec_api.c | 42 +++--- src/vnet/ipsec/ipsec_cli.c | 211 +++---------------------------- src/vnet/ipsec/ipsec_format.c | 76 +++++++++++ src/vnet/ipsec/ipsec_input.c | 151 ++++++++++++---------- src/vnet/ipsec/ipsec_output.c | 77 +++++------ src/vnet/ipsec/ipsec_sa.c | 17 +-- src/vnet/ipsec/ipsec_spd.c | 10 +- src/vnet/ipsec/ipsec_spd.h | 35 +++-- src/vnet/ipsec/ipsec_spd_policy.c | 260 +++++++++++++++++--------------------- src/vnet/ipsec/ipsec_spd_policy.h | 13 +- test/template_ipsec.py | 5 + test/test_ipsec_ah.py | 22 ++-- test/test_ipsec_esp.py | 22 ++-- test/vpp_ipsec.py | 7 +- 17 files changed, 448 insertions(+), 525 deletions(-) diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 3755354924d..d35c19eb416 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -14924,7 +14924,6 @@ api_ipsec_spd_entry_add_del (vat_main_t * vam) mp->entry.remote_port_stop = ntohs ((u16) rport_stop); mp->entry.policy = (u8) policy; mp->entry.sa_id = ntohl (sa_id); - mp->entry.is_ip_any = is_ip_any; S (mp); W (ret); diff --git a/src/vnet/ipsec/ipsec.api b/src/vnet/ipsec/ipsec.api index 92c39acefd6..54cc76bb9d6 100644 --- a/src/vnet/ipsec/ipsec.api +++ b/src/vnet/ipsec/ipsec.api @@ -96,7 +96,6 @@ typedef ipsec_spd_entry u8 protocol; // Selector - u8 is_ip_any; vl_api_address_t remote_address_start; vl_api_address_t remote_address_stop; vl_api_address_t local_address_start; @@ -115,7 +114,7 @@ typedef ipsec_spd_entry @param is_add - add SPD if non-zero, else delete @param entry - Description of the entry to add/dell */ -autoreply define ipsec_spd_entry_add_del +define ipsec_spd_entry_add_del { u32 client_index; u32 context; @@ -123,6 +122,19 @@ autoreply define ipsec_spd_entry_add_del vl_api_ipsec_spd_entry_t entry; }; +/** \brief IPsec: Reply Add/delete Security Policy Database entry + + @param context - sender context, to match reply w/ request + @param retval - success/fail rutrun code + @param stat_index - An index for the policy in the stats segment @ /net/ipec/policy +*/ +define ipsec_spd_entry_add_del_reply +{ + u32 context; + i32 retval; + u32 stat_index; +}; + /** \brief Dump IPsec all SPD IDs @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request @@ -165,8 +177,6 @@ define ipsec_spd_dump { define ipsec_spd_details { u32 context; vl_api_ipsec_spd_entry_t entry; - u64 bytes; - u64 packets; }; /* diff --git a/src/vnet/ipsec/ipsec.h b/src/vnet/ipsec/ipsec.h index fd709675b8e..ed14a5bcbe1 100644 --- a/src/vnet/ipsec/ipsec.h +++ b/src/vnet/ipsec/ipsec.h @@ -119,7 +119,10 @@ typedef struct { /* pool of tunnel instances */ ipsec_spd_t *spds; + /* Pool of security associations */ ipsec_sa_t *sad; + /* pool of policies */ + ipsec_policy_t *policies; /* pool of tunnel interfaces */ ipsec_tunnel_if_t *tunnel_interfaces; @@ -175,9 +178,6 @@ typedef struct u32 ah_default_backend; /* index of default esp backend */ u32 esp_default_backend; - - /* helper for sort function */ - ipsec_spd_t *spd_to_sort; } ipsec_main_t; extern ipsec_main_t ipsec_main; diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c index eb78dbdd319..06f954622c7 100644 --- a/src/vnet/ipsec/ipsec_api.c +++ b/src/vnet/ipsec/ipsec_api.c @@ -143,6 +143,7 @@ static void vl_api_ipsec_spd_entry_add_del_t_handler vlib_main_t *vm __attribute__ ((unused)) = vlib_get_main (); vl_api_ipsec_spd_entry_add_del_reply_t *rmp; ip46_type_t itype; + u32 stat_index; int rv; #if WITH_LIBSSL > 0 @@ -181,22 +182,22 @@ static void vl_api_ipsec_spd_entry_add_del_t_handler } p.sa_id = ntohl (mp->entry.sa_id); - rv = ipsec_add_del_policy (vm, &p, mp->is_add); + rv = ipsec_add_del_policy (vm, &p, mp->is_add, &stat_index); if (rv) goto out; - if (mp->entry.is_ip_any) - { - p.is_ipv6 = 1; - rv = ipsec_add_del_policy (vm, &p, mp->is_add); - } #else rv = VNET_API_ERROR_UNIMPLEMENTED; goto out; #endif out: - REPLY_MACRO (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY); + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_IPSEC_SPD_ENTRY_ADD_DEL_REPLY, + ({ + rmp->stat_index = ntohl(stat_index); + })); + /* *INDENT-ON* */ } static int @@ -340,6 +341,7 @@ send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg, u32 context) { vl_api_ipsec_spds_details_t *mp; + u32 n_policies = 0; mp = vl_msg_api_alloc (sizeof (*mp)); clib_memset (mp, 0, sizeof (*mp)); @@ -347,7 +349,10 @@ send_ipsec_spds_details (ipsec_spd_t * spd, vl_api_registration_t * reg, mp->context = context; mp->spd_id = htonl (spd->id); - mp->npolicies = htonl (pool_len (spd->policies)); +#define _(s, n) n_policies += vec_len (spd->policies[IPSEC_SPD_POLICY_##s]); + foreach_ipsec_spd_policy_type +#undef _ + mp->npolicies = htonl (n_policies); vl_api_send_msg (reg, (u8 *) mp); } @@ -420,9 +425,6 @@ send_ipsec_spd_details (ipsec_policy_t * p, vl_api_registration_t * reg, mp->entry.policy = ipsec_spd_action_encode (p->policy); mp->entry.sa_id = htonl (p->sa_id); - mp->bytes = clib_host_to_net_u64 (p->counter.bytes); - mp->packets = clib_host_to_net_u64 (p->counter.packets); - vl_api_send_msg (reg, (u8 *) mp); } @@ -431,10 +433,11 @@ vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp) { vl_api_registration_t *reg; ipsec_main_t *im = &ipsec_main; + ipsec_spd_policy_t ptype; ipsec_policy_t *policy; ipsec_spd_t *spd; uword *p; - u32 spd_index; + u32 spd_index, *ii; #if WITH_LIBSSL > 0 reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) @@ -448,12 +451,15 @@ vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp) spd = pool_elt_at_index (im->spds, spd_index); /* *INDENT-OFF* */ - pool_foreach (policy, spd->policies, - ({ - if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id) - send_ipsec_spd_details (policy, reg, - mp->context);} - )); + FOR_EACH_IPSEC_SPD_POLICY_TYPE(ptype) { + vec_foreach(ii, spd->policies[ptype]) + { + policy = pool_elt_at_index(im->policies, *ii); + + if (mp->sa_id == ~(0) || ntohl (mp->sa_id) == policy->sa_id) + send_ipsec_spd_details (policy, reg, mp->context); + } + } /* *INDENT-ON* */ #else clib_warning ("unimplemented"); diff --git a/src/vnet/ipsec/ipsec_cli.c b/src/vnet/ipsec/ipsec_cli.c index f3a6158e850..4bc14372042 100644 --- a/src/vnet/ipsec/ipsec_cli.c +++ b/src/vnet/ipsec/ipsec_cli.c @@ -258,9 +258,8 @@ ipsec_policy_add_del_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, *line_input = &_line_input; ipsec_policy_t p; - int is_add = 0; - int is_ip_any = 1; - u32 tmp, tmp2; + int rv, is_add = 0; + u32 tmp, tmp2, stat_index; clib_error_t *error = NULL; clib_memset (&p, 0, sizeof (p)); @@ -304,24 +303,22 @@ ipsec_policy_add_del_command_fn (vlib_main_t * vm, else if (unformat (line_input, "local-ip-range %U - %U", unformat_ip4_address, &p.laddr.start.ip4, unformat_ip4_address, &p.laddr.stop.ip4)) - is_ip_any = 0; + ; else if (unformat (line_input, "remote-ip-range %U - %U", unformat_ip4_address, &p.raddr.start.ip4, unformat_ip4_address, &p.raddr.stop.ip4)) - is_ip_any = 0; + ; 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; - is_ip_any = 0; } 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; - is_ip_any = 0; } else if (unformat (line_input, "local-port-range %u - %u", &tmp, &tmp2)) { @@ -363,12 +360,12 @@ ipsec_policy_add_del_command_fn (vlib_main_t * vm, goto done; } } - ipsec_add_del_policy (vm, &p, is_add); - if (is_ip_any) - { - p.is_ipv6 = 1; - ipsec_add_del_policy (vm, &p, is_add); - } + rv = ipsec_add_del_policy (vm, &p, is_add, &stat_index); + + if (!rv) + vlib_cli_output (vm, "policy-index:%d", stat_index); + else + vlib_cli_output (vm, "error:%d", rv); done: unformat_free (line_input); @@ -451,11 +448,9 @@ static clib_error_t * show_ipsec_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - ipsec_spd_t *spd; ipsec_sa_t *sa; - ipsec_policy_t *p; ipsec_main_t *im = &ipsec_main; - u32 *i; + u32 i; ipsec_tunnel_if_t *t; vnet_hw_interface_t *hi; u8 *protocol = NULL; @@ -494,174 +489,8 @@ show_ipsec_command_fn (vlib_main_t * vm, /* *INDENT-ON* */ /* *INDENT-OFF* */ - pool_foreach (spd, im->spds, ({ - vlib_cli_output(vm, "spd %u", spd->id); - - vlib_cli_output(vm, " outbound policies"); - vec_foreach(i, spd->ipv4_outbound_policies) - { - p = pool_elt_at_index(spd->policies, *i); - vec_reset_length(protocol); - vec_reset_length(policy); - if (p->protocol) { - protocol = format(protocol, "%U", format_ip_protocol, p->protocol); - } else { - protocol = format(protocol, "any"); - } - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) { - policy = format(policy, " sa %u", p->sa_id); - } - - vlib_cli_output(vm, " priority %d action %U protocol %v%v", - p->priority, format_ipsec_policy_action, p->policy, - protocol, policy); - vlib_cli_output(vm, " local addr range %U - %U port range %u - %u", - format_ip4_address, &p->laddr.start.ip4, - format_ip4_address, &p->laddr.stop.ip4, - p->lport.start, p->lport.stop); - vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u", - format_ip4_address, &p->raddr.start.ip4, - format_ip4_address, &p->raddr.stop.ip4, - p->rport.start, p->rport.stop); - vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets, - p->counter.bytes); - }; - vec_foreach(i, spd->ipv6_outbound_policies) - { - p = pool_elt_at_index(spd->policies, *i); - vec_reset_length(protocol); - vec_reset_length(policy); - if (p->protocol) { - protocol = format(protocol, "%U", format_ip_protocol, p->protocol); - } else { - protocol = format(protocol, "any"); - } - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) { - policy = format(policy, " sa %u", p->sa_id); - } - vlib_cli_output(vm, " priority %d action %U protocol %v%v", - p->priority, format_ipsec_policy_action, p->policy, - protocol, policy); - vlib_cli_output(vm, " local addr range %U - %U port range %u - %u", - format_ip6_address, &p->laddr.start.ip6, - format_ip6_address, &p->laddr.stop.ip6, - p->lport.start, p->lport.stop); - vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u", - format_ip6_address, &p->raddr.start.ip6, - format_ip6_address, &p->raddr.stop.ip6, - p->rport.start, p->rport.stop); - vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets, - p->counter.bytes); - }; - vlib_cli_output(vm, " inbound policies"); - vec_foreach(i, spd->ipv4_inbound_protect_policy_indices) - { - p = pool_elt_at_index(spd->policies, *i); - vec_reset_length(protocol); - vec_reset_length(policy); - if (p->protocol) { - protocol = format(protocol, "%U", format_ip_protocol, p->protocol); - } else { - protocol = format(protocol, "any"); - } - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) { - policy = format(policy, " sa %u", p->sa_id); - } - vlib_cli_output(vm, " priority %d action %U protocol %v%v", - p->priority, format_ipsec_policy_action, p->policy, - protocol, policy); - vlib_cli_output(vm, " local addr range %U - %U port range %u - %u", - format_ip4_address, &p->laddr.start.ip4, - format_ip4_address, &p->laddr.stop.ip4, - p->lport.start, p->lport.stop); - vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u", - format_ip4_address, &p->raddr.start.ip4, - format_ip4_address, &p->raddr.stop.ip4, - p->rport.start, p->rport.stop); - vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets, - p->counter.bytes); - }; - vec_foreach(i, spd->ipv4_inbound_policy_discard_and_bypass_indices) - { - p = pool_elt_at_index(spd->policies, *i); - vec_reset_length(protocol); - vec_reset_length(policy); - if (p->protocol) { - protocol = format(protocol, "%U", format_ip_protocol, p->protocol); - } else { - protocol = format(protocol, "any"); - } - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) { - policy = format(policy, " sa %u", p->sa_id); - } - vlib_cli_output(vm, " priority %d action %U protocol %v%v", - p->priority, format_ipsec_policy_action, p->policy, - protocol, policy); - vlib_cli_output(vm, " local addr range %U - %U port range %u - %u", - format_ip4_address, &p->laddr.start.ip4, - format_ip4_address, &p->laddr.stop.ip4, - p->lport.start, p->lport.stop); - vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u", - format_ip4_address, &p->raddr.start.ip4, - format_ip4_address, &p->raddr.stop.ip4, - p->rport.start, p->rport.stop); - vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets, - p->counter.bytes); - }; - vec_foreach(i, spd->ipv6_inbound_protect_policy_indices) - { - p = pool_elt_at_index(spd->policies, *i); - vec_reset_length(protocol); - vec_reset_length(policy); - if (p->protocol) { - protocol = format(protocol, "%U", format_ip_protocol, p->protocol); - } else { - protocol = format(protocol, "any"); - } - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) { - policy = format(policy, " sa %u", p->sa_id); - } - vlib_cli_output(vm, " priority %d action %U protocol %v%v", - p->priority, format_ipsec_policy_action, p->policy, - protocol, policy); - vlib_cli_output(vm, " local addr range %U - %U port range %u - %u", - format_ip6_address, &p->laddr.start.ip6, - format_ip6_address, &p->laddr.stop.ip6, - p->lport.start, p->lport.stop); - vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u", - format_ip6_address, &p->raddr.start.ip6, - format_ip6_address, &p->raddr.stop.ip6, - p->rport.start, p->rport.stop); - vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets, - p->counter.bytes); - }; - vec_foreach(i, spd->ipv6_inbound_policy_discard_and_bypass_indices) - { - p = pool_elt_at_index(spd->policies, *i); - vec_reset_length(protocol); - vec_reset_length(policy); - if (p->protocol) { - protocol = format(protocol, "%U", format_ip_protocol, p->protocol); - } else { - protocol = format(protocol, "any"); - } - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) { - policy = format(policy, " sa %u", p->sa_id); - } - vlib_cli_output(vm, " priority %d action %U protocol %v%v", - p->priority, format_ipsec_policy_action, p->policy, - protocol, policy); - vlib_cli_output(vm, " local addr range %U - %U port range %u - %u", - format_ip6_address, &p->laddr.start.ip6, - format_ip6_address, &p->laddr.stop.ip6, - p->lport.start, p->lport.stop); - vlib_cli_output(vm, " remote addr range %U - %U port range %u - %u", - format_ip6_address, &p->raddr.start.ip6, - format_ip6_address, &p->raddr.stop.ip6, - p->rport.start, p->rport.stop); - vlib_cli_output(vm, " packets %u bytes %u", p->counter.packets, - p->counter.bytes); - }; + pool_foreach_index (i, im->spds, ({ + vlib_cli_output(vm, "%U", format_ipsec_spd, i); })); /* *INDENT-ON* */ @@ -866,19 +695,9 @@ clear_ipsec_counters_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - ipsec_main_t *im = &ipsec_main; - ipsec_spd_t *spd; - ipsec_policy_t *p; - - /* *INDENT-OFF* */ - pool_foreach (spd, im->spds, ({ - pool_foreach(p, spd->policies, ({ - p->counter.packets = p->counter.bytes = 0; - })); - })); - /* *INDENT-ON* */ + vlib_clear_combined_counters (&ipsec_spd_policy_counters); - return 0; + return (NULL); } /* *INDENT-OFF* */ diff --git a/src/vnet/ipsec/ipsec_format.c b/src/vnet/ipsec/ipsec_format.c index 38aed79a155..cbd67239680 100644 --- a/src/vnet/ipsec/ipsec_format.c +++ b/src/vnet/ipsec/ipsec_format.c @@ -132,6 +132,82 @@ format_ipsec_replay_window (u8 * s, va_list * args) return s; } +u8 * +format_ipsec_policy (u8 * s, va_list * args) +{ + u32 pi = va_arg (*args, u32); + ipsec_main_t *im = &ipsec_main; + ipsec_policy_t *p; + vlib_counter_t counts; + + p = pool_elt_at_index (im->policies, pi); + + s = format (s, " [%d] priority %d action %U protocol ", + pi, p->priority, format_ipsec_policy_action, p->policy); + if (p->protocol) + { + s = format (s, "%U", format_ip_protocol, p->protocol); + } + else + { + s = format (s, "any"); + } + if (p->policy == IPSEC_POLICY_ACTION_PROTECT) + { + s = format (s, " sa %u", p->sa_id); + } + if (p->is_ipv6) + { + s = format (s, "\n local addr range %U - %U port range %u - %u", + format_ip6_address, &p->laddr.start.ip6, + format_ip6_address, &p->laddr.stop.ip6, + p->lport.start, p->lport.stop); + s = format (s, "\n remote addr range %U - %U port range %u - %u", + format_ip6_address, &p->raddr.start.ip6, + format_ip6_address, &p->raddr.stop.ip6, + p->rport.start, p->rport.stop); + } + else + { + s = format (s, "\n local addr range %U - %U port range %u - %u", + format_ip4_address, &p->laddr.start.ip4, + format_ip4_address, &p->laddr.stop.ip4, + p->lport.start, p->lport.stop); + s = format (s, "\n remote addr range %U - %U port range %u - %u", + format_ip4_address, &p->raddr.start.ip4, + format_ip4_address, &p->raddr.stop.ip4, + p->rport.start, p->rport.stop); + } + vlib_get_combined_counter (&ipsec_spd_policy_counters, pi, &counts); + s = format (s, "\n packets %u bytes %u", counts.packets, counts.bytes); + + return (s); +} + +u8 * +format_ipsec_spd (u8 * s, va_list * args) +{ + u32 si = va_arg (*args, u32); + ipsec_main_t *im = &ipsec_main; + ipsec_spd_t *spd; + u32 *i; + + spd = pool_elt_at_index (im->spds, si); + + s = format (s, "spd %u", spd->id); + +#define _(v, n) \ + s = format (s, "\n %s:", n); \ + vec_foreach(i, spd->policies[IPSEC_SPD_POLICY_##v]) \ + { \ + s = format (s, "\n %U", format_ipsec_policy, *i); \ + } + foreach_ipsec_spd_policy_type; +#undef _ + + return (s); +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c index 1f3d6d01a93..e3fd4aa551d 100644 --- a/src/vnet/ipsec/ipsec_input.c +++ b/src/vnet/ipsec/ipsec_input.c @@ -44,7 +44,9 @@ static char *ipsec_input_error_strings[] = { typedef struct { + ip_protocol_t proto; u32 spd; + u32 policy_index; u32 sa_id; u32 spi; u32 seq; @@ -58,23 +60,10 @@ format_ipsec_input_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); ipsec_input_trace_t *t = va_arg (*args, ipsec_input_trace_t *); - if (t->spi == 0 && t->seq == 0) - { - s = format (s, "esp: no esp packet"); - return s; - } + s = format (s, "%U: sa_id %u spd %u policy %d spi %u seq %u", + format_ip_protocol, t->proto, t->sa_id, + t->spd, t->policy_index, t->spi, t->seq); - if (t->sa_id != 0) - { - s = - format (s, "esp: sa_id %u spd %u spi %u seq %u", t->sa_id, t->spd, - t->spi, t->seq); - } - else - { - s = - format (s, "esp: no sa spd %u spi %u seq %u", t->spd, t->spi, t->seq); - } return s; } @@ -86,9 +75,9 @@ ipsec_input_protect_policy_match (ipsec_spd_t * spd, u32 sa, u32 da, u32 spi) ipsec_sa_t *s; u32 *i; - vec_foreach (i, spd->ipv4_inbound_protect_policy_indices) + vec_foreach (i, spd->policies[IPSEC_SPD_POLICY_IP4_INBOUND_PROTECT]) { - p = pool_elt_at_index (spd->policies, *i); + p = pool_elt_at_index (im->policies, *i); s = pool_elt_at_index (im->sad, p->sa_index); if (spi != s->spi) @@ -142,9 +131,9 @@ ipsec6_input_protect_policy_match (ipsec_spd_t * spd, ipsec_sa_t *s; u32 *i; - vec_foreach (i, spd->ipv6_inbound_protect_policy_indices) + vec_foreach (i, spd->policies[IPSEC_SPD_POLICY_IP6_INBOUND_PROTECT]) { - p = pool_elt_at_index (spd->policies, *i); + p = pool_elt_at_index (im->policies, *i); s = pool_elt_at_index (im->sad, p->sa_index); if (spi != s->spi) @@ -178,11 +167,12 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - u32 n_left_from, *from, next_index, *to_next; + u32 n_left_from, *from, next_index, *to_next, thread_index; ipsec_main_t *im = &ipsec_main; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; + thread_index = vm->thread_index; next_index = node->cached_next_index; @@ -194,7 +184,7 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0, next0; + u32 bi0, next0, pi0; vlib_buffer_t *b0; ip4_header_t *ip0; esp_header_t *esp0; @@ -249,37 +239,43 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, clib_net_to_host_u32 (esp0->spi)); - if (PREDICT_TRUE (p0 != 0)) + if (PREDICT_TRUE (p0 != NULL)) { - p0->counter.packets++; - p0->counter.bytes += clib_net_to_host_u16 (ip0->length); + pi0 = p0 - im->policies; + vlib_increment_combined_counter + (&ipsec_spd_policy_counters, + thread_index, pi0, 1, + clib_net_to_host_u16 (ip0->length)); + vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; vnet_buffer (b0)->ipsec.flags = 0; next0 = im->esp4_decrypt_next_index; vlib_buffer_advance (b0, ((u8 *) esp0 - (u8 *) ip0)); goto trace0; } + else + { + pi0 = ~0; + }; /* FIXME bypass and discard */ trace0: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ipsec_input_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP || - ip0->protocol == IP_PROTOCOL_UDP) - { - if (p0) - tr->sa_id = p0->sa_id; - tr->spi = clib_host_to_net_u32 (esp0->spi); - tr->seq = clib_host_to_net_u32 (esp0->seq); - tr->spd = spd0->id; - } - } + tr->proto = ip0->protocol; + if (p0) + tr->sa_id = p0->sa_id; + tr->spi = clib_net_to_host_u32 (esp0->spi); + tr->seq = clib_net_to_host_u32 (esp0->seq); + tr->spd = spd0->id; + tr->policy_index = pi0; + } } - if (PREDICT_TRUE (ip0->protocol == IP_PROTOCOL_IPSEC_AH)) { ah0 = (ah_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); @@ -295,27 +291,35 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, if (PREDICT_TRUE (p0 != 0)) { - p0->counter.packets++; - p0->counter.bytes += clib_net_to_host_u16 (ip0->length); + pi0 = p0 - im->policies; + vlib_increment_combined_counter + (&ipsec_spd_policy_counters, + thread_index, pi0, 1, + clib_net_to_host_u16 (ip0->length)); vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; vnet_buffer (b0)->ipsec.flags = 0; next0 = im->ah4_decrypt_next_index; goto trace1; } + else + { + pi0 = ~0; + } /* FIXME bypass and discard */ trace1: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ipsec_input_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP) - { - if (p0) - tr->sa_id = p0->sa_id; - tr->spi = clib_host_to_net_u32 (ah0->spi); - tr->seq = clib_host_to_net_u32 (ah0->seq_no); - tr->spd = spd0->id; - } + + tr->proto = ip0->protocol; + if (p0) + tr->sa_id = p0->sa_id; + tr->spi = clib_net_to_host_u32 (ah0->spi); + tr->seq = clib_net_to_host_u32 (ah0->seq_no); + tr->spd = spd0->id; + tr->policy_index = pi0; } } @@ -359,11 +363,12 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) { - u32 n_left_from, *from, next_index, *to_next; + u32 n_left_from, *from, next_index, *to_next, thread_index; ipsec_main_t *im = &ipsec_main; from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; + thread_index = vm->thread_index; next_index = node->cached_next_index; @@ -375,7 +380,7 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, while (n_left_from > 0 && n_left_to_next > 0) { - u32 bi0, next0; + u32 bi0, next0, pi0; vlib_buffer_t *b0; ip6_header_t *ip0; esp_header_t *esp0; @@ -420,16 +425,22 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, if (PREDICT_TRUE (p0 != 0)) { - p0->counter.packets++; - p0->counter.bytes += - clib_net_to_host_u16 (ip0->payload_length); - p0->counter.bytes += header_size; + pi0 = p0 - im->policies; + vlib_increment_combined_counter + (&ipsec_spd_policy_counters, + thread_index, pi0, 1, + clib_net_to_host_u16 (ip0->payload_length) + + header_size); vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; vnet_buffer (b0)->ipsec.flags = 0; next0 = im->esp6_decrypt_next_index; vlib_buffer_advance (b0, header_size); goto trace0; } + else + { + pi0 = ~0; + } } else if (ip0->protocol == IP_PROTOCOL_IPSEC_AH) { @@ -441,30 +452,36 @@ VLIB_NODE_FN (ipsec6_input_node) (vlib_main_t * vm, if (PREDICT_TRUE (p0 != 0)) { - p0->counter.packets++; - p0->counter.bytes += - clib_net_to_host_u16 (ip0->payload_length); - p0->counter.bytes += header_size; + pi0 = p0 - im->policies; + vlib_increment_combined_counter + (&ipsec_spd_policy_counters, + thread_index, pi0, 1, + clib_net_to_host_u16 (ip0->payload_length) + + header_size); vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; vnet_buffer (b0)->ipsec.flags = 0; next0 = im->ah6_decrypt_next_index; goto trace0; } + else + { + pi0 = ~0; + } } trace0: - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ipsec_input_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); - if (ip0->protocol == IP_PROTOCOL_IPSEC_ESP) - { - if (p0) - tr->sa_id = p0->sa_id; - tr->spi = clib_host_to_net_u32 (esp0->spi); - tr->seq = clib_host_to_net_u32 (esp0->seq); - tr->spd = spd0->id; - } + + if (p0) + tr->sa_id = p0->sa_id; + tr->proto = ip0->protocol; + tr->spi = clib_net_to_host_u32 (esp0->spi); + tr->seq = clib_net_to_host_u32 (esp0->seq); + tr->spd = spd0->id; } vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next, diff --git a/src/vnet/ipsec/ipsec_output.c b/src/vnet/ipsec/ipsec_output.c index 2ab98e7e140..40561269237 100644 --- a/src/vnet/ipsec/ipsec_output.c +++ b/src/vnet/ipsec/ipsec_output.c @@ -48,6 +48,7 @@ static char *ipsec_output_error_strings[] = { typedef struct { u32 spd_id; + u32 policy_id; } ipsec_output_trace_t; /* packet trace format function */ @@ -58,14 +59,8 @@ format_ipsec_output_trace (u8 * s, va_list * args) CLIB_UNUSED (vlib_node_t * node) = va_arg (*args, vlib_node_t *); ipsec_output_trace_t *t = va_arg (*args, ipsec_output_trace_t *); - if (t->spd_id != ~0) - { - s = format (s, "spd %u ", t->spd_id); - } - else - { - s = format (s, "no spd"); - } + s = format (s, "spd %u policy %d", t->spd_id, t->policy_id); + return s; } @@ -73,15 +68,16 @@ always_inline ipsec_policy_t * ipsec_output_policy_match (ipsec_spd_t * spd, u8 pr, u32 la, u32 ra, u16 lp, u16 rp) { + ipsec_main_t *im = &ipsec_main; ipsec_policy_t *p; u32 *i; if (!spd) return 0; - vec_foreach (i, spd->ipv4_outbound_policies) + vec_foreach (i, spd->policies[IPSEC_SPD_POLICY_IP4_OUTBOUND]) { - p = pool_elt_at_index (spd->policies, *i); + p = pool_elt_at_index (im->policies, *i); if (PREDICT_FALSE (p->protocol && (p->protocol != pr))) continue; @@ -134,15 +130,16 @@ ipsec6_output_policy_match (ipsec_spd_t * spd, ip6_address_t * la, ip6_address_t * ra, u16 lp, u16 rp, u8 pr) { + ipsec_main_t *im = &ipsec_main; ipsec_policy_t *p; u32 *i; if (!spd) return 0; - vec_foreach (i, spd->ipv6_outbound_policies) + vec_foreach (i, spd->policies[IPSEC_SPD_POLICY_IP6_OUTBOUND]) { - p = pool_elt_at_index (spd->policies, *i); + p = pool_elt_at_index (im->policies, *i); if (PREDICT_FALSE (p->protocol && (p->protocol != pr))) continue; @@ -181,7 +178,7 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { ipsec_main_t *im = &ipsec_main; - u32 *from, *to_next = 0; + u32 *from, *to_next = 0, thread_index; u32 n_left_from, sw_if_index0, last_sw_if_index = (u32) ~ 0; u32 next_node_index = (u32) ~ 0, last_next_node_index = (u32) ~ 0; vlib_frame_t *f = 0; @@ -192,10 +189,11 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, from = vlib_frame_vector_args (from_frame); n_left_from = from_frame->n_vectors; + thread_index = vm->thread_index; while (n_left_from > 0) { - u32 bi0; + u32 bi0, pi0; vlib_buffer_t *b0; ipsec_policy_t *p0; ip4_header_t *ip0; @@ -203,6 +201,7 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, udp_header_t *udp0; u32 iph_offset = 0; tcp_header_t *tcp0; + u64 bytes0; bi0 = from[0]; b0 = vlib_get_buffer (vm, bi0); @@ -271,6 +270,21 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, if (PREDICT_TRUE (p0 != NULL)) { + pi0 = p0 - im->policies; + + vlib_prefetch_combined_counter (&ipsec_spd_policy_counters, + thread_index, pi0); + + if (is_ipv6) + { + bytes0 = clib_net_to_host_u16 (ip6_0->payload_length); + bytes0 += sizeof (ip6_header_t); + } + else + { + bytes0 = clib_net_to_host_u16 (ip0->length); + } + if (p0->policy == IPSEC_POLICY_ACTION_PROTECT) { ipsec_sa_t *sa = 0; @@ -286,12 +300,9 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, else next_node_index = im->ah4_encrypt_node_index; vnet_buffer (b0)->ipsec.sad_index = p0->sa_index; - p0->counter.packets++; + if (is_ipv6) { - p0->counter.bytes += - clib_net_to_host_u16 (ip6_0->payload_length); - p0->counter.bytes += sizeof (ip6_header_t); if (PREDICT_FALSE (b0->flags & VNET_BUFFER_F_OFFLOAD_TCP_CKSUM)) { @@ -311,7 +322,6 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, } else { - p0->counter.bytes += clib_net_to_host_u16 (ip0->length); if (b0->flags & VNET_BUFFER_F_OFFLOAD_IP_CKSUM) { ip0->checksum = ip4_header_checksum (ip0); @@ -338,37 +348,18 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, { nc_bypass++; next_node_index = get_next_output_feature_node_index (b0, node); - p0->counter.packets++; - if (is_ipv6) - { - p0->counter.bytes += - clib_net_to_host_u16 (ip6_0->payload_length); - p0->counter.bytes += sizeof (ip6_header_t); - } - else - { - p0->counter.bytes += clib_net_to_host_u16 (ip0->length); - } } else { nc_discard++; - p0->counter.packets++; - if (is_ipv6) - { - p0->counter.bytes += - clib_net_to_host_u16 (ip6_0->payload_length); - p0->counter.bytes += sizeof (ip6_header_t); - } - else - { - p0->counter.bytes += clib_net_to_host_u16 (ip0->length); - } next_node_index = im->error_drop_node_index; } + vlib_increment_combined_counter + (&ipsec_spd_policy_counters, thread_index, pi0, 1, bytes0); } else { + pi0 = ~0; nc_nomatch++; next_node_index = im->error_drop_node_index; } @@ -397,12 +388,14 @@ ipsec_output_inline (vlib_main_t * vm, vlib_node_runtime_t * node, to_next += 1; f->n_vectors++; - if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) + if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE) && + PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED)) { ipsec_output_trace_t *tr = vlib_add_trace (vm, node, b0, sizeof (*tr)); if (spd0) tr->spd_id = spd0->id; + tr->policy_id = pi0; } } diff --git a/src/vnet/ipsec/ipsec_sa.c b/src/vnet/ipsec/ipsec_sa.c index a76197b9f50..d439b4d46d3 100644 --- a/src/vnet/ipsec/ipsec_sa.c +++ b/src/vnet/ipsec/ipsec_sa.c @@ -86,19 +86,16 @@ u8 ipsec_is_sa_used (u32 sa_index) { ipsec_main_t *im = &ipsec_main; - ipsec_spd_t *spd; - ipsec_policy_t *p; ipsec_tunnel_if_t *t; + ipsec_policy_t *p; /* *INDENT-OFF* */ - pool_foreach(spd, im->spds, ({ - pool_foreach(p, spd->policies, ({ - if (p->policy == IPSEC_POLICY_ACTION_PROTECT) - { - if (p->sa_index == sa_index) - return 1; - } - })); + pool_foreach(p, im->policies, ({ + if (p->policy == IPSEC_POLICY_ACTION_PROTECT) + { + if (p->sa_index == sa_index) + return 1; + } })); pool_foreach(t, im->tunnel_interfaces, ({ diff --git a/src/vnet/ipsec/ipsec_spd.c b/src/vnet/ipsec/ipsec_spd.c index 7e17bb91fdb..19525b206a6 100644 --- a/src/vnet/ipsec/ipsec_spd.c +++ b/src/vnet/ipsec/ipsec_spd.c @@ -42,12 +42,10 @@ ipsec_add_del_spd (vlib_main_t * vm, u32 spd_id, int is_add) })); /* *INDENT-ON* */ hash_unset (im->spd_index_by_spd_id, spd_id); - pool_free (spd->policies); - vec_free (spd->ipv4_outbound_policies); - vec_free (spd->ipv6_outbound_policies); - vec_free (spd->ipv4_inbound_protect_policy_indices); - vec_free (spd->ipv4_inbound_policy_discard_and_bypass_indices); - pool_put (im->spds, spd); +#define _(s,v) vec_free(spd->policies[IPSEC_SPD_POLICY_##s]); + foreach_ipsec_spd_policy_type +#undef _ + pool_put (im->spds, spd); } else /* create new SPD */ { diff --git a/src/vnet/ipsec/ipsec_spd.h b/src/vnet/ipsec/ipsec_spd.h index 854076ece6d..dd09041b046 100644 --- a/src/vnet/ipsec/ipsec_spd.h +++ b/src/vnet/ipsec/ipsec_spd.h @@ -17,23 +17,34 @@ #include -struct ipsec_policy_t_; +#define foreach_ipsec_spd_policy_type \ + _(IP4_OUTBOUND, "ip4-outbound") \ + _(IP6_OUTBOUND, "ip6-outbound") \ + _(IP4_INBOUND_PROTECT, "ip4-inbound-protect") \ + _(IP6_INBOUND_PROTECT, "ip6-inbound-protect") \ + _(IP4_INBOUND_BYPASS, "ip4-inbound-bypass") \ + _(IP6_INBOUND_BYPASS, "ip6-inbound-bypass") + +typedef enum ipsec_spd_policy_t_ +{ +#define _(s,v) IPSEC_SPD_POLICY_##s, + foreach_ipsec_spd_policy_type +#undef _ + IPSEC_SPD_POLICY_N_TYPES, +} ipsec_spd_policy_t; + +#define FOR_EACH_IPSEC_SPD_POLICY_TYPE(_t) \ + for (_t = 0; _t < IPSEC_SPD_POLICY_N_TYPES; _t++) /** * @brief A Secruity Policy Database */ -typedef struct ipsec_spd_t_ +typedef struct { + /** the User's ID for this policy */ u32 id; - /* pool of policies */ - struct ipsec_policy_t_ *policies; - /* vectors of policy indices */ - u32 *ipv4_outbound_policies; - u32 *ipv6_outbound_policies; - u32 *ipv4_inbound_protect_policy_indices; - u32 *ipv4_inbound_policy_discard_and_bypass_indices; - u32 *ipv6_inbound_protect_policy_indices; - u32 *ipv6_inbound_policy_discard_and_bypass_indices; + /** vectors for each of the policy types */ + u32 *policies[IPSEC_SPD_POLICY_N_TYPES]; } ipsec_spd_t; /** @@ -47,6 +58,8 @@ extern int ipsec_add_del_spd (vlib_main_t * vm, u32 spd_id, int is_add); extern int ipsec_set_interface_spd (vlib_main_t * vm, u32 sw_if_index, u32 spd_id, int is_add); +extern u8 *format_ipsec_spd (u8 * s, va_list * args); + #endif /* __IPSEC_SPD_H__ */ /* diff --git a/src/vnet/ipsec/ipsec_spd_policy.c b/src/vnet/ipsec/ipsec_spd_policy.c index 0a576595a5a..5ad147b934f 100644 --- a/src/vnet/ipsec/ipsec_spd_policy.c +++ b/src/vnet/ipsec/ipsec_spd_policy.c @@ -15,16 +15,81 @@ #include +/** + * @brief + * Policy packet & bytes counters + */ +vlib_combined_counter_main_t ipsec_spd_policy_counters = { + .name = "policy", + .stat_segment_name = "/net/ipsec/policy", +}; + +static int +ipsec_policy_is_equal (ipsec_policy_t * p1, ipsec_policy_t * p2) +{ + if (p1->priority != p2->priority) + return 0; + if (p1->is_outbound != p2->is_outbound) + return (0); + if (p1->policy != p2->policy) + return (0); + if (p1->sa_id != p2->sa_id) + return (0); + if (p1->protocol != p2->protocol) + return (0); + if (p1->lport.start != p2->lport.start) + return (0); + if (p1->lport.stop != p2->lport.stop) + return (0); + if (p1->rport.start != p2->rport.start) + return (0); + if (p1->rport.stop != p2->rport.stop) + return (0); + if (p1->is_ipv6 != p2->is_ipv6) + return (0); + if (p2->is_ipv6) + { + if (p1->laddr.start.ip6.as_u64[0] != p2->laddr.start.ip6.as_u64[0]) + return (0); + if (p1->laddr.start.ip6.as_u64[1] != p2->laddr.start.ip6.as_u64[1]) + return (0); + if (p1->laddr.stop.ip6.as_u64[0] != p2->laddr.stop.ip6.as_u64[0]) + return (0); + if (p1->laddr.stop.ip6.as_u64[1] != p2->laddr.stop.ip6.as_u64[1]) + return (0); + if (p1->raddr.start.ip6.as_u64[0] != p2->raddr.start.ip6.as_u64[0]) + return (0); + if (p1->raddr.start.ip6.as_u64[1] != p2->raddr.start.ip6.as_u64[1]) + return (0); + if (p1->raddr.stop.ip6.as_u64[0] != p2->raddr.stop.ip6.as_u64[0]) + return (0); + if (p1->laddr.stop.ip6.as_u64[1] != p2->laddr.stop.ip6.as_u64[1]) + return (0); + } + else + { + if (p1->laddr.start.ip4.as_u32 != p2->laddr.start.ip4.as_u32) + return (0); + if (p1->laddr.stop.ip4.as_u32 != p2->laddr.stop.ip4.as_u32) + return (0); + if (p1->raddr.start.ip4.as_u32 != p2->raddr.start.ip4.as_u32) + return (0); + if (p1->raddr.stop.ip4.as_u32 != p2->raddr.stop.ip4.as_u32) + return (0); + } + return (1); +} + static int ipsec_spd_entry_sort (void *a1, void *a2) { + ipsec_main_t *im = &ipsec_main; u32 *id1 = a1; u32 *id2 = a2; - ipsec_spd_t *spd = ipsec_main.spd_to_sort; ipsec_policy_t *p1, *p2; - p1 = pool_elt_at_index (spd->policies, *id1); - p2 = pool_elt_at_index (spd->policies, *id2); + p1 = pool_elt_at_index (im->policies, *id1); + p2 = pool_elt_at_index (im->policies, *id2); if (p1 && p2) return p2->priority - p1->priority; @@ -32,13 +97,14 @@ ipsec_spd_entry_sort (void *a1, void *a2) } int -ipsec_add_del_policy (vlib_main_t * vm, ipsec_policy_t * policy, int is_add) +ipsec_add_del_policy (vlib_main_t * vm, + ipsec_policy_t * policy, int is_add, u32 * stat_index) { ipsec_main_t *im = &ipsec_main; ipsec_spd_t *spd = 0; ipsec_policy_t *vp; - uword *p; u32 spd_index; + uword *p; clib_warning ("policy-id %u priority %d is_outbound %u", policy->id, policy->priority, policy->is_outbound); @@ -65,24 +131,30 @@ ipsec_add_del_policy (vlib_main_t * vm, ipsec_policy_t * policy, int is_add) { u32 policy_index; - pool_get (spd->policies, vp); + pool_get (im->policies, vp); clib_memcpy (vp, policy, sizeof (*vp)); - policy_index = vp - spd->policies; + policy_index = vp - im->policies; - ipsec_main.spd_to_sort = spd; + vlib_validate_combined_counter (&ipsec_spd_policy_counters, + policy_index); + vlib_zero_combined_counter (&ipsec_spd_policy_counters, policy_index); if (policy->is_outbound) { if (policy->is_ipv6) { - vec_add1 (spd->ipv6_outbound_policies, policy_index); - vec_sort_with_function (spd->ipv6_outbound_policies, + vec_add1 (spd->policies[IPSEC_SPD_POLICY_IP6_OUTBOUND], + policy_index); + vec_sort_with_function (spd->policies + [IPSEC_SPD_POLICY_IP6_OUTBOUND], ipsec_spd_entry_sort); } else { - vec_add1 (spd->ipv4_outbound_policies, policy_index); - vec_sort_with_function (spd->ipv4_outbound_policies, + vec_add1 (spd->policies[IPSEC_SPD_POLICY_IP4_OUTBOUND], + policy_index); + vec_sort_with_function (spd->policies + [IPSEC_SPD_POLICY_IP4_OUTBOUND], ipsec_spd_entry_sort); } } @@ -92,19 +164,20 @@ ipsec_add_del_policy (vlib_main_t * vm, ipsec_policy_t * policy, int is_add) { if (policy->policy == IPSEC_POLICY_ACTION_PROTECT) { - vec_add1 (spd->ipv6_inbound_protect_policy_indices, + vec_add1 (spd->policies + [IPSEC_SPD_POLICY_IP6_INBOUND_PROTECT], policy_index); - vec_sort_with_function - (spd->ipv6_inbound_protect_policy_indices, - ipsec_spd_entry_sort); + vec_sort_with_function (spd->policies + [IPSEC_SPD_POLICY_IP6_INBOUND_PROTECT], + ipsec_spd_entry_sort); } else { vec_add1 - (spd->ipv6_inbound_policy_discard_and_bypass_indices, + (spd->policies[IPSEC_SPD_POLICY_IP6_INBOUND_BYPASS], policy_index); vec_sort_with_function - (spd->ipv6_inbound_policy_discard_and_bypass_indices, + (spd->policies[IPSEC_SPD_POLICY_IP6_INBOUND_BYPASS], ipsec_spd_entry_sort); } } @@ -112,146 +185,45 @@ ipsec_add_del_policy (vlib_main_t * vm, ipsec_policy_t * policy, int is_add) { if (policy->policy == IPSEC_POLICY_ACTION_PROTECT) { - vec_add1 (spd->ipv4_inbound_protect_policy_indices, + vec_add1 (spd->policies + [IPSEC_SPD_POLICY_IP4_INBOUND_PROTECT], policy_index); - vec_sort_with_function - (spd->ipv4_inbound_protect_policy_indices, - ipsec_spd_entry_sort); + vec_sort_with_function (spd->policies + [IPSEC_SPD_POLICY_IP4_INBOUND_PROTECT], + ipsec_spd_entry_sort); } else { vec_add1 - (spd->ipv4_inbound_policy_discard_and_bypass_indices, + (spd->policies[IPSEC_SPD_POLICY_IP4_INBOUND_BYPASS], policy_index); vec_sort_with_function - (spd->ipv4_inbound_policy_discard_and_bypass_indices, + (spd->policies[IPSEC_SPD_POLICY_IP4_INBOUND_BYPASS], ipsec_spd_entry_sort); } } } - - ipsec_main.spd_to_sort = NULL; + *stat_index = policy_index; } else { - u32 i, j; - /* *INDENT-OFF* */ - pool_foreach_index(i, spd->policies, ({ - vp = pool_elt_at_index(spd->policies, i); - if (vp->priority != policy->priority) - continue; - if (vp->is_outbound != policy->is_outbound) - continue; - if (vp->policy != policy->policy) - continue; - if (vp->sa_id != policy->sa_id) - continue; - if (vp->protocol != policy->protocol) - continue; - if (vp->lport.start != policy->lport.start) - continue; - if (vp->lport.stop != policy->lport.stop) - continue; - if (vp->rport.start != policy->rport.start) - continue; - if (vp->rport.stop != policy->rport.stop) - continue; - if (vp->is_ipv6 != policy->is_ipv6) - continue; - if (policy->is_ipv6) - { - if (vp->laddr.start.ip6.as_u64[0] != policy->laddr.start.ip6.as_u64[0]) - continue; - if (vp->laddr.start.ip6.as_u64[1] != policy->laddr.start.ip6.as_u64[1]) - continue; - if (vp->laddr.stop.ip6.as_u64[0] != policy->laddr.stop.ip6.as_u64[0]) - continue; - if (vp->laddr.stop.ip6.as_u64[1] != policy->laddr.stop.ip6.as_u64[1]) - continue; - if (vp->raddr.start.ip6.as_u64[0] != policy->raddr.start.ip6.as_u64[0]) - continue; - if (vp->raddr.start.ip6.as_u64[1] != policy->raddr.start.ip6.as_u64[1]) - continue; - if (vp->raddr.stop.ip6.as_u64[0] != policy->raddr.stop.ip6.as_u64[0]) - continue; - if (vp->laddr.stop.ip6.as_u64[1] != policy->laddr.stop.ip6.as_u64[1]) - continue; - if (policy->is_outbound) - { - vec_foreach_index(j, spd->ipv6_outbound_policies) { - if (vec_elt(spd->ipv6_outbound_policies, j) == i) { - vec_del1 (spd->ipv6_outbound_policies, j); - break; - } - } - } - else - { - if (policy->policy == IPSEC_POLICY_ACTION_PROTECT) - { - vec_foreach_index(j, spd->ipv6_inbound_protect_policy_indices) { - if (vec_elt(spd->ipv6_inbound_protect_policy_indices, j) == i) { - vec_del1 (spd->ipv6_inbound_protect_policy_indices, j); - break; - } - } - } - else - { - vec_foreach_index(j, spd->ipv6_inbound_policy_discard_and_bypass_indices) { - if (vec_elt(spd->ipv6_inbound_policy_discard_and_bypass_indices, j) == i) { - vec_del1 (spd->ipv6_inbound_policy_discard_and_bypass_indices, j); - break; - } - } - } - } - } - else - { - if (vp->laddr.start.ip4.as_u32 != policy->laddr.start.ip4.as_u32) - continue; - if (vp->laddr.stop.ip4.as_u32 != policy->laddr.stop.ip4.as_u32) - continue; - if (vp->raddr.start.ip4.as_u32 != policy->raddr.start.ip4.as_u32) - continue; - if (vp->raddr.stop.ip4.as_u32 != policy->raddr.stop.ip4.as_u32) - continue; - if (policy->is_outbound) - { - vec_foreach_index(j, spd->ipv4_outbound_policies) { - if (vec_elt(spd->ipv4_outbound_policies, j) == i) { - vec_del1 (spd->ipv4_outbound_policies, j); - break; - } - } - } - else - { - if (policy->policy == IPSEC_POLICY_ACTION_PROTECT) - { - vec_foreach_index(j, spd->ipv4_inbound_protect_policy_indices) { - if (vec_elt(spd->ipv4_inbound_protect_policy_indices, j) == i) { - vec_del1 (spd->ipv4_inbound_protect_policy_indices, j); - break; - } - } - } - else - { - vec_foreach_index(j, spd->ipv4_inbound_policy_discard_and_bypass_indices) { - if (vec_elt(spd->ipv4_inbound_policy_discard_and_bypass_indices, j) == i) { - vec_del1 (spd->ipv4_inbound_policy_discard_and_bypass_indices, j); - break; - } - } - } - } - } - pool_put (spd->policies, vp); - break; - })); - /* *INDENT-ON* */ + ipsec_spd_policy_t ptype; + u32 ii; + + FOR_EACH_IPSEC_SPD_POLICY_TYPE (ptype) + { + vec_foreach_index (ii, (spd->policies[ptype])) + { + vp = pool_elt_at_index (im->policies, spd->policies[ptype][ii]); + if (ipsec_policy_is_equal (vp, policy)) + { + vec_del1 (spd->policies[ptype], ii); + pool_put (im->policies, vp); + goto done; + } + } + } + done:; } return 0; diff --git a/src/vnet/ipsec/ipsec_spd_policy.h b/src/vnet/ipsec/ipsec_spd_policy.h index fee059e0e56..40fad342978 100644 --- a/src/vnet/ipsec/ipsec_spd_policy.h +++ b/src/vnet/ipsec/ipsec_spd_policy.h @@ -42,6 +42,12 @@ typedef struct u16 start, stop; } port_range_t; +/** + * @brief + * Policy packet & bytes counters + */ +extern vlib_combined_counter_main_t ipsec_spd_policy_counters; + /** * @brief A Secruity Policy. An entry in an SPD */ @@ -63,17 +69,16 @@ typedef struct ipsec_policy_t_ ipsec_policy_action_t policy; u32 sa_id; u32 sa_index; - - // Counter - vlib_counter_t counter; } ipsec_policy_t; /** * @brief Add/Delete a SPD */ extern int ipsec_add_del_policy (vlib_main_t * vm, - ipsec_policy_t * policy, int is_add); + ipsec_policy_t * policy, + int is_add, u32 * stat_index); +extern u8 *format_ipsec_policy (u8 * s, va_list * args); extern u8 *format_ipsec_policy_action (u8 * s, va_list * args); extern uword unformat_ipsec_policy_action (unformat_input_t * input, va_list * args); diff --git a/test/template_ipsec.py b/test/template_ipsec.py index 7888a6788ab..77461d4397f 100644 --- a/test/template_ipsec.py +++ b/test/template_ipsec.py @@ -380,6 +380,11 @@ class IpsecTun4Tests(object): self.logger.info(self.vapi.ppcli("show error")) self.logger.info(self.vapi.ppcli("show ipsec")) + if (hasattr(p, "spd_policy_in_any")): + pkts = p.spd_policy_in_any.get_stats()['packets'] + self.assertEqual(pkts, count, + "incorrect SPD any policy: expected %d != %d" % + (count, pkts)) self.assert_packet_counter_equal(self.tun4_encrypt_node_name, count) self.assert_packet_counter_equal(self.tun4_decrypt_node_name, count) diff --git a/test/test_ipsec_ah.py b/test/test_ipsec_ah.py index caec8d431c5..f8add0d3c9c 100644 --- a/test/test_ipsec_ah.py +++ b/test/test_ipsec_ah.py @@ -99,15 +99,19 @@ class TemplateIpsecAh(TemplateIpsec): self.tun_if.remote_addr[addr_type], self.tun_if.local_addr[addr_type]).add_vpp_config() - VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id, - addr_any, addr_bcast, - addr_any, addr_bcast, - socket.IPPROTO_AH).add_vpp_config() - VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id, - addr_any, addr_bcast, - addr_any, addr_bcast, - socket.IPPROTO_AH, - is_outbound=0).add_vpp_config() + params.spd_policy_in_any = VppIpsecSpdEntry(self, self.tun_spd, + vpp_tun_sa_id, + addr_any, addr_bcast, + addr_any, addr_bcast, + socket.IPPROTO_AH) + params.spd_policy_in_any.add_vpp_config() + params.spd_policy_out_any = VppIpsecSpdEntry(self, self.tun_spd, + vpp_tun_sa_id, + addr_any, addr_bcast, + addr_any, addr_bcast, + socket.IPPROTO_AH, + is_outbound=0) + params.spd_policy_out_any.add_vpp_config() VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id, remote_tun_if_host, diff --git a/test/test_ipsec_esp.py b/test/test_ipsec_esp.py index ae62aecc2ed..ba67b60a08e 100644 --- a/test/test_ipsec_esp.py +++ b/test/test_ipsec_esp.py @@ -110,15 +110,19 @@ class TemplateIpsecEsp(TemplateIpsec): self.tun_if.remote_addr[addr_type], self.tun_if.local_addr[addr_type]).add_vpp_config() - VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id, - addr_any, addr_bcast, - addr_any, addr_bcast, - socket.IPPROTO_ESP).add_vpp_config() - VppIpsecSpdEntry(self, self.tun_spd, scapy_tun_sa_id, - addr_any, addr_bcast, - addr_any, addr_bcast, - socket.IPPROTO_ESP, - is_outbound=0).add_vpp_config() + params.spd_policy_in_any = VppIpsecSpdEntry(self, self.tun_spd, + scapy_tun_sa_id, + addr_any, addr_bcast, + addr_any, addr_bcast, + socket.IPPROTO_ESP) + params.spd_policy_in_any.add_vpp_config() + params.spd_policy_out_any = VppIpsecSpdEntry(self, self.tun_spd, + scapy_tun_sa_id, + addr_any, addr_bcast, + addr_any, addr_bcast, + socket.IPPROTO_ESP, + is_outbound=0) + params.spd_policy_out_any.add_vpp_config() VppIpsecSpdEntry(self, self.tun_spd, vpp_tun_sa_id, remote_tun_if_host, remote_tun_if_host, diff --git a/test/vpp_ipsec.py b/test/vpp_ipsec.py index 1218c4bb8bb..69aebc599d6 100644 --- a/test/vpp_ipsec.py +++ b/test/vpp_ipsec.py @@ -111,7 +111,7 @@ class VppIpsecSpdEntry(VppObject): self.remote_port_stop = remote_port_stop def add_vpp_config(self): - self.test.vapi.ipsec_spd_entry_add_del( + rv = self.test.vapi.ipsec_spd_entry_add_del( self.spd.id, self.sa_id, self.local_start, @@ -127,6 +127,7 @@ class VppIpsecSpdEntry(VppObject): local_port_stop=self.local_port_stop, remote_port_start=self.remote_port_start, remote_port_stop=self.remote_port_stop) + self.stat_index = rv.stat_index self.test.registry.register(self, self.test.logger) def remove_vpp_config(self): @@ -171,6 +172,10 @@ class VppIpsecSpdEntry(VppObject): return True return False + def get_stats(self): + c = self.test.statistics.get_counter("/net/ipsec/policy") + return c[0][self.stat_index] + class VppIpsecSA(VppObject): """ -- 2.16.6