.. _aclwithvpp: Access Control Lists (ACLs) with FD.io VPP ========================================== This section is overview of the options available to implement ACLs in FD.io VPP. As there are a number of way's to address ACL-like functionality, it is worth a separate survey of these options with some commentary on features and performance All performance numbers and examples from this document are reused from the `FD.io CSIT v19.04 performance report `__ All information and performance is accurate for `FD.io VPP 19.04 `__ release. The sections *performance* & *operational data* below correlate directly with those sections from the FD.io CSIT performance report. Summary ------- +---------------------+-----------+-----------------------------------+ | Option | Relative | Features & Notes | | | Performan | | | | ce | | +=====================+===========+===================================+ | :ref:`aclplugin` | Lowest | Match on restricted L2-L4 fields, | | | | stateful & stateless | +---------------------+-----------+-----------------------------------+ | :ref:`vppcop` | Highest | Match on Layer 3 IPs, stateless | | | (software | | | | only) | | +---------------------+-----------+-----------------------------------+ | :ref:`vppflow` | Highest | Match on restricted L2-L4 fields, | | | (accelera | stateless, limited number of | | | ted) | flows | +---------------------+-----------+-----------------------------------+ | :ref:`classifiers` | TBD | Match on any field in the first | | | | 80 bytes, Not measured | +---------------------+-----------+-----------------------------------+ FD.io VPP ACL Options --------------------- .. _aclplugin: The FD.io VPP ACL Plugin ~~~~~~~~~~~~~~~~~~~~~~~~ The plugin was originally developed as part of FD.io VPP and OpenStack integration. The plugin needs to be enabled on specific interfaces. Supports stateful and stateless ACLs on … """""""""""""""""""""""""""""""""""""""""" - MACs - IPS - UDP Ports - TCP Ports & Flags - ICMP Messages Directional """"""""""" * Input ACLs * Run before the IP flow classification. * ACLs * Run before interface output. Actions """"""" - Permit (sl) - Drop (sf) - Permit+Reflect (sf) Stateful (sf) """"""""""""" - Actions: permit+reflect - Most heavily optimized, as are the most common use case. - Faster because stateful uses a flow cache, it means the ACL hit is only taken once, up front for the flow and then becomes just look-up. - Uses more memory, less deterministic as the flow cache makes it more susceptible to the effects of the memory hierarchy and locality. Stateless (sl) """""""""""""" - Actions : permit, drop - Less optimized, less common use case. - Slower as there is no flow-cache, every new packet incurs the same amount ACL processing. - Uses less memory, and are more deterministic (compared to stateful). Operational Data ---------------- Input/Stateless ~~~~~~~~~~~~~~~ Test Case: 10ge2p1x520-ethip4udp-ip4base-iacl1sl-10kflows-ndrpdr """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. code-block:: console DUT1: Thread 0 vpp_main (lcore 1) Time 3.8, average vectors/node 0.00, last 128 main loops 0.00 per node 0.00 vector rates in 0.0000e0, out 0.0000e0, drop 0.0000e0, punt 0.0000e0 Name State Calls Vectors Suspends Clocks Vectors/Call acl-plugin-fa-cleaner-process any wait 0 0 14 1.29e3 0.00 acl-plugin-fa-worker-cleaner-pinterrupt wa 7 0 0 9.18e2 0.00 api-rx-from-ring active 0 0 52 8.96e4 0.00 dpdk-process any wait 0 0 1 1.35e4 0.00 fib-walk any wait 0 0 2 2.69e3 0.00 ip6-icmp-neighbor-discovery-ev any wait 0 0 4 1.32e3 0.00 lisp-retry-service any wait 0 0 2 2.90e3 0.00 unix-epoll-input polling 7037 0 0 1.25e6 0.00 vpe-oam-process any wait 0 0 2 2.28e3 0.00 Thread 1 vpp_wk_0 (lcore 2) Time 3.8, average vectors/node 249.02, last 128 main loops 32.00 per node 273.07 vector rates in 6.1118e6, out 6.1118e6, drop 0.0000e0, punt 0.0000e0 Name State Calls Vectors Suspends Clocks Vectors/Call TenGigabitEtherneta/0/0-output active 47106 11721472 0 9.47e0 248.83 TenGigabitEtherneta/0/0-tx active 47106 11721472 0 4.22e1 248.83 TenGigabitEtherneta/0/1-output active 47106 11721472 0 1.02e1 248.83 TenGigabitEtherneta/0/1-tx active 47106 11721472 0 4.18e1 248.83 acl-plugin-fa-worker-cleaner-pinterrupt wa 7 0 0 1.39e3 0.00 acl-plugin-in-ip4-fa active 94107 23442944 0 1.75e2 249.11 dpdk-input polling 47106 23442944 0 4.64e1 497.66 ethernet-input active 94212 23442944 0 1.55e1 248.83 ip4-input-no-checksum active 94107 23442944 0 3.23e1 249.11 ip4-lookup active 94107 23442944 0 2.91e1 249.11 ip4-rewrite active 94107 23442944 0 2.48e1 249.11 unix-epoll-input polling 46 0 0 1.54e3 0.00 Input/Stateful ~~~~~~~~~~~~~~ Test Case: 64b-1t1c-ethip4udp-ip4base-iacl1sf-10kflows-ndrpdr """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. code-block:: console DUT1: Thread 0 vpp_main (lcore 1) Time 3.9, average vectors/node 0.00, last 128 main loops 0.00 per node 0.00 vector rates in 0.0000e0, out 0.0000e0, drop 0.0000e0, punt 0.0000e0 Name State Calls Vectors Suspends Clocks Vectors/Call acl-plugin-fa-cleaner-process any wait 0 0 16 1.40e3 0.00 acl-plugin-fa-worker-cleaner-pinterrupt wa 8 0 0 8.97e2 0.00 api-rx-from-ring active 0 0 52 7.12e4 0.00 dpdk-process any wait 0 0 1 1.69e4 0.00 fib-walk any wait 0 0 2 2.55e3 0.00 ip4-reassembly-expire-walk any wait 0 0 1 1.27e4 0.00 ip6-icmp-neighbor-discovery-ev any wait 0 0 4 1.09e3 0.00 ip6-reassembly-expire-walk any wait 0 0 1 2.57e3 0.00 lisp-retry-service any wait 0 0 2 1.18e4 0.00 statseg-collector-process time wait 0 0 1 6.38e3 0.00 unix-epoll-input polling 6320 0 0 1.41e6 0.00 vpe-oam-process any wait 0 0 2 7.53e3 0.00 Thread 1 vpp_wk_0 (lcore 2) Time 3.9, average vectors/node 252.74, last 128 main loops 32.00 per node 273.07 vector rates in 7.5833e6, out 7.5833e6, drop 0.0000e0, punt 0.0000e0 Name State Calls Vectors Suspends Clocks Vectors/Call TenGigabitEtherneta/0/0-output active 58325 14738944 0 9.41e0 252.70 TenGigabitEtherneta/0/0-tx active 58325 14738944 0 4.32e1 252.70 TenGigabitEtherneta/0/1-output active 58323 14738944 0 1.02e1 252.71 TenGigabitEtherneta/0/1-tx active 58323 14738944 0 4.31e1 252.71 acl-plugin-fa-worker-cleaner-pinterrupt wa 8 0 0 1.62e3 0.00 acl-plugin-in-ip4-fa active 116628 29477888 0 1.01e2 252.75 dpdk-input polling 58325 29477888 0 4.63e1 505.41 ethernet-input active 116648 29477888 0 1.53e1 252.71 ip4-input-no-checksum active 116628 29477888 0 3.21e1 252.75 ip4-lookup active 116628 29477888 0 2.90e1 252.75 ip4-rewrite active 116628 29477888 0 2.48e1 252.75 unix-epoll-input polling 57 0 0 2.39e3 0.00 Output/Stateless ~~~~~~~~~~~~~~~~ Test Case: 64b-1t1c-ethip4udp-ip4base-oacl10sl-10kflows-ndrpdr """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .. code-block:: console DUT1: Thread 0 vpp_main (lcore 1) Time 3.8, average vectors/node 0.00, last 128 main loops 0.00 per node 0.00 vector rates in 0.0000e0, out 0.0000e0, drop 0.0000e0, punt 0.0000e0 Name State Calls Vectors Suspends Clocks Vectors/Call acl-plugin-fa-cleaner-process any wait 0
/*
 * Copyright (c) 2015 Cisco and/or its affiliates.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __ESP_H__
#define __ESP_H__

#include <vnet/ip/ip.h>
#include <vnet/crypto/crypto.h>
#include <vnet/ipsec/ipsec.h>

typedef struct
{
  union
  {
    u32 spi;
    u8 spi_bytes[4];
  };
  u32 seq;
  u8 data[0];
} esp_header_t;

typedef struct
{
  u8 pad_length;
  u8 next_header;
} esp_footer_t;

/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
  ip4_header_t ip4;
  esp_header_t esp;
}) ip4_and_esp_header_t;
/* *INDENT-ON* */

/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
  ip4_header_t ip4;
  udp_header_t udp;
  esp_header_t esp;
}) ip4_and_udp_and_esp_header_t;
/* *INDENT-ON* */

/* *INDENT-OFF* */
typedef CLIB_PACKED (struct {
  ip6_header_t ip6;
  esp_header_t esp;
}) ip6_and_esp_header_t;
/* *INDENT-ON* */

/**
 * AES GCM Additional Authentication data
 */
typedef struct esp_aead_t_
{
  /**
   * for GCM: when using ESN it's:
   *   SPI, seq-hi, seg-low
   * else
   *   SPI, seq-low
   */
  u32 data[3];
} __clib_packed esp_aead_t;

#define ESP_SEQ_MAX		(4294967295UL)
#define ESP_MAX_BLOCK_SIZE	(16)
#define ESP_MAX_IV_SIZE		(16)
#define ESP_MAX_ICV_SIZE	(32)

u8 *format_esp_header (u8 * s, va_list * args);

/* TODO seq increment should be atomic to be accessed by multiple workers */
always_inline int
esp_seq_advance (ipsec_sa_t * sa)
{
  if (PREDICT_TRUE (ipsec_sa_is_set_USE_ESN (sa)))
    {
      if (PREDICT_FALSE (sa->seq == ESP_SEQ_MAX))
	{
	  if (PREDICT_FALSE (ipsec_sa_is_set_USE_ANTI_REPLAY (sa) &&
			     sa->seq_hi == ESP_SEQ_MAX))
	    return 1;
	  sa->seq_hi++;
	}
      sa->seq++;
    }
  else
    {
      if (PREDICT_FALSE (ipsec_sa_is_set_USE_ANTI_REPLAY (sa) &&
			 sa->seq == ESP_SEQ_MAX))
	return 1;
      sa->seq++;
    }

  return 0;
}

always_inline u16
esp_aad_fill (u8 * data, const esp_header_t * esp, const ipsec_sa_t * sa)
{
  esp_aead_t *aad;

  aad = (esp_aead_t *) data;
  aad->data[0] =