aboutsummaryrefslogtreecommitdiffstats
path: root/examples/server_node_efd/server/init.h
blob: 8dc5885bc51387792072484b24b9105145b8701c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*-
 *   BSD LICENSE
 *
 *   Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
 *   All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _INIT_H_
#define _INIT_H_

/*
 * #include <rte_ring.h>
 * #include "args.h"
 */

/*
 * Define a node structure with all needed info, including
 * stats from the nodes.
 */
struct node {
	struct rte_ring *rx_q;
	unsigned int node_id;
	/* these stats hold how many packets the node will actually receive,
	 * and how many packets were dropped because the node's queue was full.
	 * The port-info stats, in contrast, record how many packets were received
	 * or transmitted on an actual NIC port.
	 */
	struct {
		uint64_t rx;
		uint64_t rx_drop;
	} stats;
};

extern struct rte_efd_table *efd_table;
extern struct node *nodes;

/*
 * shared information between server and nodes: number of nodes,
 * port numbers, rx and tx stats etc.
 */
extern struct shared_info *info;

extern struct rte_mempool *pktmbuf_pool;
extern uint8_t num_nodes;
extern unsigned int num_sockets;
extern uint32_t num_flows;

int init(int argc, char *argv[]);

#endif /* ifndef _INIT_H_ */
7'>527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
/*
 *------------------------------------------------------------------
 * Copyright (c) 2022 Intel 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 IPSEC_SPD_FP_LOOKUP_H
#define IPSEC_SPD_FP_LOOKUP_H

#include <vnet/ipsec/ipsec.h>

static_always_inline int
single_rule_out_match_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *match)
{
  if (PREDICT_FALSE (policy->is_ipv6 != match->is_ipv6))
    return (0);

  if (PREDICT_FALSE (policy->protocol != IPSEC_POLICY_PROTOCOL_ANY &&
		     (policy->protocol != match->protocol)))
    return (0);

  if (!policy->is_ipv6)
    {
      if (PREDICT_FALSE (
	    clib_net_to_host_u32 (match->laddr.as_u32) <
	    clib_net_to_host_u32 (policy->laddr.start.ip4.as_u32)))
	return (0);

      if (PREDICT_FALSE (clib_net_to_host_u32 (match->laddr.as_u32) >
			 clib_net_to_host_u32 (policy->laddr.stop.ip4.as_u32)))
	return (0);

      if (PREDICT_FALSE (
	    clib_net_to_host_u32 (match->raddr.as_u32) <
	    clib_net_to_host_u32 (policy->raddr.start.ip4.as_u32)))
	return (0);

      if (PREDICT_FALSE (clib_net_to_host_u32 (match->raddr.as_u32) >
			 clib_net_to_host_u32 (policy->raddr.stop.ip4.as_u32)))
	return (0);
    }
  else
    {

      if (ip6_address_compare (&match->ip6_laddr, &policy->laddr.start.ip6) <
	  0)
	return (0);

      if (ip6_address_compare (&policy->laddr.stop.ip6, &match->ip6_laddr) < 0)

	return (0);

      if (ip6_address_compare (&match->ip6_raddr, &policy->raddr.start.ip6) <
	  0)

	return (0);

      if (ip6_address_compare (&policy->raddr.stop.ip6, &match->ip6_raddr) < 0)

	return (0);
    }

  if (PREDICT_FALSE ((match->protocol != IP_PROTOCOL_TCP) &&
		     (match->protocol != IP_PROTOCOL_UDP) &&
		     (match->protocol != IP_PROTOCOL_SCTP)))
    {
      return (1);
    }

  if (match->lport < policy->lport.start)
    return (0);

  if (match->lport > policy->lport.stop)
    return (0);

  if (match->rport < policy->rport.start)
    return (0);

  if (match->rport > policy->rport.stop)
    return (0);

  return (1);
}

static_always_inline int
single_rule_in_match_5tuple (ipsec_policy_t *policy, ipsec_fp_5tuple_t *match)
{

  u32 da = clib_net_to_host_u32 (match->laddr.as_u32);
  u32 sa = clib_net_to_host_u32 (match->raddr.as_u32);

  if (policy->policy == IPSEC_POLICY_ACTION_PROTECT)
    {
      ipsec_sa_t *s = ipsec_sa_get (policy->sa_index);

      if (match->spi != s->spi)
	return (0);

      if (ipsec_sa_is_set_IS_TUNNEL (s))
	{
	  if (da != clib_net_to_host_u32 (s->tunnel.t_dst.ip.ip4.as_u32))
	    return (0);

	  if (sa != clib_net_to_host_u32 (s->tunnel.t_src.ip.ip4.as_u32))
	    return (0);
	}
    }
  else
    {
      if (sa < clib_net_to_host_u32 (policy->raddr.start.ip4.as_u32))
	return (0);

      if (sa > clib_net_to_host_u32 (policy->raddr.stop.ip4.as_u32))
	return (0);

      if (da < clib_net_to_host_u32 (policy->laddr.start.ip4.as_u32))
	return (0);

      if (da > clib_net_to_host_u32 (policy->laddr.stop.ip4.as_u32))
	return (0);
    }
  return (1);
}

static_always_inline u32
ipsec_fp_in_ip6_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
				ipsec_policy_t **policies, u32 n)
{
  u32 last_priority[n];
  u32 i = 0;
  u32 counter = 0;
  ipsec_fp_mask_type_entry_t *mte;
  ipsec_fp_mask_id_t *mti;
  ipsec_fp_5tuple_t *match = tuples;
  ipsec_policy_t *policy;
  u32 n_left = n;
  clib_bihash_kv_40_8_t kv;
  /* result of the lookup */
  clib_bihash_kv_40_8_t result;
  ipsec_fp_lookup_value_t *result_val =
    (ipsec_fp_lookup_value_t *) &result.value;
  u64 *pkey, *pmatch, *pmask;
  ipsec_main_t *im = &ipsec_main;
  ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
  ipsec_fp_mask_id_t *mask_type_ids = pspd_fp->fp_mask_ids[match->action];
  clib_bihash_40_8_t *bihash_table = pool_elt_at_index (
    im->fp_ip6_lookup_hashes_pool, pspd_fp->ip6_in_lookup_hash_idx);

  /* clear the list of matched policies pointers */
  clib_memset (policies, 0, n * sizeof (*policies));
  clib_memset (last_priority, 0, n * sizeof (u32));
  n_left = n;
  while (n_left)
    {
      vec_foreach (mti, mask_type_ids)
	{
	  mte = im->fp_mask_types + mti->mask_type_idx;
	  if (mte->mask.action == 0)
	    continue;

	  pmatch = (u64 *) match->kv_40_8.key;
	  pmask = (u64 *) mte->mask.kv_40_8.key;
	  pkey = (u64 *) kv.key;

	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey = *pmatch & *pmask;

	  int res =
	    clib_bihash_search_inline_2_40_8 (bihash_table, &kv, &result);
	  /* lookup the hash by each packet in the burst for this mask. */

	  if (res == 0)
	    {
	      /* There is a hit in the hash table. */
	      /* Find the policy with highest priority. */
	      /* Store the lookup results in a dedicated array. */

	      if (vec_len (result_val->fp_policies_ids) > 1)
		{
		  u32 *policy_id;
		  vec_foreach (policy_id, result_val->fp_policies_ids)
		    {
		      policy = im->policies + *policy_id;

		      if ((last_priority[i] < policy->priority) &&
			  (single_rule_in_match_5tuple (policy, match)))
			{
			  last_priority[i] = policy->priority;
			  if (policies[i] == 0)
			    counter++;
			  policies[i] = policy;
			}
		    }
		}
	      else
		{
		  u32 *policy_id;
		  ASSERT (vec_len (result_val->fp_policies_ids) == 1);
		  policy_id = result_val->fp_policies_ids;
		  policy = im->policies + *policy_id;
		  if ((last_priority[i] < policy->priority) &&
		      (single_rule_in_match_5tuple (policy, match)))
		    {
		      last_priority[i] = policy->priority;
		      if (policies[i] == 0)
			counter++;
		      policies[i] = policy;
		    }
		}
	    }
	}

      i++;
      n_left--;
      match++;
    }
  return counter;
}

static_always_inline u32
ipsec_fp_in_ip4_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
				ipsec_policy_t **policies, u32 n)

{
  u32 last_priority[n];
  u32 i = 0;
  u32 counter = 0;
  ipsec_fp_mask_type_entry_t *mte;
  ipsec_fp_mask_id_t *mti;
  ipsec_fp_5tuple_t *match = tuples;
  ipsec_policy_t *policy;
  u32 n_left = n;
  clib_bihash_kv_16_8_t kv;
  /* result of the lookup */
  clib_bihash_kv_16_8_t result;
  ipsec_fp_lookup_value_t *result_val =
    (ipsec_fp_lookup_value_t *) &result.value;
  u64 *pkey, *pmatch, *pmask;
  ipsec_main_t *im = &ipsec_main;
  ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
  ipsec_fp_mask_id_t *mask_type_ids = pspd_fp->fp_mask_ids[match->action];
  clib_bihash_16_8_t *bihash_table = pool_elt_at_index (
    im->fp_ip4_lookup_hashes_pool, pspd_fp->ip4_in_lookup_hash_idx);

  /* clear the list of matched policies pointers */
  clib_memset (policies, 0, n * sizeof (*policies));
  clib_memset (last_priority, 0, n * sizeof (u32));
  n_left = n;
  while (n_left)
    {
      vec_foreach (mti, mask_type_ids)
	{
	  mte = im->fp_mask_types + mti->mask_type_idx;
	  if (mte->mask.action == 0)
	    continue;
	  pmatch = (u64 *) match->kv_16_8.key;
	  pmask = (u64 *) mte->mask.kv_16_8.key;
	  pkey = (u64 *) kv.key;

	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey = *pmatch & *pmask;

	  int res =
	    clib_bihash_search_inline_2_16_8 (bihash_table, &kv, &result);
	  /* lookup the hash by each packet in the burst for this mask. */

	  if (res == 0)
	    {
	      /* There is a hit in the hash table. */
	      /* Find the policy with highest priority. */
	      /* Store the lookup results in a dedicated array. */

	      if (vec_len (result_val->fp_policies_ids) > 1)
		{
		  u32 *policy_id;
		  vec_foreach (policy_id, result_val->fp_policies_ids)
		    {
		      policy = im->policies + *policy_id;

		      if ((last_priority[i] < policy->priority) &&
			  (single_rule_in_match_5tuple (policy, match)))
			{
			  last_priority[i] = policy->priority;
			  if (policies[i] == 0)
			    counter++;
			  policies[i] = policy;
			}
		    }
		}
	      else
		{
		  u32 *policy_id;
		  ASSERT (vec_len (result_val->fp_policies_ids) == 1);
		  policy_id = result_val->fp_policies_ids;
		  policy = im->policies + *policy_id;
		  if ((last_priority[i] < policy->priority) &&
		      (single_rule_in_match_5tuple (policy, match)))
		    {
		      last_priority[i] = policy->priority;
		      if (policies[i] == 0)
			counter++;
		      policies[i] = policy;
		    }
		}
	    }
	}

      i++;
      n_left--;
      match++;
    }
  return counter;
}

/**
 * @brief function handler to perform lookup in fastpath SPD
 * for inbound traffic burst of n packets
 **/

static_always_inline u32
ipsec_fp_in_policy_match_n (void *spd_fp, u8 is_ipv6,
			    ipsec_fp_5tuple_t *tuples,
			    ipsec_policy_t **policies, u32 n)
{
  if (is_ipv6)
    return ipsec_fp_in_ip6_policy_match_n (spd_fp, tuples, policies, n);
  else
    return ipsec_fp_in_ip4_policy_match_n (spd_fp, tuples, policies, n);
}

static_always_inline u32
ipsec_fp_out_ip6_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
				 ipsec_policy_t **policies, u32 *ids, u32 n)

{
  u32 last_priority[n];
  u32 i = 0;
  u32 counter = 0;
  ipsec_fp_mask_type_entry_t *mte;
  ipsec_fp_mask_id_t *mti;
  ipsec_fp_5tuple_t *match = tuples;
  ipsec_policy_t *policy;

  u32 n_left = n;
  clib_bihash_kv_40_8_t kv;
  /* result of the lookup */
  clib_bihash_kv_40_8_t result;
  ipsec_fp_lookup_value_t *result_val =
    (ipsec_fp_lookup_value_t *) &result.value;
  u64 *pkey, *pmatch, *pmask;
  ipsec_main_t *im = &ipsec_main;
  ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
  ipsec_fp_mask_id_t *mask_type_ids =
    pspd_fp->fp_mask_ids[IPSEC_SPD_POLICY_IP6_OUTBOUND];
  clib_bihash_40_8_t *bihash_table = pool_elt_at_index (
    im->fp_ip6_lookup_hashes_pool, pspd_fp->ip6_out_lookup_hash_idx);

  /*clear the list of matched policies pointers */
  clib_memset (policies, 0, n * sizeof (*policies));
  clib_memset (last_priority, 0, n * sizeof (u32));
  n_left = n;
  while (n_left)
    {
      vec_foreach (mti, mask_type_ids)
	{
	  mte = im->fp_mask_types + mti->mask_type_idx;
	  if (mte->mask.action != 0)
	    continue;

	  pmatch = (u64 *) match->kv_40_8.key;
	  pmask = (u64 *) mte->mask.kv_40_8.key;
	  pkey = (u64 *) kv.key;

	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey = *pmatch & *pmask;

	  int res =
	    clib_bihash_search_inline_2_40_8 (bihash_table, &kv, &result);
	  /* lookup the hash by each packet in the burst for this mask. */

	  if (res == 0)
	    {
	      /* There is a hit in the hash table. */
	      /* Find the policy with highest priority. */
	      /* Store the lookup results in a dedicated array. */

	      if (vec_len (result_val->fp_policies_ids) > 1)
		{
		  u32 *policy_id;
		  vec_foreach (policy_id, result_val->fp_policies_ids)
		    {
		      policy = im->policies + *policy_id;

		      if (single_rule_out_match_5tuple (policy, match))
			{
			  if (last_priority[i] < policy->priority)
			    {
			      last_priority[i] = policy->priority;
			      if (policies[i] == 0)
				counter++;
			      policies[i] = policy;
			      ids[i] = *policy_id;
			    }
			}
		    }
		}
	      else
		{
		  u32 *policy_id;
		  ASSERT (vec_len (result_val->fp_policies_ids) == 1);
		  policy_id = result_val->fp_policies_ids;
		  policy = im->policies + *policy_id;
		  if (single_rule_out_match_5tuple (policy, match))
		    {
		      if (last_priority[i] < policy->priority)
			{
			  last_priority[i] = policy->priority;
			  if (policies[i] == 0)
			    counter++;
			  policies[i] = policy;
			  ids[i] = *policy_id;
			}
		    }
		}
	    }
	}
      n_left--;
      match++;
      i++;
    }
  return counter;
}

static_always_inline u32
ipsec_fp_out_ip4_policy_match_n (void *spd_fp, ipsec_fp_5tuple_t *tuples,
				 ipsec_policy_t **policies, u32 *ids, u32 n)

{
  u32 last_priority[n];
  u32 i = 0;
  u32 counter = 0;
  ipsec_fp_mask_type_entry_t *mte;
  ipsec_fp_mask_id_t *mti;
  ipsec_fp_5tuple_t *match = tuples;
  ipsec_policy_t *policy;

  u32 n_left = n;
  clib_bihash_kv_16_8_t kv;
  /* result of the lookup */
  clib_bihash_kv_16_8_t result;
  ipsec_fp_lookup_value_t *result_val =
    (ipsec_fp_lookup_value_t *) &result.value;
  u64 *pkey, *pmatch, *pmask;
  ipsec_main_t *im = &ipsec_main;
  ipsec_spd_fp_t *pspd_fp = (ipsec_spd_fp_t *) spd_fp;
  ipsec_fp_mask_id_t *mask_type_ids =
    pspd_fp->fp_mask_ids[IPSEC_SPD_POLICY_IP4_OUTBOUND];
  clib_bihash_16_8_t *bihash_table = pool_elt_at_index (
    im->fp_ip4_lookup_hashes_pool, pspd_fp->ip4_out_lookup_hash_idx);

  /* clear the list of matched policies pointers */
  clib_memset (policies, 0, n * sizeof (*policies));
  clib_memset (last_priority, 0, n * sizeof (u32));
  n_left = n;
  while (n_left)
    {
      vec_foreach (mti, mask_type_ids)
	{
	  mte = im->fp_mask_types + mti->mask_type_idx;
	  if (mte->mask.action != 0)
	    continue;

	  pmatch = (u64 *) match->kv_16_8.key;
	  pmask = (u64 *) mte->mask.kv_16_8.key;
	  pkey = (u64 *) kv.key;

	  *pkey++ = *pmatch++ & *pmask++;
	  *pkey = *pmatch & *pmask;

	  int res =
	    clib_bihash_search_inline_2_16_8 (bihash_table, &kv, &result);
	  /* lookup the hash by each packet in the burst for this mask. */

	  if (res == 0)
	    {
	      /* There is a hit in the hash table. */
	      /* Find the policy with highest priority. */
	      /* Store the lookup results in a dedicated array. */

	      if (vec_len (result_val->fp_policies_ids) > 1)
		{
		  u32 *policy_id;
		  vec_foreach (policy_id, result_val->fp_policies_ids)
		    {
		      policy = im->policies + *policy_id;

		      if ((last_priority[i] < policy->priority) &&
			  (single_rule_out_match_5tuple (policy, match)))
			{
			  last_priority[i] = policy->priority;
			  if (policies[i] == 0)
			    counter++;
			  policies[i] = policy;
			  ids[i] = *policy_id;
			}
		    }
		}
	      else
		{
		  u32 *policy_id;
		  ASSERT (vec_len (result_val->fp_policies_ids) == 1);
		  policy_id = result_val->fp_policies_ids;
		  policy = im->policies + *policy_id;
		  if ((last_priority[i] < policy->priority) &&
		      (single_rule_out_match_5tuple (policy, match)))
		    {
		      last_priority[i] = policy->priority;
		      if (policies[i] == 0)
			counter++;
		      policies[i] = policy;
		      ids[i] = *policy_id;
		    }
		}
	    }
	}

      i++;
      n_left--;
      match++;
    }
  return counter;
}

/**
 * @brief function handler to perform lookup in fastpath SPD
 * for outbound traffic burst of n packets
 * returns number of successfully matched policies
 **/

static_always_inline u32
ipsec_fp_out_policy_match_n (void *spd_fp, u8 is_ipv6,
			     ipsec_fp_5tuple_t *tuples,
			     ipsec_policy_t **policies, u32 *ids, u32 n)

{
  if (is_ipv6)
    return ipsec_fp_out_ip6_policy_match_n (spd_fp, tuples, policies, ids, n);
  else
    return ipsec_fp_out_ip4_policy_match_n (spd_fp, tuples, policies, ids, n);
}

#endif /* !IPSEC_SPD_FP_LOOKUP_H */