diff options
Diffstat (limited to 'src/vnet/ip/ip6_hop_by_hop.h')
-rw-r--r-- | src/vnet/ip/ip6_hop_by_hop.h | 277 |
1 files changed, 277 insertions, 0 deletions
diff --git a/src/vnet/ip/ip6_hop_by_hop.h b/src/vnet/ip/ip6_hop_by_hop.h new file mode 100644 index 00000000..5f12f647 --- /dev/null +++ b/src/vnet/ip/ip6_hop_by_hop.h @@ -0,0 +1,277 @@ +/* + * 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. + */ +#ifndef __included_ip6_hop_by_hop_ioam_h__ +#define __included_ip6_hop_by_hop_ioam_h__ + +#include <vnet/ip/ip6_hop_by_hop_packet.h> +#include <vnet/ip/ip.h> + + +#define MAX_IP6_HBH_OPTION 256 + +/* To determine whether a node is decap MS bit is set */ +#define IOAM_DECAP_BIT 0x80000000 + +#define IOAM_DEAP_ENABLED(opaque_data) (opaque_data & IOAM_DECAP_BIT) + +#define IOAM_SET_DECAP(opaque_data) \ + (opaque_data |= IOAM_DECAP_BIT) + +#define IOAM_MASK_DECAP_BIT(x) (x & ~IOAM_DECAP_BIT) + +/* + * Stores the run time flow data of hbh options + */ +typedef struct +{ + u32 ctx[MAX_IP6_HBH_OPTION]; + u8 flow_name[64]; +} flow_data_t; + +typedef struct +{ + /* The current rewrite we're using */ + u8 *rewrite; + + /* Trace data processing callback */ + void *ioam_end_of_path_cb; + /* Configuration data */ + /* Adjacency */ + ip6_address_t adj; +#define IOAM_HBYH_ADD 0 +#define IOAM_HBYH_MOD 1 +#define IOAM_HBYH_POP 2 + u8 ioam_flag; + /* time scale transform. Joy. */ + u32 unix_time_0; + f64 vlib_time_0; + + + /* Trace option */ + u8 has_trace_option; + + /* Pot option */ + u8 has_pot_option; + + /* Per Packet Counter option */ + u8 has_seqno_option; + + /* Enabling analyis of iOAM data on decap node */ + u8 has_analyse_option; + + /* Array of function pointers to ADD and POP HBH option handling routines */ + u8 options_size[MAX_IP6_HBH_OPTION]; + int (*add_options[MAX_IP6_HBH_OPTION]) (u8 * rewrite_string, + u8 * rewrite_size); + int (*pop_options[MAX_IP6_HBH_OPTION]) (vlib_buffer_t * b, + ip6_header_t * ip, + ip6_hop_by_hop_option_t * opt); + int (*get_sizeof_options[MAX_IP6_HBH_OPTION]) (u32 * rewrite_size); + int (*config_handler[MAX_IP6_HBH_OPTION]) (void *data, u8 disable); + + /* Array of function pointers to handle hbh options being used with classifier */ + u32 (*flow_handler[MAX_IP6_HBH_OPTION]) (u32 flow_ctx, u8 add); + flow_data_t *flows; + + /* convenience */ + vlib_main_t *vlib_main; + vnet_main_t *vnet_main; +} ip6_hop_by_hop_ioam_main_t; + +extern ip6_hop_by_hop_ioam_main_t ip6_hop_by_hop_ioam_main; + +extern clib_error_t *ip6_ioam_enable (int has_trace_option, + int has_pot_option, + int has_seqno_option, + int has_analyse_option); + +extern int ip6_ioam_set_destination (ip6_address_t * addr, u32 mask_width, + u32 vrf_id, int is_add, int is_pop, + int is_none); + +extern clib_error_t *clear_ioam_rewrite_fn (void); + +static inline u8 +is_zero_ip4_address (ip4_address_t * a) +{ + return (a->as_u32 == 0); +} + +static inline void +copy_ip6_address (ip6_address_t * dst, ip6_address_t * src) +{ + dst->as_u64[0] = src->as_u64[0]; + dst->as_u64[1] = src->as_u64[1]; +} + +static inline void +set_zero_ip6_address (ip6_address_t * a) +{ + a->as_u64[0] = 0; + a->as_u64[1] = 0; +} + +static inline u8 +cmp_ip6_address (ip6_address_t * a1, ip6_address_t * a2) +{ + return ((a1->as_u64[0] == a2->as_u64[0]) + && (a1->as_u64[1] == a2->as_u64[1])); +} + +static inline u8 +is_zero_ip6_address (ip6_address_t * a) +{ + return ((a->as_u64[0] == 0) && (a->as_u64[1] == 0)); +} + +int ip6_hbh_add_register_option (u8 option, + u8 size, + int rewrite_options (u8 * rewrite_string, + u8 * size)); +int ip6_hbh_add_unregister_option (u8 option); + +int ip6_hbh_pop_register_option (u8 option, + int options (vlib_buffer_t * b, + ip6_header_t * ip, + ip6_hop_by_hop_option_t * opt)); +int ip6_hbh_pop_unregister_option (u8 option); + +int +ip6_hbh_get_sizeof_register_option (u8 option, + int get_sizeof_hdr_options (u32 * + rewrite_size)); + +int +ip6_ioam_set_rewrite (u8 ** rwp, int has_trace_option, + int has_pot_option, int has_seq_no); + +int +ip6_hbh_config_handler_register (u8 option, + int config_handler (void *data, u8 disable)); + +int ip6_hbh_config_handler_unregister (u8 option); + +int ip6_hbh_flow_handler_register (u8 option, + u32 ioam_flow_handler (u32 flow_ctx, + u8 add)); + +int ip6_hbh_flow_handler_unregister (u8 option); + +u8 *get_flow_name_from_flow_ctx (u32 flow_ctx); + +static inline flow_data_t * +get_flow (u32 index) +{ + flow_data_t *flow = NULL; + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + + if (pool_is_free_index (hm->flows, index)) + return NULL; + + flow = pool_elt_at_index (hm->flows, index); + return flow; +} + +static inline u32 +get_flow_data_from_flow_ctx (u32 flow_ctx, u8 option) +{ + flow_data_t *flow = NULL; + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + u32 index; + + index = IOAM_MASK_DECAP_BIT (flow_ctx); + //flow = pool_elt_at_index (hm->flows, index); + flow = &hm->flows[index]; + return (flow->ctx[option]); +} + +static inline u8 +is_seqno_enabled (void) +{ + return (ip6_hop_by_hop_ioam_main.has_seqno_option); +} + +int ip6_trace_profile_setup (); + +static inline u32 +ioam_flow_add (u8 encap, u8 * flow_name) +{ + ip6_hop_by_hop_ioam_main_t *hm = &ip6_hop_by_hop_ioam_main; + flow_data_t *flow = 0; + u32 index = 0; + u8 i; + + pool_get (hm->flows, flow); + memset (flow, 0, sizeof (flow_data_t)); + + index = flow - hm->flows; + strncpy ((char *) flow->flow_name, (char *) flow_name, 31); + + if (!encap) + IOAM_SET_DECAP (index); + + for (i = 0; i < 255; i++) + { + if (hm->flow_handler[i]) + flow->ctx[i] = hm->flow_handler[i] (index, 1); + } + return (index); +} + +always_inline ip6_hop_by_hop_option_t * +ip6_hbh_get_option (ip6_hop_by_hop_header_t * hbh0, u8 option_to_search) +{ + ip6_hop_by_hop_option_t *opt0, *limit0; + u8 type0; + + if (!hbh0) + return NULL; + + opt0 = (ip6_hop_by_hop_option_t *) (hbh0 + 1); + limit0 = (ip6_hop_by_hop_option_t *) + ((u8 *) hbh0 + ((hbh0->length + 1) << 3)); + + /* Scan the set of h-b-h options, process ones that we understand */ + while (opt0 < limit0) + { + type0 = opt0->type; + switch (type0) + { + case 0: /* Pad1 */ + opt0 = (ip6_hop_by_hop_option_t *) ((u8 *) opt0) + 1; + continue; + case 1: /* PadN */ + break; + default: + if (type0 == option_to_search) + return opt0; + break; + } + opt0 = + (ip6_hop_by_hop_option_t *) (((u8 *) opt0) + opt0->length + + sizeof (ip6_hop_by_hop_option_t)); + } + return NULL; +} + +#endif /* __included_ip6_hop_by_hop_ioam_h__ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ |