/* * Copyright (c) 2016 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. */ /** * An adjacency is a representation of an attached L3 peer. * * Adjacency Sub-types: * - neighbour: a representation of an attached L3 peer. * Key:{addr,interface,link/ether-type} * SHARED * - glean: used to drive ARP/ND for packets destined to a local sub-net. * 'glean' mean use the packet's destination address as the target * address in the ARP packet. * UNSHARED. Only one per-interface. * - midchain: a nighbour adj on a virtual/tunnel interface. * * The API to create and update the adjacency is very sub-type specific. This * is intentional as it encourages the user to carefully consider which adjacency * sub-type they are really using, and hence assign it data in the appropriate * sub-type space in the union of sub-types. This prevents the adj becoming a * disorganised dumping group for 'my features needs a u16 somewhere' data. It * is important to enforce this approach as space in the adjacency is a premium, * as we need it to fit in 1 cache line. * * the API is also based around an index to an ajdacency not a raw pointer. This * is so the user doesn't suffer the same limp inducing firearm injuries that * the author suffered as the adjacenices can realloc. */ #ifndef __ADJ_H__ #define __ADJ_H__ #include #include #include #include /** @brief Common (IP4/IP6) next index stored in adjacency. */ typedef enum { /** Adjacency to drop this packet. */ IP_LOOKUP_NEXT_DROP, /** Adjacency to punt this packet. */ IP_LOOKUP_NEXT_PUNT, /** This packet is for one of our own IP addresses. */ IP_LOOKUP_NEXT_LOCAL, /** This packet matches an "incomplete adjacency" and packets need to be passed to ARP to find rewrite string for this destination. */ IP_LOOKUP_NEXT_ARP, /** This packet matches an "interface route" and packets need to be passed to ARP to find rewrite string for this destination. */ IP_LOOKUP_NEXT_GLEAN, /** This packet is to be rewritten and forwarded to the next processing node. This is typically the output interface but might be another node for further output processing. */ IP_LOOKUP_NEXT_REWRITE, /** This packets follow a mid-chain adjacency */ IP_LOOKUP_NEXT_MIDCHAIN, /** This packets needs to go to ICMP error */ IP_LOOKUP_NEXT_ICMP_ERROR, /** Multicast Adjacency. */ IP_LOOKUP_NEXT_MCAST, /** Multicast Midchain Adjacency. An Adjacency for sending macst packets * on a tunnel/virtual interface */ IP_LOOKUP_NEXT_MCAST_MIDCHAIN, IP_LOOKUP_N_NEXT, } __attribute__ ((packed)) ip_lookup_next_t; typedef enum { IP4_LOOKUP_N_NEXT = IP_LOOKUP_N_NEXT, } ip4_lookup_next_t; typedef enum { /* Hop-by-hop header handling */ IP6_LOOKUP_NEXT_HOP_BY_HOP = IP_LOOKUP_N_NEXT, IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP, IP6_LOOKUP_NEXT_POP_HOP_BY_HOP, IP6_LOOKUP_N_NEXT, } ip6_lookup_next_t; #define IP4_LOOKUP_NEXT_NODES { \ [IP_LOOKUP_NEXT_DROP] = "ip4-drop", \ [IP_LOOKUP_NEXT_PUNT] = "ip4-punt", \ [IP_LOOKUP_NEXT_LOCAL] = "ip4-local", \ [IP_LOOKUP_NEXT_ARP] = "ip4-arp", \ [IP_LOOKUP_NEXT_GLEAN] = "ip4-glean", \ [IP_LOOKUP_NEXT_REWRITE] = "ip4-rewrite", \ [IP_LOOKUP_NEXT_MCAST] = "ip4-rewrite-mcast", \ [IP_LOOKUP_NEXT_MIDCHAIN] = "ip4-midchain", \ [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip4-mcast-midchain", \ [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip4-icmp-error", \ } #define IP6_LOOKUP_NEXT_NODES { \ [IP_LOOKUP_NEXT_DROP] = "ip6-drop", \ [IP_LOOKUP_NEXT_PUNT] = "ip6-punt", \ [IP_LOOKUP_NEXT_LOCAL] = "ip6-local", \ [IP_LOOKUP_NEXT_ARP] = "ip6-discover-neighbor", \ [IP_LOOKUP_NEXT_GLEAN] = "ip6-glean", \ [IP_LOOKUP_NEXT_REWRITE] = "ip6-rewrite", \ [IP_LOOKUP_NEXT_MCAST] = "ip6-rewrite-mcast", \ [IP_LOOKUP_NEXT_MIDCHAIN] = "ip6-midchain", \ [IP_LOOKUP_NEXT_MCAST_MIDCHAIN] = "ip6-mcast-midchain", \ [IP_LOOKUP_NEXT_ICMP_ERROR] = "ip6-icmp-error", \ [IP6_LOOKUP_NEXT_HOP_BY_HOP] = "ip6-hop-by-hop", \ [IP6_LOOKUP_NEXT_ADD_HOP_BY_HOP] = "ip6-add-hop-by-hop", \ [IP6_LOOKUP_NEXT_POP_HOP_BY_HOP] = "ip6-pop-hop-by-hop", \ } /** * Forward delcartion */ struct ip_adjacency_t_; /** * @brief A function type for post-rewrite fixups on midchain adjacency */ typedef void (*adj_midchain_fixup_t) (vlib_main_t * vm, struct ip_adjacency_t_ * adj, vlib_buffer_t * b0); /** * @brief Flags on an IP adjacency */ typedef enum ip_adjacency_flags_t_ { ADJ_FLAG_NONE = 0, /** * Currently a sync walk is active. Used to prevent re-entrant walking */ ADJ_FLAG_SYNC_WALK_ACTIVE = (1 << 0), /** * Packets TX through the midchain do not increment the interface * counters. This should be used when the adj is associated with an L2 * interface and that L2 interface is in a bridege domain. In that case * the packet will have traversed the interface's TX node, and hence have * been counted, before it traverses ths midchain */ ADJ_FLAG_MIDCHAIN_NO_COUNT = (1 << 1), } __attribute__ ((packed)) adj_flags_t; /** * @brief IP unicast adjacency. * @note cache aligned. * * An adjacency is a represenation of a peer on a particular link. */ typedef struct ip_adjacency_t_ { CLIB_CACHE_LINE_ALIGN_MARK (cacheline0); /** * Linkage into the FIB node grpah. First member since this type * has 8 byte alignment requirements. */ fib_node_t ia_node; /** * Next hop after ip4-lookup. * This is not accessed in the rewrite nodes. * 1-bytes */ ip_lookup_next_t lookup_next_index; /** * link/ether-type * 1 bytes */ vnet_link_t ia_link; /** * The p