LCOV - code coverage report
Current view: top level - vnet/adj - adj.h (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 6 6 100.0 %
Date: 2023-10-26 01:39:38 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2016 Cisco and/or its affiliates.
       3             :  * Licensed under the Apache License, Version 2.0 (the "License");
       4             :  * you may not use this file except in compliance with the License.
       5             :  * You may obtain a copy of the License at:
       6             :  *
       7             :  *     http://www.apache.org/licenses/LICENSE-2.0
       8             :  *
       9             :  * Unless required by applicable law or agreed to in writing, software
      10             :  * distributed under the License is distributed on an "AS IS" BASIS,
      11             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             :  * See the License for the specific language governing permissions and
      13             :  * limitations under the License.
      14             :  */
      15             : /**
      16             :  * An adjacency is a representation of an attached L3 peer.
      17             :  *
      18             :  * Adjacency Sub-types:
      19             :  *   - neighbour: a representation of an attached L3 peer.
      20             :  *                Key:{addr,interface,link/ether-type}
      21             :  *           SHARED
      22             :  *   - glean: used to drive ARP/ND for packets destined to a local sub-net.
      23             :  *            'glean' mean use the packet's destination address as the target
      24             :  *            address in the ARP packet.
      25             :  *          UNSHARED. Only one per-interface.
      26             :  *   - midchain: a neighbour adj on a virtual/tunnel interface.
      27             :  *
      28             :  * The API to create and update the adjacency is very sub-type specific. This
      29             :  * is intentional as it encourages the user to carefully consider which adjacency
      30             :  * sub-type they are really using, and hence assign it data in the appropriate
      31             :  * sub-type space in the union of sub-types. This prevents the adj becoming a
      32             :  * disorganised dumping group for 'my features needs a u16 somewhere' data. It
      33             :  * is important to enforce this approach as space in the adjacency is a premium,
      34             :  * as we need it to fit in 1 cache line.
      35             :  *
      36             :  * the API is also based around an index to an adjacency not a raw pointer. This
      37             :  * is so the user doesn't suffer the same limp inducing firearm injuries that
      38             :  * the author suffered as the adjacencies can realloc.
      39             :  */
      40             : 
      41             : #ifndef __ADJ_H__
      42             : #define __ADJ_H__
      43             : 
      44             : #include <vnet/adj/adj_types.h>
      45             : #include <vnet/adj/adj_nbr.h>
      46             : #include <vnet/adj/adj_glean.h>
      47             : #include <vnet/adj/rewrite.h>
      48             : 
      49             : /** @brief Common (IP4/IP6) next index stored in adjacency. */
      50             : typedef enum
      51             : {
      52             :   /** Adjacency to drop this packet. */
      53             :   IP_LOOKUP_NEXT_DROP,
      54             :   /** Adjacency to punt this packet. */
      55             :   IP_LOOKUP_NEXT_PUNT,
      56             : 
      57             :   /** This packet is for one of our own IP addresses. */
      58             :   IP_LOOKUP_NEXT_LOCAL,
      59             : 
      60             :   /** This packet matches an "incomplete adjacency" and packets
      61             :      need to be passed to ARP to find rewrite string for
      62             :      this destination. */
      63             :   IP_LOOKUP_NEXT_ARP,
      64             : 
      65             :   /** This packet matches an "interface route" and packets
      66             :      need to be passed to ARP to find rewrite string for
      67             :      this destination. */
      68             :   IP_LOOKUP_NEXT_GLEAN,
      69             : 
      70             :   /** This packet is to be rewritten and forwarded to the next
      71             :      processing node.  This is typically the output interface but
      72             :      might be another node for further output processing. */
      73             :   IP_LOOKUP_NEXT_REWRITE,
      74             : 
      75             :   /** This packets follow a mid-chain adjacency */
      76             :   IP_LOOKUP_NEXT_MIDCHAIN,
      77             : 
      78             :   /** This packets needs to go to ICMP error */
      79             :   IP_LOOKUP_NEXT_ICMP_ERROR,
      80             : 
      81             :   /** Multicast Adjacency. */
      82             :   IP_LOOKUP_NEXT_MCAST,
      83             : 
      84             :   /** Broadcast Adjacency. */
      85             :   IP_LOOKUP_NEXT_BCAST,
      86             : 
      87             :   /** Multicast Midchain Adjacency. An Adjacency for sending multicast packets
      88             :    *  on a tunnel/virtual interface */
      89             :   IP_LOOKUP_NEXT_MCAST_MIDCHAIN,
      90             : 
      91             :   IP_LOOKUP_N_NEXT,
      92             : } __attribute__ ((packed)) ip_lookup_next_t;
      93             : 
      94             : typedef enum
      95             : {
      96             :   IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT,
      97             : } ip4_lookup_next_t;
      98             : 
      99             : typedef enum
     100             : {
     101             :   /* Hop-by-hop header handling */
     102             :   IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT,
     103             :   IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP,
     104             :   IP6_LOOKUP_NEXT_POP_HOP_BY_HOP,
     105             :   IP6_LOOKUP_N_NEXT,
     106             : } ip6_lookup_next_t;
     107             : 
     108             : #define IP4_LOOKUP_NEXT_NODES {                                 \
     109             :     [IP_LOOKUP_NEXT_DROP] = "ip4-drop",                               \
     110             :     [IP_LOOKUP_NEXT_PUNT] = "ip4-punt",                               \
     111             :     [IP_LOOKUP_NEXT_LOCAL] = "ip4-local",                     \
     112             :     [IP_LOOKUP_NEXT_ARP] = "ip4-arp",                         \
     113             :     [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean",                     \
     114             :     [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite",                 \
     115             :     [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast",             \
     116             :     [IP_LOOKUP_NEXT_BCAST] = "ip4-rewrite-bcast",               \
     117             :     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain",                       \
     118             :     [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain",     \
     119             :     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error",           \
     120             : }
     121             : 
     122             : #define IP6_LOOKUP_NEXT_NODES {                                 \
     123             :     [IP_LOOKUP_NEXT_DROP] = "ip6-drop",                               \
     124             :     [IP_LOOKUP_NEXT_PUNT] = "ip6-punt",                               \
     125             :     [IP_LOOKUP_NEXT_LOCAL] = "ip6-local",                     \
     126             :     [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor",           \
     127             :     [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean",                     \
     128             :     [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite",                 \
     129             :     [IP_LOOKUP_NEXT_BCAST] = "ip6-rewrite-bcast",             \
     130             :     [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast",             \
     131             :     [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain",                       \
     132             :     [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain",     \
     133             :     [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error",           \
     134             :     [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop",          \
     135             :     [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop",  \
     136             :     [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop",  \
     137             : }
     138             : 
     139             : /**
     140             :  * The special broadcast address (to construct a broadcast adjacency
     141             :  */
     142             : extern const ip46_address_t ADJ_BCAST_ADDR;
     143             : 
     144             : /**
     145             :  * Forward declaration
     146             :  */
     147             : struct ip_adjacency_t_;
     148             : 
     149             : /**
     150             :  * @brief A function type for post-rewrite fixups on midchain adjacency
     151             :  */
     152             : typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm,
     153             :                                       const struct ip_adjacency_t_ * adj,
     154             :                                       vlib_buffer_t * b0,
     155             :                                       const void *data);
     156             : 
     157             : /**
     158             :  * @brief Flags on an IP adjacency
     159             :  */
     160             : typedef enum adj_attr_t_
     161             : {
     162             :     /**
     163             :      * Currently a sync walk is active. Used to prevent re-entrant walking
     164             :      */
     165             :     ADJ_ATTR_SYNC_WALK_ACTIVE = 0,
     166             : 
     167             :     /**
     168             :      * When stacking midchains on a fib-entry extract the choice from the
     169             :      * load-balance returned based on an IP hash of the adj's rewrite
     170             :      */
     171             :     ADJ_ATTR_MIDCHAIN_IP_STACK,
     172             :     /**
     173             :      * If the midchain were to stack on its FIB entry a loop would form.
     174             :      */
     175             :     ADJ_ATTR_MIDCHAIN_LOOPED,
     176             :     /**
     177             :      * the fixup function is standard IP4o4 header
     178             :      */
     179             :     ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR,
     180             :     /**
     181             :      * the fixup function performs the flow hash
     182             :      * this means the flow hash is performed on the inner
     183             :      * header, where the entropy is higher.
     184             :      */
     185             :     ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH,
     186             : }  adj_attr_t;
     187             : 
     188             : #define ADJ_ATTR_NAMES {                                        \
     189             :     [ADJ_ATTR_SYNC_WALK_ACTIVE] = "walk-active",                \
     190             :     [ADJ_ATTR_MIDCHAIN_IP_STACK] = "midchain-ip-stack",         \
     191             :     [ADJ_ATTR_MIDCHAIN_LOOPED] = "midchain-looped",             \
     192             :     [ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR] = "midchain-ip4o4-hdr-fixup",   \
     193             :     [ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH] = "midchain-flow-hash",   \
     194             : }
     195             : 
     196             : #define FOR_EACH_ADJ_ATTR(_attr)                        \
     197             :     for (_attr = ADJ_ATTR_SYNC_WALK_ACTIVE;             \
     198             :          _attr <= ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH;    \
     199             :          _attr++)
     200             : 
     201             : /**
     202             :  * @brief Flags on an IP adjacency
     203             :  */
     204             : typedef enum adj_flags_t_
     205             : {
     206             :     ADJ_FLAG_NONE = 0,
     207             :     ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << ADJ_ATTR_SYNC_WALK_ACTIVE),
     208             :     ADJ_FLAG_MIDCHAIN_IP_STACK = (1 << ADJ_ATTR_MIDCHAIN_IP_STACK),
     209             :     ADJ_FLAG_MIDCHAIN_LOOPED = (1 << ADJ_ATTR_MIDCHAIN_LOOPED),
     210             :     ADJ_FLAG_MIDCHAIN_FIXUP_IP4O4_HDR = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_IP4O4_HDR),
     211             :     ADJ_FLAG_MIDCHAIN_FIXUP_FLOW_HASH = (1 << ADJ_ATTR_MIDCHAIN_FIXUP_FLOW_HASH),
     212             : }  __attribute__ ((packed)) adj_flags_t;
     213             : 
     214             : /**
     215             :  * @brief Format adjacency flags
     216             :  */
     217             : extern u8* format_adj_flags(u8 * s, va_list * args);
     218             : 
     219             : /**
     220             :  * @brief IP unicast adjacency.
     221             :  *  @note cache aligned.
     222             :  *
     223             :  * An adjacency is a representation of a peer on a particular link.
     224             :  */
     225             : typedef struct ip_adjacency_t_
     226             : {
     227             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
     228             : 
     229             :   /**
     230             :    * Linkage into the FIB node graph. First member since this type
     231             :    * has 8 byte alignment requirements.
     232             :    */
     233             :   fib_node_t ia_node;
     234             :   /**
     235             :    * feature [arc] config index
     236             :    */
     237             :   u32 ia_cfg_index;
     238             : 
     239             :   union
     240             :   {
     241             :     /**
     242             :      * IP_LOOKUP_NEXT_ARP/IP_LOOKUP_NEXT_REWRITE
     243             :      *
     244             :      * neighbour adjacency sub-type;
     245             :      */
     246             :     struct
     247             :     {
     248             :       ip46_address_t next_hop;
     249             :     } nbr;
     250             :       /**
     251             :        * IP_LOOKUP_NEXT_MIDCHAIN
     252             :        *
     253             :        * A nbr adj that is also recursive. Think tunnels.
     254             :        * A nbr adj can transition to be of type MIDCHAIN
     255             :        * so be sure to leave the two structs with the next_hop
     256             :        * fields aligned.
     257             :        */
     258             :     struct
     259             :     {
     260             :       /**
     261             :        * The recursive next-hop.
     262             :        *  This field MUST be at the same memory location as
     263             :        *   sub_type.nbr.next_hop
     264             :        */
     265             :       ip46_address_t next_hop;
     266             :       /**
     267             :        * The next DPO to use
     268             :        */
     269             :       dpo_id_t next_dpo;
     270             :       /**
     271             :        * A function to perform the post-rewrite fixup
     272             :        */
     273             :       adj_midchain_fixup_t fixup_func;
     274             :       /**
     275             :        * Fixup data passed back to the client in the fixup function
     276             :        */
     277             :       const void *fixup_data;
     278             :       /**
     279             :        * the FIB entry this midchain resolves through. required for recursive
     280             :        * loop detection.
     281             :        */
     282             :       fib_node_index_t fei;
     283             : 
     284             :       /** spare space */
     285             :       u8 __ia_midchain_pad[4];
     286             : 
     287             :     } midchain;
     288             :     /**
     289             :      * IP_LOOKUP_NEXT_GLEAN
     290             :      *
     291             :      * Glean the address to ARP for from the packet's destination.
     292             :      * Technically these aren't adjacencies, i.e. they are not a
     293             :      * representation of a peer. One day we might untangle this coupling
     294             :      * and use a new Glean DPO.
     295             :      */
     296             :     struct
     297             :     {
     298             :       fib_prefix_t rx_pfx;
     299             :     } glean;
     300             :   } sub_type;
     301             : 
     302             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline1);
     303             : 
     304             :   /** Rewrite in second and third cache lines */
     305             :   VNET_DECLARE_REWRITE;
     306             : 
     307             :   /**
     308             :    * more control plane members that do not fit on the first cacheline
     309             :    */
     310             :   CLIB_CACHE_LINE_ALIGN_MARK (cacheline3);
     311             : 
     312             :   /**
     313             :    * A sorted vector of delegates
     314             :    */
     315             :   struct adj_delegate_t_ *ia_delegates;
     316             : 
     317             :   /**
     318             :    * The VLIB node in which this adj is used to forward packets
     319             :    */
     320             :   u32 ia_node_index;
     321             : 
     322             :   /**
     323             :    * Next hop after ip4-lookup.
     324             :    *  This is not accessed in the rewrite nodes.
     325             :    * 1-bytes
     326             :    */
     327             :   ip_lookup_next_t lookup_next_index;
     328             : 
     329             :   /**
     330             :    * link/ether-type
     331             :    * 1 bytes
     332             :    */
     333             :   vnet_link_t ia_link;
     334             : 
     335             :   /**
     336             :    * The protocol of the neighbor/peer. i.e. the protocol with
     337             :    * which to interpret the 'next-hop' attributes of the sub-types.
     338             :    * 1-bytes
     339             :    */
     340             :   fib_protocol_t ia_nh_proto;
     341             : 
     342             :   /**
     343             :    * Flags on the adjacency
     344             :    * 1-bytes
     345             :    */
     346             :   adj_flags_t ia_flags;
     347             : 
     348             :   /**
     349             :    * Free space on the fourth cacheline (not used in the DP)
     350             :    */
     351             :   u8 __ia_pad[48];
     352             : } ip_adjacency_t;
     353             : 
     354             : STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline0) == 0),
     355             :                "IP adjacency cacheline 0 is not offset");
     356             : STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline1) ==
     357             :                 CLIB_CACHE_LINE_BYTES),
     358             :                "IP adjacency cacheline 1 is more than one cacheline size offset");
     359             : #if defined __x86_64__
     360             : STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, cacheline3) ==
     361             :                 3 * CLIB_CACHE_LINE_BYTES),
     362             :                "IP adjacency cacheline 3 is more than one cacheline size offset");
     363             : /* An adj fits into 4 cachelines on your average machine */
     364             : STATIC_ASSERT_SIZEOF (ip_adjacency_t, 4 * 64);
     365             : #endif
     366             : STATIC_ASSERT ((STRUCT_OFFSET_OF (ip_adjacency_t, sub_type.nbr.next_hop) ==
     367             :                 STRUCT_OFFSET_OF (ip_adjacency_t, sub_type.midchain.next_hop)),
     368             :                "IP adjacency nbr and midchain offsets don't match");
     369             : 
     370             : /**
     371             :  * @brief
     372             :  *   Take a reference counting lock on the adjacency
     373             :  */
     374             : extern void adj_lock(adj_index_t adj_index);
     375             : /**
     376             :  * @brief
     377             :  *   Release a reference counting lock on the adjacency
     378             :  */
     379             : extern void adj_unlock(adj_index_t adj_index);
     380             : 
     381             : /**
     382             :  * @brief
     383             :  *  Add a child dependent to an adjacency. The child will
     384             :  *  thus be informed via its registered back-walk function
     385             :  *  when the adjacency state changes.
     386             :  */
     387             : extern u32 adj_child_add(adj_index_t adj_index,
     388             :                          fib_node_type_t type,
     389             :                          fib_node_index_t child_index);
     390             : /**
     391             :  * @brief
     392             :  *  Remove a child dependent
     393             :  */
     394             : extern void adj_child_remove(adj_index_t adj_index,
     395             :                              u32 sibling_index);
     396             : 
     397             : /**
     398             :  * @brief Walk the Adjacencies on a given interface
     399             :  */
     400             : extern void adj_walk (u32 sw_if_index,
     401             :                       adj_walk_cb_t cb,
     402             :                       void *ctx);
     403             : 
     404             : /**
     405             :  * @brief Return the link type of the adjacency
     406             :  */
     407             : extern vnet_link_t adj_get_link_type (adj_index_t ai);
     408             : 
     409             : /**
     410             :  * @brief Return the sw interface index of the adjacency.
     411             :  */
     412             : extern u32 adj_get_sw_if_index (adj_index_t ai);
     413             : 
     414             : /**
     415             :  * @brief Return true if the adjacency is 'UP', i.e. can be used for forwarding.
     416             :  * 0 is down, !0 is up.
     417             :  */
     418             : extern int adj_is_up (adj_index_t ai);
     419             : 
     420             : /**
     421             :  * @brief Return the link type of the adjacency
     422             :  */
     423             : extern const u8* adj_get_rewrite (adj_index_t ai);
     424             : 
     425             : /**
     426             :  * @brief descend the FIB graph looking for loops
     427             :  *
     428             :  * @param ai
     429             :  *  The adj index to traverse
     430             :  *
     431             :  * @param entry_indicies)
     432             :  *  A pointer to a vector of FIB entries already visited.
     433             :  */
     434             : extern int adj_recursive_loop_detect (adj_index_t ai,
     435             :                                       fib_node_index_t **entry_indicies);
     436             : 
     437             : /**
     438             :  * @brief
     439             :  * The global adjacency pool. Exposed for fast/inline data-plane access
     440             :  */
     441             : extern ip_adjacency_t *adj_pool;
     442             : 
     443             : /**
     444             :  * @brief 
     445             :  * Adjacency packet counters
     446             :  */
     447             : extern vlib_combined_counter_main_t adjacency_counters;
     448             : 
     449             : /**
     450             :  * @brief Global Config for enabling per-adjacency counters
     451             :  * This is configurable because it comes with  a non-negligible
     452             :  * performance cost. */
     453             : extern int adj_per_adj_counters;
     454             : 
     455             : /**
     456             :  * @brief
     457             :  * Get a pointer to an adjacency object from its index
     458             :  */
     459             : static inline ip_adjacency_t *
     460    27286951 : adj_get (adj_index_t adj_index)
     461             : {
     462    27286951 :     return (pool_elt_at_index(adj_pool, adj_index));
     463             : }
     464             : 
     465             : static inline int
     466      376869 : adj_is_valid(adj_index_t adj_index)
     467             : {
     468      376869 :   return !(pool_is_free_index(adj_pool, adj_index));
     469             : }
     470             : 
     471             : /**
     472             :  * @brief Get the global configuration option for enabling per-adj counters
     473             :  */
     474             : static inline int 
     475      523513 : adj_are_counters_enabled (void)
     476             : {
     477      523513 :     return (adj_per_adj_counters);
     478             : }
     479             : 
     480             : #endif

Generated by: LCOV version 1.14