/* * 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. */ /** * @brief * A Data-Path Object is an object that represents actions that are * applied to packets are they are switched through VPP's data-path. * * The DPO can be considered to be like is a base class that is specialised * by other objects to provide concreate actions * * The VLIB graph nodes are graph of DPO types, the DPO graph is a graph of * instances. */ #ifndef __DPO_H__ #define __DPO_H__ #include /** * @brief An index for adjacencies. * Alas 'C' is not typesafe enough to b0rk when a u32 is used instead of * an index_t. However, for us humans, we can glean much more intent * from the declaration * foo barindex_t t); * than we can from * foo bar(u32 t); */ typedef u32 index_t; /** * @brief Invalid index - used when no index is known * blazoned capitals INVALID speak volumes where ~0 does not. */ #define INDEX_INVALID ((index_t)(~0)) /** * @brief Data path protocol. * Actions performed on packets in the data-plane can be described and represented * by protocol independent objects, i.e. ADJACENCY, but the spceifics actions * required during ADJACENCY processing can be protocol dependent. For example, * the adjacency rewrite node performs a ip4 checksum calculation, ip6 and MPLS * do not, all 3 perform a TTL decrement. The VLIB graph nodes are thus protocol * dependent, and thus each graph edge/arc is too. * When programming a DPO's next node arc from child to parent it is thus required * to know the parent's data-path protocol so the correct arc index can be used. */ typedef enum dpo_proto_t_ { DPO_PROTO_IP4 = 0, DPO_PROTO_IP6, DPO_PROTO_MPLS, DPO_PROTO_ETHERNET, DPO_PROTO_BIER, DPO_PROTO_NSH, } __attribute__((packed)) dpo_proto_t; #define DPO_PROTO_NUM ((dpo_proto_t)(DPO_PROTO_NSH+1)) #define DPO_PROTO_NONE ((dpo_proto_t)(DPO_PROTO_NUM+1)) #define DPO_PROTOS { \ [DPO_PROTO_IP4] = "ip4", \ [DPO_PROTO_IP6] = "ip6", \ [DPO_PROTO_ETHERNET] = "ethernet", \ [DPO_PROTO_MPLS] = "mpls", \ [DPO_PROTO_NSH] = "nsh", \ [DPO_PROTO_BIER] = "bier", \ } #define FOR_EACH_DPO_PROTO(_proto) \ for (_proto = DPO_PROTO_IP4; \ _proto <= DPO_PROTO_NSH; \ _proto++) /** * @brief Common types of data-path objects * New types can be dynamically added using dpo_register_new_type() */ typedef enum dpo_type_t_ { /** * A non-zero value first so we can spot unitialisation errors */ DPO_FIRST, DPO_DROP, DPO_IP_NULL, DPO_PUNT, /** * @brief load-balancing over a choice of [un]equal cost paths */ DPO_LOAD_BALANCE, DPO_REPLICATE, DPO_ADJACENCY, DPO_ADJACENCY_INCOMPLETE, DPO_ADJACENCY_MIDCHAIN, DPO_ADJACENCY_GLEAN, DPO_ADJACENCY_MCAST, DPO_ADJACENCY_MCAST_MIDCHAIN, DPO_RECEIVE, DPO_LOOKUP, DPO_LISP_CP, DPO_CLASSIFY, DPO_MPLS_DISPOSITION_PIPE, DPO_MPLS_DISPOSITION_UNIFORM, DPO_MFIB_ENTRY, DPO_INTERFACE_RX, DPO_INTERFACE_TX, DPO_DVR, DPO_L3_PROXY, DPO_BIER_TABLE, DPO_BIER_FMASK, DPO_BIER_IMP, DPO_BIER_DISP_TABLE, DPO_BIER_DISP_ENTRY, DPO_IP6_LL, DPO_LAST, } __attribute__((packed)) dpo_type_t; #define DPO_TYPE_NUM DPO_LAST #define DPO_TYPES { \ [DPO_FIRST] = "dpo-invalid", \ [DPO_DROP] = "dpo-drop", \ [DPO_IP_NULL] = "dpo-ip-null", \ [DPO_PUNT] = "dpo-punt", \ [DPO_ADJACENCY] = "dpo-adjacency", \ [DPO_ADJACENCY_INCOMPLETE] = "dpo-adjacency-incomplete", \ [DPO_ADJACENCY_MIDCHAIN] = "dpo-adjacency-midcahin", \ [DPO_ADJACENCY_GLEAN] = "dpo-glean", \ [DPO_ADJACENCY_MCAST] = "dpo-adj-mcast", \ [DPO_ADJACENCY_MCAST_MIDCHAIN] = "dpo-adj-mcast-midchain", \ [DPO_RECEIVE] = "dpo-receive", \ [DPO_LOOKUP] = "dpo-lookup", \ [DPO_LOAD_BALANCE] = "dpo-load-balance", \ [DPO_REPLICATE] = "dpo-replicate", \ [DPO_LISP_CP] = "dpo-lisp-cp", \ [DPO_CLASSIFY] = "dpo-classify", \ [DPO_MPLS_DISPOSITION_PIPE] = "dpo-mpls-diposition-pipe", \ [DPO_MPLS_DISPOSITION_UNIFORM] = "dpo-mpls-diposition-uniform", \ [DPO_MFIB_ENTRY] = "dpo-mfib-entry", \ [DPO_INTERFACE_RX] = "dpo-interface-rx", \ [DPO_INTERFACE_TX] = "dpo-interface-tx", \ [DPO_DVR] = "dpo-dvr", \ [DPO_L3_PROXY] = "dpo-l3-proxy", \ [DPO_BIER_TABLE] = "bier-table", \ [DPO_BIER_FMASK] = "bier-fmask", \ [DPO_BIER_IMP] = "bier-imposition", \ [DPO_BIER_DISP_ENTRY] = "bier-disp-entry", \ [DPO_BIER_DISP_TABLE] = "bier-disp-table", \ [DPO_IP6_LL] = "ip6-link-local", \ } /** * @brief The identity of a DPO is a combination of its type and its * instance number/index of objects of that type */ typedef struct dpo_id_t_ { /** * the type */ dpo_type_t dpoi_type; /** * the data-path protocol of the type. */ dpo_proto_t dpoi_proto; /** * The next VLIB node to follow. */ u16 dpoi_next_node; /** * the index of objects of that type */ index_t dpoi_index; } __attribute__ ((aligned(sizeof(u64)))) dpo_id_t; STATIC_ASSERT(sizeof(dpo_id_t) <= sizeof(u64), "DPO ID is greater than sizeof u64 "
set int ip address GigabitEthernet2/1/0 1.2.3.4/24
set int state GigabitEthernet2/1/0 up 

set int state GigabitEthernet2/2/0 up
cre sub GigabitEthernet2/2/0 1 dot1q 9 
set int state GigabitEthernet2/2/0.1 up
set int state tuntap-0 down

set int acl input GigabitEthernet2/1/0
set int acl output GigabitEthernet2/1/0
set int acl input GigabitEthernet2/2/0.1 
set int acl output GigabitEthernet2/2/0.1

set int l2 xc GigabitEthernet2/1/0   GigabitEthernet2/2/0.1
set int l2 xc GigabitEthernet2/2/0.1 GigabitEthernet2/1/0

clear error
clear run
clear int

packet-generator new {
  name xc
  limit 11
  no-recycle
  node ethernet-input 
  interface GigabitEthernet2/1/0
  size 98-98
  data { hex 0x00010203040500020406080a080045006402b46b96000100096978676265000500bf436973636f20494f5320536f6674776172652c2040160011000000010101cc000400000000001a00100000000100000000ffffffff }
}
d * in dpo_type_t enum * * @param vft * The virtual function table to register for the type. * * @param nodes * The string description of the per-protocol VLIB graph nodes. * * @return The new dpo_type_t */ extern dpo_type_t dpo_register_new_type(const dpo_vft_t *vft, const char * const * const * nodes); /** * @brief Return already stacked up next node index for a given * child_type/child_proto and parent_type/patent_proto. * The VLIB graph arc used is taken from the parent and child types * passed. * * @param child_type * Child DPO type. * * @param child_proto * Child DPO proto * * @param parent_type * Parent DPO type. * * @param parent_proto * Parent DPO proto * * @return The VLIB Graph node index */ extern u32 dpo_get_next_node_by_type_and_proto (dpo_type_t child_type, dpo_proto_t child_proto, dpo_type_t parent_type, dpo_proto_t parent_proto); #endif